/* ============================================================================
   SBT UI — the platform's own theme. Plain committed CSS, no build step, no
   third-party framework.

   FIVE themes. prime-light and prime-dark are this suite's own (#318): cool
   blue-grey neutrals, a sky accent, and a user-pickable accent hue driven by
   accent.js. prime-light is the DEFAULT for every user and every company.
   light / dark / aura are the original three, mirroring the SBT D-TAP app —
   underline top-nav links in light/dark, glass pill nav in aura, gray surfaces,
   indigo accent, emerald/amber/rose states; aura = the dark tokens plus the
   aura visual layer, mirroring dtap's dual `dark`+`aura` classes.

   Theme switch: html[data-sbt-theme="prime-light|prime-dark|light|dark|aura"].
   An unset attribute no longer follows the OS — the server resolves the theme
   (user setting -> company setting -> prime-light) and renders it onto <html>
   before first paint. The prefers-color-scheme block below is therefore only
   for the legacy `dark`/`aura` pair, and every theme carrying its own palette
   must be named in its :not() guards.
   ========================================================================== */

/* ---- font: Figtree (self-hosted, SIL OFL 1.1 — see fonts/OFL.txt) ---- */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('fonts/figtree-var.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 300 900;
  font-display: swap;
  src: url('fonts/figtree-var-latinext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Figtree';
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url('fonts/figtree-var-italic.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Figtree';
  font-style: italic;
  font-weight: 300 900;
  font-display: swap;
  src: url('fonts/figtree-var-italic-latinext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ---- tokens ----

   ⚠ EVERY token block below is also reachable through `.sbt-theme-scope`, which
   re-scopes a whole theme onto ONE ELEMENT and its subtree instead of the page.
   It exists for the theme picker's preview swatches: those carry a
   `data-sbt-theme` of their own, but every block here was keyed on `html[...]`,
   so the attribute matched nothing and all six swatches quietly rendered the
   theme already on screen — a picker that previewed only what you were already
   looking at. A declaration made ON an element beats one INHERITED from `html`
   whatever its specificity, which is what makes the re-scope work from inside
   any theme, `light` included, whose palette is this `:root`.
   ⛔ The scope class is opt-in on purpose: `[data-sbt-theme]` alone would hand
   a full palette to any element that ever carries the attribute. */
:root,
.sbt-theme-scope[data-sbt-theme="light"] {
  --sbt-bg: #f3f4f6;
  --sbt-surface: #ffffff;
  --sbt-surface-2: #f9fafb;
  --sbt-surface-3: #f3f4f6;
  --sbt-text: #111827;
  --sbt-text-2: #374151;
  --sbt-muted: #6b7280;
  --sbt-border: #e5e7eb;
  --sbt-border-2: #d1d5db;
  --sbt-accent: #4f46e5;
  --sbt-accent-strong: #4338ca;
  --sbt-accent-weak: #eef2ff;
  --sbt-accent-text: #4338ca;
  --sbt-accent-vivid: #4f46e5;   /* defined, NOT consumed outside prime (WO5-7) */
  --sbt-nav-active-border: #818cf8; /* indigo-400 (dtap light active underline) */
  /* Text that sits ON a solid fill. Defined in EVERY theme block, not only the
     prime ones: `var(--sbt-on-accent)` with no fallback would otherwise be
     invalid at computed-value time here, and `color` being an inherited
     property that means the label quietly inherits the surrounding text colour
     instead of failing loudly. Measured: white on #4f46e5 is 6.29. */
  --sbt-on-accent: #ffffff;
  /* White on the warning fill is only 3.19 here and 1.67 on the dark themes --
     the "internal note" badge was effectively unreadable. Black is 6.59. */
  --sbt-on-warning: #000000;
  --sbt-success: #059669;
  --sbt-success-weak: #ecfdf5;
  --sbt-warning: #d97706;
  --sbt-warning-weak: #fffbeb;
  --sbt-danger: #e11d48;
  --sbt-danger-weak: #fff1f2;
  --sbt-info: #0891b2;
  --sbt-info-weak: #ecfeff;
  /* chart series — CVD-validated categorical order; keep the order, never cycle */
  --sbt-series-1: #2a78d6;
  --sbt-series-2: #eb6834;
  --sbt-series-3: #1baf7a;
  --sbt-series-4: #eda100;
  --sbt-series-5: #e87ba4;
  --sbt-series-6: #008300;
  --sbt-series-7: #4a3aa7;
  --sbt-series-8: #e34948;
  --sbt-shadow: 0 1px 3px rgba(17, 24, 39, .08), 0 1px 2px rgba(17, 24, 39, .04);
  --sbt-shadow-lg: 0 10px 30px rgba(17, 24, 39, .18);
  --sbt-radius: 10px;
  --sbt-radius-sm: 8px;
  --sbt-font: 'Figtree', ui-sans-serif, system-ui, -apple-system, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --sbt-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
html[data-sbt-theme="dark"],
html[data-sbt-theme="aura"] { color-scheme: dark; }
html[data-sbt-theme="dark"],
html[data-sbt-theme="dark"] body { background: #030712; }
html[data-sbt-theme="dark"],
html[data-sbt-theme="aura"],
.sbt-theme-scope[data-sbt-theme="dark"],
.sbt-theme-scope[data-sbt-theme="aura"] {
  --sbt-bg: #030712;
  --sbt-surface: #111827;
  --sbt-surface-2: #1f2937;
  --sbt-surface-3: #273449;
  --sbt-text: #e5e7eb;
  --sbt-text-2: #d1d5db;
  --sbt-muted: #9ca3af;
  --sbt-border: #374151;
  --sbt-border-2: #4b5563;
  --sbt-accent: #6366f1;
  --sbt-accent-strong: #818cf8;
  --sbt-accent-weak: rgba(99, 102, 241, .16);
  --sbt-accent-text: #a5b4fc;
  --sbt-accent-vivid: #6366f1;   /* defined, NOT consumed outside prime (WO5-7) */
  --sbt-nav-active-border: #6366f1; /* indigo-500 (dtap dark active underline) */
  /* #372 -- the label on an accent fill is BLACK on these two themes. White on
     #6366f1 measures 4.47, a hair under AA, and WO5-1 leg 4 deliberately left
     it alone because moving it changes what a shipped theme looks like; that
     is now the ruled change. Black on the same fill measures 4.70 and passes,
     and it is the only step available without moving the accent itself, which
     feeds far more than labels. Black on #fbbf24 is 12.58. */
  --sbt-on-accent: #000000;
  --sbt-on-warning: #000000;
  --sbt-success: #34d399;
  --sbt-success-weak: rgba(16, 185, 129, .14);
  --sbt-warning: #fbbf24;
  --sbt-warning-weak: rgba(245, 158, 11, .14);
  --sbt-danger: #fb7185;
  --sbt-danger-weak: rgba(225, 29, 72, .16);
  --sbt-info: #22d3ee;
  --sbt-info-weak: rgba(8, 145, 178, .16);
  /* chart series — same hues re-stepped for the dark surface (validated) */
  --sbt-series-1: #3987e5;
  --sbt-series-2: #d95926;
  --sbt-series-3: #199e70;
  --sbt-series-4: #c98500;
  --sbt-series-5: #d55181;
  --sbt-series-6: #008300;
  --sbt-series-7: #9085e9;
  --sbt-series-8: #e66767;
  --sbt-shadow: 0 1px 3px rgba(0, 0, 0, .5);
  --sbt-shadow-lg: 0 10px 30px rgba(0, 0, 0, .6);
}
/* ⚠ These guards list every theme that must NOT inherit the dark tokens when the
   OS asks for dark. A theme missing from the :not() chain looks perfect on a
   light machine and silently turns dark on someone else's — the tokens below
   win purely by source order. `aura` was special-cased here for that reason and
   both prime themes now are too: prime-light because it is a light theme, and
   prime-dark because it carries its own dark palette rather than borrowing
   this one. Add any future theme here in the same breath as its token block. */
@media (prefers-color-scheme: dark) {
  html:not([data-sbt-theme="light"]):not([data-sbt-theme="prime-light"]):not([data-sbt-theme="prime-dark"]):not([data-sbt-theme="bluebell"]):not([data-sbt-theme="bluebell-dark"]):not([data-sbt-theme="fruits-light"]):not([data-sbt-theme="fruits-dark"]) { color-scheme: dark; }
  html:not([data-sbt-theme="light"]):not([data-sbt-theme="aura"]):not([data-sbt-theme="prime-light"]):not([data-sbt-theme="prime-dark"]):not([data-sbt-theme="bluebell"]):not([data-sbt-theme="bluebell-dark"]):not([data-sbt-theme="fruits-light"]):not([data-sbt-theme="fruits-dark"]),
  html:not([data-sbt-theme="light"]):not([data-sbt-theme="aura"]):not([data-sbt-theme="prime-light"]):not([data-sbt-theme="prime-dark"]):not([data-sbt-theme="bluebell"]):not([data-sbt-theme="bluebell-dark"]):not([data-sbt-theme="fruits-light"]):not([data-sbt-theme="fruits-dark"]) body { background: #030712; }
  html:not([data-sbt-theme="light"]):not([data-sbt-theme="prime-light"]):not([data-sbt-theme="prime-dark"]):not([data-sbt-theme="bluebell"]):not([data-sbt-theme="bluebell-dark"]):not([data-sbt-theme="fruits-light"]):not([data-sbt-theme="fruits-dark"]) {
    --sbt-bg: #030712;
    --sbt-surface: #111827;
    --sbt-surface-2: #1f2937;
    --sbt-surface-3: #273449;
    --sbt-text: #e5e7eb;
    --sbt-text-2: #d1d5db;
    --sbt-muted: #9ca3af;
    --sbt-border: #374151;
    --sbt-border-2: #4b5563;
    --sbt-accent: #6366f1;
    --sbt-accent-strong: #818cf8;
    --sbt-accent-weak: rgba(99, 102, 241, .16);
    --sbt-accent-text: #a5b4fc;
    --sbt-accent-vivid: #6366f1; /* defined, NOT consumed outside prime (WO5-7) */
    --sbt-nav-active-border: #6366f1;
    /* #372 -- same ruling as the attribute-stamped block above: black reads
       4.70 on #6366f1 where white read 4.47. Kept in step so a viewer whose OS
       is dark and who has never picked a theme sees what "dark" sees. */
    --sbt-on-accent: #000000;
    --sbt-on-warning: #000000;
    --sbt-success: #34d399;
    --sbt-success-weak: rgba(16, 185, 129, .14);
    --sbt-warning: #fbbf24;
    --sbt-warning-weak: rgba(245, 158, 11, .14);
    --sbt-danger: #fb7185;
    --sbt-danger-weak: rgba(225, 29, 72, .16);
    --sbt-info: #22d3ee;
    --sbt-info-weak: rgba(8, 145, 178, .16);
    --sbt-series-1: #3987e5;
    --sbt-series-2: #d95926;
    --sbt-series-3: #199e70;
    --sbt-series-4: #c98500;
    --sbt-series-5: #d55181;
    --sbt-series-6: #008300;
    --sbt-series-7: #9085e9;
    --sbt-series-8: #e66767;
    --sbt-shadow: 0 1px 3px rgba(0, 0, 0, .5);
    --sbt-shadow-lg: 0 10px 30px rgba(0, 0, 0, .6);
  }
}


/* ==========================================================================
   prime-light / prime-dark — the default themes (#318).

   Derived, not eyeballed: every value below was computed in OKLCH and then
   proved against WCAG 2.1 relative luminance on the surfaces it actually sits
   on, not just on white. The generator is ~/claude/kotak_handoff/s138_palette.py
   and public/sbt-ui/accent.js is its port — the user's colour picker runs the
   same maths, so a picked hue lands where these did.

   Two findings shaped the whole palette and are worth keeping written down:

   1. No blue in the sky family carries white text at its 600 step (measured
      3.87-4.01 across six seeds), so the white-text-safe solid is the 700 step.
      The sky identity lives in the tints, the bright non-text accents and the
      surfaces — never in the button fill.
   2. A muted grey validated only against white silently fails on tinted
      surfaces. slate-500 #64748b is 4.76 on white but 4.27 on --sbt-surface-2,
      which is exactly where muted text is most used. --sbt-muted is #5b6b80,
      and every pair below was measured on surface, bg AND surface-2.
   ========================================================================== */
html[data-sbt-theme="prime-light"] { color-scheme: light; }
html[data-sbt-theme="prime-light"],
html[data-sbt-theme="prime-light"] body { background: #f4f7fb; }
html[data-sbt-theme="prime-light"],
.sbt-theme-scope[data-sbt-theme="prime-light"] {
  /* neutrals — cool, faintly blue, to sit under a sky accent.
     bg -> surface is a 1.075 lift, so white cards genuinely rise off the
     ground instead of dissolving into a flat grey wash. */
  --sbt-bg: #f4f7fb;
  --sbt-surface: #ffffff;
  --sbt-surface-2: #eef3f9;
  --sbt-surface-3: #e2eaf4;
  /* text ramp. text 17.50/16.29/15.69 · text-2 10.06/9.36 · muted 5.44/5.06/4.88
     on surface/bg/surface-2. ⚠ muted on --sbt-surface-3 is 4.48, a hair under —
     surface-3 is an avatar/inset fill and must never carry muted body text; use
     --sbt-text-2 there. */
  --sbt-text: #0d1a2b;
  --sbt-text-2: #31435c;
  --sbt-muted: #5b6b80;
  /* the fourth step of the ramp. ⚠ NON-TEXT ONLY — icon strokes, dividers,
     disabled glyphs (3.56 on surface, clears SC 1.4.11's 3:1). Nothing in this
     app is "large text": 14pt-bold is 18.66px and 18pt is 24px, so timestamps
     (12px), previews (14px) and sender names (15px) all need the full 4.5:1 and
     must use --sbt-muted. There is no room for a lighter text step. */
  --sbt-faint: #7c899a;
  --sbt-border: #dde5f0;
  --sbt-border-2: #c3d0e0;
  /* sky ramp, seed #0ea5e9. 700 is the solid because 600 cannot carry white. */
  --sbt-accent: #006fa0;         /* 700 · white on it 5.55 */
  --sbt-accent-strong: #005981;  /* 800 · white on it 7.65 (hover) */
  --sbt-accent-weak: #f0f9ff;    /* 50  · tint fills · accent text on it 5.21 */
  --sbt-accent-tint: #dbf0ff;    /* 100 · stronger tint · accent text on it 4.74 */
  --sbt-accent-text: #006fa0;    /* 700 · 5.55 on surface */
  --sbt-accent-bright: #00a5ea;  /* 500 · rails, rings, dots — 2.77 on white, so
                                    decorative only: never text, never state
                                    carried alone, never a fill behind a label */
  --sbt-accent-vivid: #0d9ce0;   /* WO5-7 (§14b) · the brightest sky that still
                                    clears SC 1.4.11's 3:1 non-text floor on
                                    white (3.07). MAY carry state — unread dots,
                                    active indicator bars, rings, rail markers.
                                    ⛔ NEVER a fill behind white text: white on
                                    it is 3.07, and the seed #0ea5e9 is 2.77. */
  --sbt-on-accent: #ffffff;      /* what the accent engine recomputes per hue */
  --sbt-nav-active-border: #00a5ea;
  /* status — the stock light steps all fail AA on these neutrals (success 3.77,
     warning 3.19, danger 4.70, info 3.68 on surface), so prime uses darker
     steps: 5.48 / 5.38 / 5.64 / 5.72 on surface and >=4.82 on surface-2. */
  --sbt-success: #047857;
  --sbt-success-weak: #ecfdf5;
  --sbt-warning: #a2570a;        /* white on it 5.38, so the badge keeps white */
  --sbt-on-warning: #ffffff;
  --sbt-warning-weak: #fffbeb;
  --sbt-danger: #c81e42;
  --sbt-danger-weak: #fff1f2;
  --sbt-info: #0e6f8c;
  --sbt-info-weak: #ecfeff;
  /* chart series — the CVD-validated light order, unchanged. sbt-dash.js:35-45
     reads these from computed style and falls back to hardcoded hexes if a
     theme omits them, so all eight must be present or charts silently drift. */
  --sbt-series-1: #2a78d6;
  --sbt-series-2: #eb6834;
  --sbt-series-3: #1baf7a;
  --sbt-series-4: #eda100;
  --sbt-series-5: #e87ba4;
  --sbt-series-6: #008300;
  --sbt-series-7: #4a3aa7;
  --sbt-series-8: #e34948;
  /* elevation is RING-FIRST: the 1px ring is what makes a panel read as
     foreground, and the blur only softens it. Every shipping design system
     measured for this (Radix, Geist, Superhuman, Campsite) leads with a ring at
     4-10% black and keeps the resting blur at 3-6% alpha. Stock Tailwind's 10%
     shadow is heavier than any of them — which is precisely why default cards
     read "template-y". ⚠ forced-colors mode drops box-shadow entirely, so
     anything relying on this for separation also needs a border there. */
  --sbt-shadow: 0 0 0 1px rgba(13, 26, 43, .06), 0 1px 2px rgba(13, 26, 43, .04),
    0 2px 6px rgba(13, 26, 43, .04);
  --sbt-shadow-lg: 0 0 0 1px rgba(13, 26, 43, .07), 0 8px 24px rgba(13, 26, 43, .10),
    0 2px 6px rgba(13, 26, 43, .05);
}

/* prime-dark — the sibling. The user asked only for a light theme; without a
   dark partner a dark-preferring user loses the colour picker entirely and the
   theme cycle strands them. Same sky family, same engine, re-stepped: the solid
   is the brightest sky that still carries white text (5.45) while keeping 3:1
   against its own surface, and hover goes brighter rather than darker. */
html[data-sbt-theme="prime-dark"] { color-scheme: dark; }
html[data-sbt-theme="prime-dark"],
html[data-sbt-theme="prime-dark"] body { background: #0b1118; }
html[data-sbt-theme="prime-dark"],
.sbt-theme-scope[data-sbt-theme="prime-dark"] {
  --sbt-bg: #0b1118;
  --sbt-surface: #181e26;
  --sbt-surface-2: #222831;
  --sbt-surface-3: #2e353f;
  /* text 16.54/14.62/12.94 · text-2 11.85/10.48/9.27 · muted 7.25/6.41/5.67
     on bg/surface/surface-2. muted on surface-3 is 4.73, so it holds here. */
  --sbt-text: #ebf0f5;
  --sbt-text-2: #c7cdd5;
  --sbt-muted: #97a1af;
  --sbt-faint: #687380;          /* non-text only — 3.48 on surface */
  --sbt-border: #2d333c;
  --sbt-border-2: #424a55;
  --sbt-accent: #1d709c;         /* white on it 5.45 · 3.07 against surface */
  --sbt-accent-strong: #217aaa;  /* hover, brighter · white on it 4.74 */
  --sbt-accent-weak: rgba(45, 159, 219, .16);
  --sbt-accent-tint: rgba(45, 159, 219, .26);
  --sbt-accent-text: #48b8f7;    /* 7.56 on surface */
  --sbt-accent-bright: #48b8f7;
  --sbt-accent-vivid: #48b8f7;   /* 7.56 on prime-dark surface — same role (WO5-7) */
  --sbt-on-accent: #ffffff;
  --sbt-nav-active-border: #48b8f7;
  /* the stock dark status steps all clear AA on these neutrals (5.51-11.36) */
  --sbt-success: #34d399;
  --sbt-success-weak: rgba(16, 185, 129, .14);
  --sbt-warning: #fbbf24;        /* white on it is 1.67 -- the badge takes black */
  --sbt-on-warning: #000000;
  --sbt-warning-weak: rgba(245, 158, 11, .14);
  --sbt-danger: #fb7185;
  --sbt-danger-weak: rgba(225, 29, 72, .16);
  --sbt-info: #22d3ee;
  --sbt-info-weak: rgba(8, 145, 178, .16);
  --sbt-series-1: #3987e5;
  --sbt-series-2: #d95926;
  --sbt-series-3: #199e70;
  --sbt-series-4: #c98500;
  --sbt-series-5: #d55181;
  --sbt-series-6: #008300;
  --sbt-series-7: #9085e9;
  --sbt-series-8: #e66767;
  --sbt-shadow: 0 0 0 1px rgba(0, 0, 0, .55), 0 1px 3px rgba(0, 0, 0, .45);
  --sbt-shadow-lg: 0 0 0 1px rgba(0, 0, 0, .6), 0 12px 32px rgba(0, 0, 0, .55);
}

/* ==========================================================================
   BLUEBELL — the soft theme. A light palette built from pastel tints on a
   periwinkle ground, for people who find prime's contrast clinical and the
   legacy light theme flat.

   WHERE IT CAME FROM. The reference was a consumer security app whose screens
   read as friendly without reading as a toy. Measured off its own screenshots,
   the trick is not that it is pastel: its accent is a LOUD #006fff, and the
   softness is carried entirely by pale tint chips behind small icons —
   #e1f3fa baby blue, #f6f2ff baby lavender, #f1fff8 baby mint — floating on
   generous white. Pastel where a colour is DECORATIVE, confident where a
   colour carries MEANING.

   That split is the whole design, and it is also what makes a pastel theme
   survive this app's contrast rules. Nothing here is "large text" (§ the
   --sbt-faint note in prime-light), so every label needs the full 4.5:1; a
   theme that were pastel all the way through could not carry a single word.
   So the pastels live in the -weak/-tint fills and the surfaces, and every
   token that carries text is a deepened step of the same hue.

   NOT a recolour of prime-light. Prime is a SKY theme — cyan-leaning, cool,
   its neutrals faintly blue. Bluebell is a PERIWINKLE theme: the neutrals are
   violet-leaning (#1a1b3d ink rather than #0d1a2b), the ground is lilac-white
   rather than blue-grey, and the accent is an indigo-blue at the hue where
   blue and violet meet — which is where the reference's two brand colours,
   its #006fff blue and its #726fdb violet, actually sit together.

   MEASURED, not asserted. Every ratio below was computed, and Bluebell clears
   the two floors prime-light has to carry a caveat for:
     · --sbt-muted holds 4.5:1 on ALL FOUR grounds including --sbt-surface-3
       (4.99). Prime-light is 4.48 there and has to warn callers off it.
     · --sbt-faint clears the 3:1 non-text floor on all four (3.76/3.49/3.31/
       3.03). Prime-light documents 3.56 on surface alone.
   ⚠ --sbt-faint is still NON-TEXT ONLY. Clearing 3:1 makes it legal for icon
   strokes and dividers, not for a timestamp.

   The chart series are the CVD-validated light order, byte-for-byte. They are
   chosen for colour-vision-deficiency separation, which is a property of the
   set and not of this palette, and re-tinting them to match the theme would
   throw that away for a decoration nobody asked for. sbt-dash.js:35-45 reads
   all eight from computed style, so all eight must be present.
   ========================================================================== */
html[data-sbt-theme="bluebell"] { color-scheme: light; }
html[data-sbt-theme="bluebell"],
html[data-sbt-theme="bluebell"] body { background: #f5f6fe; }
html[data-sbt-theme="bluebell"],
.sbt-theme-scope[data-sbt-theme="bluebell"] {
  /* neutrals — violet-leaning, so white cards read as warm-cool white against
     a lilac ground rather than as a grey hole. bg -> surface is a 1.08 lift,
     the same separation prime uses, so a card still visibly rises. */
  --sbt-bg: #f5f6fe;
  --sbt-surface: #ffffff;
  --sbt-surface-2: #eef0fc;
  --sbt-surface-3: #e1e6fa;
  /* text ramp, on surface/bg/surface-2/surface-3:
     text 16.56/15.37/14.59/13.33 · text-2 9.87/9.16/8.69/7.94
     muted 6.20/5.76/5.47/4.99 — clears 4.5 on all four, surface-3 included. */
  --sbt-text: #1a1b3d;
  --sbt-text-2: #3c3f6e;
  --sbt-muted: #5b5e85;
  /* the fourth step. ⚠ NON-TEXT ONLY — icon strokes, dividers, disabled
     glyphs. 3.76/3.49/3.31/3.03, so it clears SC 1.4.11's 3:1 on every ground
     this theme has; that still does not make it a text colour. */
  --sbt-faint: #7e81a7;
  --sbt-border: #e4e6f6;
  --sbt-border-2: #cbcfec;
  /* periwinkle ramp. Same rule prime found the hard way: no blue-violet at its
     600 step carries white, so the solid is the deepened step and the softness
     lives in the tints. */
  --sbt-accent: #4f5bd5;         /* white on it 5.54 */
  --sbt-accent-strong: #3f4abb;  /* white on it 7.22 (hover) */
  --sbt-accent-weak: #f0f2fe;    /* the baby-blue chip · accent text on it 4.97 */
  --sbt-accent-tint: #e4e8fe;    /* stronger chip · accent text on it 4.56 */
  --sbt-accent-text: #4f5bd5;    /* 5.54 on surface, 4.88 on surface-2 */
  --sbt-accent-bright: #8fa0f5;  /* rails, rings, dots — 2.47 on white, so
                                    decorative only: never text, never state
                                    carried alone, never a fill behind a label */
  --sbt-accent-vivid: #7385f0;   /* the brightest periwinkle still clearing the
                                    3:1 non-text floor on white (3.31). MAY
                                    carry state — unread dots, indicator bars,
                                    rings. ⛔ NEVER a fill behind white text. */
  --sbt-on-accent: #ffffff;
  --sbt-nav-active-border: #7385f0;
  /* status — pastel fills, deepened solids. Solids measured on surface / bg /
     surface-2 / their own -weak fill, and each also carries white at >=5.33,
     so a solid badge keeps a white label whichever way it is used. */
  --sbt-success: #0e7a57;        /* 5.33/4.95/4.70/4.95 · white on it 5.33 */
  --sbt-success-weak: #e8fbf2;   /* baby mint */
  --sbt-warning: #99590f;        /* 5.54/5.14/4.88/5.13 · white on it 5.54 */
  --sbt-on-warning: #ffffff;
  --sbt-warning-weak: #fff5e6;   /* baby apricot */
  --sbt-danger: #c22a50;         /* 5.61/5.21/4.95/5.05 · white on it 5.61 */
  --sbt-danger-weak: #ffeff3;    /* baby rose */
  --sbt-info: #1a6d95;           /* 5.73/5.32/5.05/5.20 · white on it 5.73 */
  --sbt-info-weak: #e9f6fd;      /* baby sky */
  /* chart series — the CVD-validated light order, unchanged and complete. */
  --sbt-series-1: #2a78d6;
  --sbt-series-2: #eb6834;
  --sbt-series-3: #1baf7a;
  --sbt-series-4: #eda100;
  --sbt-series-5: #e87ba4;
  --sbt-series-6: #008300;
  --sbt-series-7: #4a3aa7;
  --sbt-series-8: #e34948;
  /* elevation is RING-FIRST, like prime, but the ring is tinted with the ink
     (#1a1b3d) rather than black: a neutral-black ring over a lilac ground
     reads as a dirty edge. Alphas are prime's, which are already at the light
     end of what shipping systems use. */
  --sbt-shadow: 0 0 0 1px rgba(26, 27, 61, .06), 0 1px 2px rgba(26, 27, 61, .04),
    0 2px 6px rgba(26, 27, 61, .04);
  --sbt-shadow-lg: 0 0 0 1px rgba(26, 27, 61, .07), 0 8px 24px rgba(26, 27, 61, .10),
    0 2px 6px rgba(26, 27, 61, .05);
}

/* ==========================================================================
   BLUEBELL DARK — bluebell's sibling, added by prime-dark's own rule: without
   a dark partner, a dark-preferring user who wants the periwinkle family is
   stranded by the theme cycle. Same family, same engine, re-stepped for a
   night ground: the neutrals are the bluebell ink (#1a1b3d) deepened into
   grounds rather than used as text, the pastels become low-alpha tints (a
   pastel FILL on a dark ground is paint, not light, so the -weak chips are
   alpha steps of the vivid hue), and every token that carries text is a
   brightened step of the same periwinkle.

   MEASURED, not asserted — on bg / surface / surface-2 / surface-3:
     · text 15.69/13.83/11.92/9.96 · text-2 11.51/10.14/8.74/7.30
     · muted 7.19/6.34/5.47/4.57 — clears 4.5:1 on ALL FOUR grounds,
       surface-3 included, keeping the floor bluebell holds in the light.
     · faint 4.84/4.27/3.68/3.07 — clears the 3:1 non-text floor on all four.
       ⚠ NON-TEXT ONLY, same as everywhere: icon strokes, dividers, disabled
       glyphs. Clearing 3:1 does not make it a timestamp colour.
   The solid follows prime-dark's hard-won rule: the deepest periwinkle that
   still reads as a button on the surface (3.22 against it) while carrying
   white at 4.92, and hover goes BRIGHTER, not darker (white on it 4.56).

   The chart series are the CVD-validated dark order, byte-for-byte from
   prime-dark. They are chosen for colour-vision-deficiency separation, which
   is a property of the set and not of the palette, and sbt-dash.js:35-45
   reads all eight from computed style, so all eight must be present.
   ========================================================================== */
html[data-sbt-theme="bluebell-dark"] { color-scheme: dark; }
html[data-sbt-theme="bluebell-dark"],
html[data-sbt-theme="bluebell-dark"] body { background: #12142f; }
html[data-sbt-theme="bluebell-dark"],
.sbt-theme-scope[data-sbt-theme="bluebell-dark"] {
  /* neutrals — the bluebell ink family as grounds: violet-leaning night, not
     neutral black, so cards rise as warm-dark lilac rather than grey slabs.
     bg -> surface is the same visible lift prime-dark uses. */
  --sbt-bg: #12142f;
  --sbt-surface: #1c1f42;
  --sbt-surface-2: #262a52;
  --sbt-surface-3: #313663;
  /* text ramp — measured values in the header comment. */
  --sbt-text: #eceffb;
  --sbt-text-2: #c9cdec;
  --sbt-muted: #9ba1cf;
  --sbt-faint: #7b81b5;          /* non-text only — 3.07 on surface-3 */
  --sbt-border: #2b2f59;
  --sbt-border-2: #454b82;
  /* periwinkle ramp, re-stepped for dark. */
  --sbt-accent: #5563e2;         /* white on it 4.92 · 3.22 against surface */
  --sbt-accent-strong: #5b69e6;  /* hover, brighter · white on it 4.56 */
  --sbt-accent-weak: rgba(139, 155, 247, .16);
  --sbt-accent-tint: rgba(139, 155, 247, .26);
  --sbt-accent-text: #a3b1fb;    /* 7.73 on surface, 8.78 on bg */
  --sbt-accent-bright: #a9b6fc;  /* rails, rings, dots — 8.14 on surface */
  --sbt-accent-vivid: #8b9bf7;   /* state-carrier — 6.14 on surface (WO5-7) */
  --sbt-on-accent: #ffffff;
  --sbt-nav-active-border: #8b9bf7;
  /* status — the baby-tint family carried to night: bright steps that clear
     AA as text on bg/surface/surface-2 (success 9.69/8.54/7.37 · warning
     10.70/9.43/8.13 · danger 7.30/6.43/5.55 · info 9.64/8.50/7.33), with the
     pastel softness moved into the alpha fills. */
  --sbt-success: #3bd6a0;        /* night mint */
  --sbt-success-weak: rgba(59, 214, 160, .14);
  --sbt-warning: #f5bf5b;        /* night apricot · white on it is 1.55 — the
                                    badge takes black (12.49) */
  --sbt-on-warning: #000000;
  --sbt-warning-weak: rgba(245, 191, 91, .14);
  --sbt-danger: #fb7d9c;         /* night rose */
  --sbt-danger-weak: rgba(251, 125, 156, .16);
  --sbt-info: #43cdf2;           /* night sky */
  --sbt-info-weak: rgba(67, 205, 242, .16);
  /* chart series — the CVD-validated dark order, unchanged and complete. */
  --sbt-series-1: #3987e5;
  --sbt-series-2: #d95926;
  --sbt-series-3: #199e70;
  --sbt-series-4: #c98500;
  --sbt-series-5: #d55181;
  --sbt-series-6: #008300;
  --sbt-series-7: #9085e9;
  --sbt-series-8: #e66767;
  /* elevation — ring-first at prime-dark's alphas, but the ring is the ink's
     own black-violet (#07 08 18) rather than neutral black: a neutral ring
     over a violet ground reads as a dirty edge, exactly the lesson bluebell
     learned in the light. */
  --sbt-shadow: 0 0 0 1px rgba(7, 8, 24, .55), 0 1px 3px rgba(7, 8, 24, .45);
  --sbt-shadow-lg: 0 0 0 1px rgba(7, 8, 24, .6), 0 12px 32px rgba(7, 8, 24, .55);
}

/* ---- aura base: cosmic gradient ground (ported from dtap .aura) ---- */
html[data-sbt-theme="aura"] {
  background: linear-gradient(to bottom right, #020617, #0f172a, #1e1b4b) !important;
}
/* aura's identity is the ground itself, not a --sbt-bg value, so a swatch that
   painted only the token would preview the one theme dishonestly. */
.sbt-theme-scope[data-sbt-theme="aura"] {
  background: linear-gradient(to bottom right, #020617, #0f172a, #1e1b4b) !important;
}
html[data-sbt-theme="aura"] body.sbt-body { background: transparent; }

/* ---- base ---- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body.sbt-body {
  margin: 0;
  font-family: var(--sbt-font);
  font-size: .9375rem;
  line-height: 1.5;
  color: var(--sbt-text);
  background: var(--sbt-bg);
  min-height: 100vh;
}
.sbt-body h1, .sbt-body h2, .sbt-body h3, .sbt-body h4, .sbt-body h5, .sbt-body h6 {
  margin: 0 0 .5rem; font-weight: 600; line-height: 1.3; color: var(--sbt-text);
}
.sbt-body h4 { font-size: 1.25rem; }
.sbt-body h5 { font-size: 1.05rem; }
.sbt-body p { margin: 0 0 .75rem; }
.sbt-body a { color: var(--sbt-accent-text); text-decoration: none; }
.sbt-body a:hover { text-decoration: underline; }
.sbt-body ::placeholder { color: var(--sbt-muted); opacity: .8; }
/* Long unbroken tokens — an API key, a URL, a JSON blob — must never widen the
   page. An inline <code> offers no wrap opportunity inside a long token, and a
   <pre> that already sets overflow-x:auto still cannot shrink while it is a
   flex item, because a flex item's default min-width:auto refuses to go below
   its content width. Together those overflowed /settings/api-keys/docs by 119px
   at 390px — in every one of the five themes, so these are base rules and not
   prime-scoped. `overflow-wrap` has no effect inside <pre> (white-space:pre
   creates no soft wrap opportunities), so code blocks keep scrolling instead. */
.sbt-body code { overflow-wrap: anywhere; }
.sbt-body pre { max-width: 100%; min-width: 0; overflow-x: auto; }

/* ---- aura background effects (rendered always, visible only under aura;
        ported verbatim from dtap app.css) ---- */
.sbt-aura-fx { display: none; }
html[data-sbt-theme="aura"] .sbt-aura-fx {
  display: block; position: fixed; inset: 0; z-index: 0;
  pointer-events: none; overflow: hidden;
}
.aura-geometric {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(30deg, rgba(99,102,241,0.02) 12%, transparent 12.5%, transparent 87%, rgba(99,102,241,0.02) 87.5%),
    linear-gradient(150deg, rgba(99,102,241,0.02) 12%, transparent 12.5%, transparent 87%, rgba(99,102,241,0.02) 87.5%),
    linear-gradient(30deg, rgba(99,102,241,0.02) 12%, transparent 12.5%, transparent 87%, rgba(99,102,241,0.02) 87.5%),
    linear-gradient(150deg, rgba(99,102,241,0.02) 12%, transparent 12.5%, transparent 87%, rgba(99,102,241,0.02) 87.5%);
  background-size: 80px 140px;
  background-position: 0 0, 0 0, 40px 70px, 40px 70px;
}
.aura-grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(99,102,241,0.015) 1px, transparent 1px),
    linear-gradient(90deg, rgba(99,102,241,0.015) 1px, transparent 1px);
  background-size: 64px 64px;
}
.aura-noise {
  position: absolute; inset: 0; opacity: 0.02;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat; background-size: 256px 256px;
}
.aura-orb {
  position: absolute; border-radius: 9999px; filter: blur(48px);
  animation: aura-pulse-glow 8s ease-in-out infinite;
}
.aura-orb-1 {
  top: 0; left: 25%; width: 300px; height: 300px;
  background: linear-gradient(to bottom right, rgba(139,92,246,0.1), rgba(99,102,241,0.1));
}
.aura-orb-2 {
  bottom: 0; right: 25%; width: 250px; height: 250px;
  background: linear-gradient(to bottom right, rgba(37,99,235,0.1), rgba(6,182,212,0.1));
}
.aura-orb-3 {
  top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 400px; height: 400px;
  background: linear-gradient(to bottom right, rgba(168,85,247,0.05), rgba(236,72,153,0.05));
}
.aura-delay-1 { animation-delay: -1s; }
.aura-delay-2 { animation-delay: -2s; }
.aura-delay-4 { animation-delay: -4s; }

/* Everything above the fx layer */
.sbt-nav, .sbt-main, .sbt-toasts { position: relative; z-index: 1; }

/* ---- icons (inline SVG sprite) ---- */
.si {
  width: 1.15em; height: 1.15em; stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  vertical-align: -.2em; flex: 0 0 auto;
}
.si-lg { width: 1.5em; height: 1.5em; }
.si-xl { width: 2.4em; height: 2.4em; }

/* ---- top navigation (dtap structure: h-16 bar; light/dark = Breeze underline
        links; aura = glass bar + pill links) ---- */
.sbt-nav {
  background: var(--sbt-surface);
  border-bottom: 1px solid var(--sbt-border);
  position: sticky; top: 0; z-index: 900;
}
.sbt-nav-inner {
  max-width: 1400px; margin: 0 auto; padding: 0 1.25rem;
  display: flex; align-items: stretch; gap: .25rem; min-height: 64px; flex-wrap: wrap;
}
.sbt-brand {
  display: flex; align-items: center; gap: .55rem; margin-right: 1.75rem;
  font-weight: 700; font-size: 1.05rem; color: var(--sbt-text) !important;
  text-decoration: none !important;
}
.sbt-brand-mark {
  width: 30px; height: 30px; border-radius: 9px; display: inline-flex;
  align-items: center; justify-content: center; color: #fff;
  /* a11y (A-15): an 8% scrim under the letter — white on the bare gradient
     reads 4.23..4.47, with the scrim 4.87..5.12, hue untouched. Aura replaces
     this background wholesale (its inner span is near-black) and is unaffected. */
  background: linear-gradient(rgba(0,0,0,.08), rgba(0,0,0,.08)), linear-gradient(135deg, #6366f1, #8b5cf6);
  font-size: .8rem; font-weight: 800;
}
.sbt-nav-links { display: flex; align-items: stretch; gap: 1.25rem; flex-wrap: wrap; }
/* underline nav item (dtap/Breeze NavLink): border-b-2, no radius, full height */
.sbt-nav-link {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: 2px .15rem 0; border: 0; border-bottom: 2px solid transparent;
  font-size: .875rem; font-weight: 500; line-height: 1.4;
  color: var(--sbt-muted) !important; text-decoration: none !important;
  background: none; cursor: pointer; font-family: inherit;
  transition: color .12s, border-color .12s;
}
.sbt-nav-link:hover {
  color: var(--sbt-text-2) !important; border-bottom-color: var(--sbt-border-2);
}
.sbt-nav-link.active {
  color: var(--sbt-text) !important; border-bottom-color: var(--sbt-nav-active-border);
}
/* Its children are rem-sized and `white-space: nowrap`, so a reader who raises
   the browser's default font size grows this row without letting it break: at a
   32px root (the WCAG 1.4.4 200% bar) it needs 483px inside a 390px bar and
   pushed an icon button clean off the screen, on every page of the suite. The
   wrap is a no-op wherever the row already fits — at the default 16px root the
   whole bar measures byte-identical in all five themes. */
.sbt-nav-right { margin-left: auto; display: flex; flex-wrap: wrap; align-items: center; gap: .35rem; }
.sbt-nav-burger { display: none; }

/* aura nav: glass bar + pill links (dtap .aura-nav / .aura-nav-link) */
html[data-sbt-theme="aura"] .sbt-nav {
  background: rgba(15,23,42,0.5);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border-bottom: 1px solid rgba(51,65,85,0.5);
}
html[data-sbt-theme="aura"] .sbt-nav-links { gap: .3rem; align-items: center; }
html[data-sbt-theme="aura"] .sbt-nav-link {
  padding: .5rem .75rem; border-bottom: 0; border-radius: .5rem;
  color: #94a3b8 !important; transition: all 0.2s;
}
html[data-sbt-theme="aura"] .sbt-nav-link:hover {
  color: #fff !important; background: rgba(30,41,59,0.5);
}
html[data-sbt-theme="aura"] .sbt-nav-link.active {
  color: #fff !important; background: rgba(30,41,59,0.8) !important;
  box-shadow: 0 10px 15px -3px rgba(99,102,241,0.1);
}
/* aura brand: gradient-ring logo + gradient wordmark (dtap aura-logo-*) */
html[data-sbt-theme="aura"] .sbt-brand-mark {
  background: linear-gradient(to bottom right, #6366f1, #a855f7, #ec4899);
  padding: 2px; border-radius: .65rem;
}
html[data-sbt-theme="aura"] .sbt-brand-mark > span {
  background: #0f172a; border-radius: calc(.65rem - 2px);
  width: 100%; height: 100%; display: flex; align-items: center; justify-content: center;
}
.sbt-brand-mark > span { width: 100%; height: 100%; display: flex;
  align-items: center; justify-content: center; }
html[data-sbt-theme="aura"] .sbt-brand-text {
  background: linear-gradient(to right, #fff, #cbd5e1);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
}

@media (max-width: 991px) {
  .sbt-nav-inner { align-items: center; }
  .sbt-nav-links {
    display: none; width: 100%; flex-direction: column; align-items: stretch;
    gap: .125rem; padding: .5rem 0; border-top: 1px solid var(--sbt-border); margin-top: .25rem;
  }
  .sbt-nav-links.open { display: flex; }
  .sbt-nav-burger { display: inline-flex; }
  /* stacked mobile items: pill style regardless of theme */
  .sbt-nav-link { border-bottom: 0; border-radius: 8px; padding: .5rem .7rem; }
  .sbt-nav-link:hover { background: var(--sbt-surface-2); }
  .sbt-nav-link.active { background: var(--sbt-accent-weak); color: var(--sbt-accent-text) !important; }
  .sbt-dropdown { position: static; }
  .sbt-nav-links .sbt-dropdown-menu { position: static; box-shadow: none; border: 0;
    padding-left: 1.5rem; min-width: 0; background: transparent; }
}

/* ---- dropdowns (dtap submenu: white/gray-800 rounded-md shadow; active item
        indigo-50/indigo-700 + right-side indigo dot) ---- */
.sbt-dropdown { position: relative; display: flex; align-items: stretch; }
.sbt-dropdown-menu {
  position: absolute; top: calc(100% + 2px); left: 0; min-width: 220px;
  background: var(--sbt-surface); border: 1px solid var(--sbt-border);
  border-radius: var(--sbt-radius); box-shadow: var(--sbt-shadow-lg);
  padding: .4rem; display: none; z-index: 1000;
}
.sbt-dropdown-menu.end { left: auto; right: 0; }
.sbt-dropdown.open > .sbt-dropdown-menu { display: block; }
.sbt-dropdown-item {
  display: flex; align-items: center; gap: .5rem; width: 100%;
  padding: .45rem .65rem; border-radius: 7px; font-size: .875rem;
  color: var(--sbt-text-2) !important; text-decoration: none !important;
  border: 0; background: none; cursor: pointer; text-align: left; font-family: inherit;
}
.sbt-dropdown-item:hover { background: var(--sbt-surface-2); color: var(--sbt-text) !important; }
.sbt-dropdown-item.active {
  background: var(--sbt-accent-weak); color: var(--sbt-accent-text) !important;
}
.sbt-dropdown-item.active::after {
  content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--sbt-accent); margin-left: auto; flex: 0 0 auto;
}
.sbt-dropdown-header {
  padding: .35rem .65rem .2rem; font-size: .7rem; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--sbt-muted);
}
.sbt-dropdown-divider { border-top: 1px solid var(--sbt-border); margin: .35rem 0; }
html[data-sbt-theme="aura"] .sbt-dropdown-menu {
  background: #1e293b; border: 1px solid rgba(51,65,85,0.5);
  border-radius: .75rem; box-shadow: 0 25px 50px -12px rgba(0,0,0,0.5);
}

/* ---- user chip / avatar ---- */
.sbt-avatar {
  width: 30px; height: 30px; border-radius: 50%; display: inline-flex;
  align-items: center; justify-content: center; flex: 0 0 auto;
  background: var(--sbt-accent-weak); color: var(--sbt-accent-text);
  font-weight: 600; font-size: .75rem;
  position: relative; overflow: hidden;
}

/* WO5-9 (#319) — one profile photo, wherever an identity avatar is drawn.
   SBT.avatarInner() emits this INSIDE the initials, not instead of them, so a
   photo that 404s or is blocked reveals the initials underneath rather than an
   empty coloured disc. That is why every avatar wrapper carries
   `position: relative` and this is absolute.

   ⚠ Theme-agnostic ON PURPOSE, and it is the one part of WO5-9 that is not
   prime-only: a photo is DATA, not styling, so it would be absurd for someone's
   face to disappear when they switch to `dark`. The richer initials RAMP below
   stays prime-scoped; with no photo uploaded — which is every user until they
   upload one — light/dark/aura render exactly what they rendered before. */
.sbt-av-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; border-radius: inherit; display: block;
}
html[data-sbt-theme="aura"] .sbt-avatar {
  background: linear-gradient(to bottom right, #6366f1, #a855f7); color: #fff;
}
.sbt-user-btn {
  display: inline-flex; align-items: center; gap: .5rem; padding: .35rem .6rem;
  border: 1px solid var(--sbt-border); border-radius: 10px; cursor: pointer;
  background: var(--sbt-surface); color: var(--sbt-text-2);
  font-family: inherit; font-size: .875rem; font-weight: 500;
}
.sbt-user-btn:hover { background: var(--sbt-surface-2); }
html[data-sbt-theme="aura"] .sbt-user-btn {
  background: rgba(30,41,59,0.5); border-color: rgba(51,65,85,0.5); color: #e2e8f0;
}
html[data-sbt-theme="aura"] .sbt-user-btn:hover { background: rgba(30,41,59,0.8); }

/* ---- page scaffold ---- */
.sbt-main { max-width: 1400px; margin: 0 auto; padding: 1.5rem 1.25rem 3rem; }
/* ---- WO5-8: the app frame (workorder 05 §14c) ----------------------------
   The two Dribbble references are application WINDOWS: the app owns the
   viewport, and there is no page title, no subtitle and no centred column.
   Ours was a document page with the app inside a bordered card under ~250px of
   chrome, which accounts for more of the visual gap than every colour token
   combined (§14a-4).

   Opt-in via `.is-app` (the blade sets it) AND prime-scoped AND >=1024px:
     - the other 29 pages never see it (no `.is-app`),
     - light/dark/aura keep the centred document page (prime scope),
     - phone and tablet keep the existing one-pane machine, which §1c says is
       already good and must be preserved (the min-width bound).
   ⚠ The min-width bound is not optional: sbt.css's own narrow blocks live
   earlier at lower specificity, the same ordering trap as §12 defect 4b. */
@media (min-width: 1024px) {
  html[data-sbt-theme^="prime"] .sbt-main.is-app {
    max-width: none;
    padding: 0;
  }
  /* The app supplies its own title where the references put it — at the top of
     the list pane — so the page head is redundant chrome here. */
  html[data-sbt-theme^="prime"] .sbt-main.is-app .sbt-page-head { display: none; }

  /* `padding: 0` on the main is what lets the PANES reach the window edge, the
     way both references do. The bands ABOVE the panes are not panes, so they
     would otherwise sit flush against the glass. Give those their own inline
     padding rather than re-padding the main. ⚠ Only the bands: adding this to
     the pane wrap would inset the panes and undo the frame. */
  html[data-sbt-theme^="prime"] .sbt-main.is-app .ml-seg,
  html[data-sbt-theme^="prime"] .sbt-main.is-app .ml-mail-head {
    padding-inline: var(--sbt-sp-4);
  }
  html[data-sbt-theme^="prime"] .sbt-main.is-app .ml-seg { padding-top: var(--sbt-sp-3); }
}

.sbt-page-head { display: flex; flex-wrap: wrap; justify-content: space-between;
  align-items: flex-start; gap: 1rem; margin-bottom: 1.25rem; }
.sbt-page-head p { color: var(--sbt-muted); margin: 0; }

/* ---- cards ---- */
.sbt-card {
  background: var(--sbt-surface); border: 1px solid var(--sbt-border);
  border-radius: var(--sbt-radius); box-shadow: var(--sbt-shadow); margin-bottom: 1.5rem;
}
.sbt-card-header {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: .75rem; padding: .9rem 1.15rem; border-bottom: 1px solid var(--sbt-border);
}
.sbt-card-header h5 { margin: 0; display: flex; align-items: center; gap: .5rem; }
.sbt-card-body { padding: 1.15rem; }
/* aura glass card (dtap .aura-glass-card) */
html[data-sbt-theme="aura"] .sbt-card {
  background: linear-gradient(135deg, rgba(15,23,42,0.8), rgba(30,41,59,0.6));
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid rgba(51,65,85,0.5);
  border-radius: 1rem;
  transition: border-color .25s ease, box-shadow .25s ease;
}
html[data-sbt-theme="aura"] .sbt-card:hover {
  border-color: rgba(139,92,246,0.34);
  box-shadow: 0 8px 34px rgba(99,102,241,0.20);
}
html[data-sbt-theme="aura"] .sbt-card-header { border-bottom-color: rgba(51,65,85,0.5); }

/* ---- buttons ---- */
.sbt-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .5rem .95rem; border-radius: 8px; font-size: .875rem; font-weight: 500;
  font-family: inherit; line-height: 1.4; cursor: pointer; white-space: nowrap;
  border: 1px solid transparent; background: var(--sbt-surface-2);
  color: var(--sbt-text-2); text-decoration: none !important;
  transition: background .12s, border-color .12s, color .12s;
}
.sbt-btn:hover { background: var(--sbt-surface-3); text-decoration: none !important; }
.sbt-btn:disabled { opacity: .5; cursor: not-allowed; }
.sbt-btn-sm { padding: .32rem .65rem; font-size: .8125rem; border-radius: 7px; }
.sbt-btn-xs { padding: .18rem .45rem; font-size: .75rem; border-radius: 6px; }
.sbt-btn-primary { background: var(--sbt-accent); color: #fff; }
.sbt-btn-primary:hover { background: var(--sbt-accent-strong); color: #fff; }
/* `.sbt-body a` (line 392) is a more specific selector than `.sbt-btn-primary`,
   so an <a> styled as a primary button took the LINK colour instead of white —
   and in prime-light --sbt-accent-text and --sbt-accent are the same value, so
   the label sat on its own background at a contrast ratio of 1.00 and was
   simply invisible. An anchor button must render identically to a <button>. */
.sbt-body a.sbt-btn-primary,
.sbt-body a.sbt-btn-primary:hover { color: #fff; }
.sbt-btn-outline { background: transparent; border-color: var(--sbt-border-2); }
.sbt-btn-outline:hover { background: var(--sbt-surface-2); }
.sbt-btn-danger { background: var(--sbt-danger-weak); color: var(--sbt-danger); }
.sbt-btn-danger:hover { background: var(--sbt-danger); color: #fff; }
.sbt-btn-danger-solid { background: var(--sbt-danger); color: #fff; }
.sbt-btn-danger-solid:hover { filter: brightness(.92); color: #fff; }
/* The rule above sets a filter and a colour but no BACKGROUND, so the generic
   `.sbt-btn:hover` (line 718, one class more specific than the danger rule)
   wins and repaints the button in --sbt-surface-3. On the light themes that is
   a pale grey and the white label on it measured 1.21:1 in prime-light and
   1.10:1 in light: the "Delete all" button's own text vanished the moment a
   pointer touched it. Restoring the fill is the functional half of the fix, so
   it reaches `light` too.
   The dark-surface themes take a LIGHT rose for --sbt-danger (#fb7185), where
   white is 2.69:1 and black is 7.80:1 — the same finding the bell badge already
   carries at line 1143, and the same convention as this theme's own
   --sbt-on-warning. prime-dark is in scope so it takes both halves. `dark` and
   `aura` stay byte-identical: their idle 2.69 is the legacy ruling parked since
   c72, and giving them the fill back without the black label would have made
   their hover worse, so it is deliberately not done. */
html[data-sbt-theme="prime-light"] .sbt-btn-danger-solid:hover,
html[data-sbt-theme="light"] .sbt-btn-danger-solid:hover,
html[data-sbt-theme="prime-dark"] .sbt-btn-danger-solid:hover { background: var(--sbt-danger); }
html[data-sbt-theme="prime-dark"] .sbt-btn-danger-solid,
html[data-sbt-theme="prime-dark"] .sbt-btn-danger-solid:hover { color: #000; }
.sbt-btn-icon { padding: .38rem; width: 2.1rem; height: 2.1rem; }
.sbt-btn-icon.sbt-btn-sm { width: 1.85rem; height: 1.85rem; padding: .28rem; }
/* aura primary: animated indigo→purple gradient + shimmer (dtap .aura-btn-primary) */
html[data-sbt-theme="aura"] .sbt-btn-primary {
  position: relative; overflow: hidden;
  background: linear-gradient(to right, #4f46e5, #9333ea, #4f46e5);
  background-size: 200% 100%;
  animation: aura-gradient-shift 8s ease infinite;
  border: none; transition: all 0.2s;
}
html[data-sbt-theme="aura"] .sbt-btn-primary:hover {
  box-shadow: 0 0 20px rgba(99,102,241,0.4);
}
html[data-sbt-theme="aura"] .sbt-btn-primary::after {
  content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
  animation: aura-shimmer 3s infinite;
}
html[data-sbt-theme="aura"] .sbt-btn {
  background-color: rgba(30,41,59,0.5); border-color: rgba(51,65,85,0.5);
}
html[data-sbt-theme="aura"] .sbt-btn:hover { background-color: rgba(30,41,59,0.8); }
html[data-sbt-theme="aura"] .sbt-btn-primary,
html[data-sbt-theme="aura"] .sbt-btn-primary:hover { border: none; }
html[data-sbt-theme="aura"] .sbt-btn-danger { background: var(--sbt-danger-weak); }
html[data-sbt-theme="aura"] .sbt-btn-danger:hover { background: var(--sbt-danger); }
html[data-sbt-theme="aura"] .sbt-btn-danger-solid { background: var(--sbt-danger); }

/* ---- badges ---- */
.sbt-badge {
  display: inline-flex; align-items: center; gap: .3rem; padding: .18rem .55rem;
  border-radius: 999px; font-size: .72rem; font-weight: 600; line-height: 1.35;
  background: var(--sbt-surface-3); color: var(--sbt-text-2); white-space: nowrap;
}
.sbt-badge-accent { background: var(--sbt-accent-weak); color: var(--sbt-accent-text); }
.sbt-badge-success { background: var(--sbt-success-weak); color: var(--sbt-success); }
.sbt-badge-warning { background: var(--sbt-warning-weak); color: var(--sbt-warning); }
.sbt-badge-danger { background: var(--sbt-danger-weak); color: var(--sbt-danger); }
.sbt-badge-info { background: var(--sbt-info-weak); color: var(--sbt-info); }
.sbt-badge-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

/* #372 -- the one real AA failure of the 465-cell sweep (w05 SS16b): under the
   legacy light theme the four badge families read 3.07-4.28 on their own tints,
   because the base token was chosen to sit on a white surface and the tint is
   not white. Measured on the shipped values:
                current            ->  stepped
     success    #059669 3.58           #047857 5.21
     warning    #d97706 3.07           #a2570a 5.19
     danger     #e11d48 4.28           #c81e42 5.14
     info       #0891b2 3.54           #0e6f8c 5.50
   Badge-only and light-only: the tints do not move, and every other use of
   --sbt-success / -warning / -danger / -info is untouched, so nothing that
   already passes is restyled to fix something that did not. `light` is always
   stamped explicitly (the no-attribute state maps to the dark palette above),
   so scoping by the attribute reaches every light-theme page. */
html[data-sbt-theme="light"] .sbt-badge-success { color: #047857; }
html[data-sbt-theme="light"] .sbt-badge-warning { color: #a2570a; }
html[data-sbt-theme="light"] .sbt-badge-danger  { color: #c81e42; }
html[data-sbt-theme="light"] .sbt-badge-info    { color: #0e6f8c; }

/* ---- alerts ---- */
.sbt-alert {
  display: flex; align-items: flex-start; gap: .6rem; padding: .7rem .95rem;
  border-radius: var(--sbt-radius-sm); font-size: .875rem; margin-bottom: 1rem;
  border: 1px solid transparent;
}
.sbt-alert-info { background: var(--sbt-info-weak); color: var(--sbt-info); }
.sbt-alert-warning { background: var(--sbt-warning-weak); color: var(--sbt-warning); }
.sbt-alert-danger { background: var(--sbt-danger-weak); color: var(--sbt-danger); }
.sbt-alert-success { background: var(--sbt-success-weak); color: var(--sbt-success); }

/* manu code for erasure banner overlap starts here */
/* ---- G6d: the company-wide erasure cooling-off banner ----
   A strip at the top of every page, for every member of a company with a live
   erasure request. Every colour is a token, so it follows the viewer's theme
   like the rest of the app.
   It no longer sticks on its own: it was sticky at top 0 with z-index 1990
   (under the impersonation banner's 2000, over the nav's 900), and once a page
   scrolled it lay over the nav and over the top edge of every overlay. It now
   sticks as part of .sbt-chrome below, one block with the nav. */
.sbt-erasure-banner {
/* manu code for erasure banner overlap ends here */
  display: flex; align-items: center; justify-content: center;
  gap: .55rem; padding: .55rem 1rem;
  background: var(--sbt-danger-weak); color: var(--sbt-danger);
  border-bottom: 1px solid var(--sbt-danger);
  font-size: .875rem; line-height: 1.35;
}
/* Deliberately NOT flex-wrap. A flex line breaks on an item's CONTENT width
   before any shrinking, so a wrapping container puts this sentence — and then
   the link — on lines of their own: measured at 109px of sticky chrome on a
   780px viewport. Without it the sentence wraps INSIDE its own column and the
   row stays one row. */
.sbt-erasure-banner > span { min-width: 0; }
.sbt-erasure-banner .si { width: 1rem; height: 1rem; flex: none; }
.sbt-erasure-banner-link {
  color: var(--sbt-danger); font-weight: 600; text-decoration: underline;
  text-underline-offset: 2px; white-space: nowrap;
}
/* manu code for erasure banner overlap starts here */
/* ---- the sticky top chrome: the erasure banners and the nav as ONE block ----
   The layout wraps both in .sbt-chrome. Each used to stick to top 0 on its
   own, so once a page scrolled the banner lay over the nav — measured c321 on
   dev: at 1280px every nav control's centre was under the 37px banner, and at
   390px the whole 79px nav was under the 94px banner, with the menu button's
   centre on the banner's "Review it" link. Stacked in one sticky block they
   cannot overlap. The nav keeps its own sticky rule: inside a block that is
   exactly the banners plus the nav it never moves, and it stays the
   containing block that the bell and money menus pin to on a phone.
   z-index 1030 keeps the block above the page and the nav's own menus and
   BELOW every overlay: the task/ticket drawer's veil (1040) and panel (1041),
   tooltips (1050), the assistant (1085/1086), the chat lightbox (1090),
   context menus (1100), modals (1200), toasts (1400) and confirm dialogs
   (1500). At 1990 the banner sat over all of them: the drawer's History,
   Follow, Archive, Delete and Close buttons (y 10-40) were under it at every
   width, and at 390px so was the History panel's close button. The
   impersonation banner (2000) still sits above everything: it is about who
   you currently ARE. */
.sbt-chrome { position: sticky; top: 0; z-index: 1030; }
/* manu code for erasure banner overlap ends here */
/* manu code for impersonation banner overlap starts here */
/* ---- the impersonation banner: above everything, and everything below it --
   The banner keeps its place OVER every overlay (2000 — who you ARE), but it
   used to be the erasure story again, one storey up: sticky at top 0 it lay
   over the chrome once a page scrolled (c460 measured on dev: all 11 nav
   control centres under its 38px at 1280px), over the task drawer's head at
   ANY scroll (History, Follow, Archive, Delete, Close — centres y 24), and
   at 390px, where it wraps to 97px, over a modal's close button (centre y
   62). It cannot join .sbt-chrome — it must outrank the overlays the chrome
   sits under — so instead sbt.js publishes its height as --sbt-imp-h and the
   three surfaces start below it: the chrome (here), the drawer (work.css
   #wk-drawer) and the modal band (.sbt-modal-backdrop below, which is also
   every confirm dialog's shell). Without an impersonation the variable is
   unset and every rule falls back to 0. */
.sbt-imp-banner { position: sticky; top: 0; z-index: 2000; font-size: .9rem; }
.sbt-chrome { top: var(--sbt-imp-h, 0px); }
/* manu code for impersonation banner overlap ends here */

/* ---- breadcrumb ---- */
.sbt-breadcrumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: .35rem;
  list-style: none; margin: 0 0 1rem; padding: 0; font-size: .875rem;
}
.sbt-breadcrumb li { display: flex; align-items: center; gap: .35rem; }
.sbt-breadcrumb li + li::before { content: "/"; color: var(--sbt-muted); opacity: .6; }
.sbt-breadcrumb .current { color: var(--sbt-muted); }

/* ---- tables ---- */
.sbt-table-wrap { overflow-x: auto; }
.sbt-table { width: 100%; border-collapse: collapse; font-size: .875rem; }
.sbt-table th {
  text-align: left; padding: .6rem .75rem; font-size: .72rem; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase; color: var(--sbt-muted);
  border-bottom: 1px solid var(--sbt-border); white-space: nowrap;
}
.sbt-table td {
  padding: .55rem .75rem; border-bottom: 1px solid var(--sbt-border);
  vertical-align: middle;
}
.sbt-table tbody tr:last-child td { border-bottom: 0; }
.sbt-table tbody tr:hover { background: var(--sbt-surface-2); }
html[data-sbt-theme="aura"] .sbt-table tbody tr:hover { background: rgba(30,41,59,0.5); }
.sbt-table th.sortable { cursor: pointer; user-select: none; }
.sbt-table th.sortable:hover { color: var(--sbt-text-2); }

/* A-18 (c69/c73): opt-in pinned last column for tables whose per-row controls
   live in their final column. On a phone — and at 200% text — those controls
   otherwise sit behind a sideways scroll with nothing on screen saying the
   region scrolls. Reachability, not styling: every theme gets it, only below
   640px. Colspan cells (Loading… / empty / Load more) are never pinned. */
@media (max-width: 640px) {
  .sbt-table-pin thead th:last-child,
  .sbt-table-pin tbody td:last-child:not([colspan]) {
    position: sticky; right: 0; z-index: 2;
    background: var(--sbt-surface);
    box-shadow: -8px 0 8px -8px rgba(0, 0, 0, .35);
  }
  .sbt-table-pin thead th:last-child { z-index: 3; }
  .sbt-table-pin tbody tr:hover td:last-child:not([colspan]) { background: var(--sbt-surface-2); }
  /* aura paints cards as a translucent gradient; --sbt-surface would read as
     a foreign block behind the pinned cell — use the gradient's first stop */
  html[data-sbt-theme="aura"] .sbt-table-pin thead th:last-child,
  html[data-sbt-theme="aura"] .sbt-table-pin tbody td:last-child:not([colspan]) {
    background: rgba(15, 23, 42, .96);
  }
  /* A-18 companions: what actually pushes a phone page sideways at 200% text
     is the page-head's action row (no wrap) and its nowrap button labels —
     let the row wrap and the labels break. Empty-state CTAs share the shape. */
  .sbt-page-head .d-flex { flex-wrap: wrap; }
  .sbt-page-head .sbt-btn, .sbt-empty .sbt-btn { white-space: normal; }
  /* A pinned cell wider than the scroll wrap cannot be pinned — the browser
     clamps it at the row edge and the controls hang off screen. Cap the
     cell's content and let action groups and text labels wrap inside it. */
  .sbt-table-pin tbody td:last-child:not([colspan]) > * { max-width: 220px; }
  .sbt-table-pin td:last-child .d-inline-flex { flex-wrap: wrap; justify-content: flex-end; }
  .sbt-table-pin td:last-child .d-inline-flex > * { min-width: 0; max-width: 100%; }
  .sbt-table-pin td:last-child .sbt-btn { white-space: normal; word-break: break-word; }
  /* Pagination rows (Prev · Page N of M · Next) run a few px over at 200%. */
  .sbt-card-body.d-flex { flex-wrap: wrap; }
}
.sbt-table .text-end { text-align: right; }

/* ---- forms ---- */
.sbt-label { display: block; font-size: .8125rem; font-weight: 500; margin-bottom: .3rem;
  color: var(--sbt-text-2); }
.sbt-input, .sbt-select, .sbt-textarea {
  width: 100%; padding: .48rem .7rem; border-radius: 8px; font-size: .875rem;
  font-family: inherit; color: var(--sbt-text);
  background: var(--sbt-surface); border: 1px solid var(--sbt-border-2);
  transition: border-color .12s, box-shadow .12s;
}
.sbt-input:focus, .sbt-select:focus, .sbt-textarea:focus {
  outline: none; border-color: var(--sbt-accent);
  box-shadow: 0 0 0 3px var(--sbt-accent-weak);
}
/* aura inputs (dtap .aura-input) */
html[data-sbt-theme="aura"] .sbt-input,
html[data-sbt-theme="aura"] .sbt-select,
html[data-sbt-theme="aura"] .sbt-textarea {
  background-color: rgba(15,23,42,0.5); border-color: rgba(51,65,85,0.5); color: #fff;
}
html[data-sbt-theme="aura"] .sbt-input::placeholder,
html[data-sbt-theme="aura"] .sbt-textarea::placeholder { color: #64748b; }
html[data-sbt-theme="aura"] .sbt-input:focus,
html[data-sbt-theme="aura"] .sbt-select:focus,
html[data-sbt-theme="aura"] .sbt-textarea:focus {
  border-color: rgba(99,102,241,0.5);
  box-shadow: 0 0 0 3px rgba(99,102,241,0.1), 0 0 20px rgba(99,102,241,0.2);
  outline: none;
}
.sbt-input-sm, .sbt-select-sm { padding: .3rem .55rem; font-size: .8125rem; }
select.sbt-select { -webkit-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .6rem center; padding-right: 2rem; }

/* A-42: no text entry under 16px on a touch-primary device — below that,
   iOS Safari auto-zooms the page the moment the field is tapped (the viewport
   meta rightly allows zoom, WCAG 1.4.4, so the only fix is the font size).
   Element selectors + !important on purpose: later page sheets set their own
   control sizes (13/13.12px measured across all 31 URLs) and every one of
   them must lose here, or the zoom comes back on that one field. Buttons are
   untouched — focusing a button never zooms. Desktop keeps its density: the
   query never matches a mouse/trackpad-primary machine. */
@media (hover: none) and (pointer: coarse) {
  input, select, textarea, [contenteditable="true"] { font-size: 16px !important; }
}
.sbt-check { width: 1rem; height: 1rem; accent-color: var(--sbt-accent); cursor: pointer; }

/* ---- modal ---- */
.sbt-modal-backdrop {
  position: fixed; inset: 0; background: rgba(3, 7, 18, .55); z-index: 1200;
  display: none; align-items: flex-start; justify-content: center;
  padding: 4vh 1rem; overflow-y: auto;
  /* manu code for impersonation banner overlap starts here */
  /* Below the impersonation banner (2000): the band starts under it so a
     modal's close button stays clickable — at 390px the wrapped banner (97px,
     measured c460) reached past the close button's centre (y 62). Confirm
     dialogs reuse this shell (dialogShell, z 1500), so this line is theirs
     too. Unset outside an impersonation -> 0. */
  top: var(--sbt-imp-h, 0px);
  /* manu code for impersonation banner overlap ends here */
}
.sbt-modal-backdrop.open { display: flex; }
.sbt-modal {
  background: var(--sbt-surface); border: 1px solid var(--sbt-border);
  border-radius: 14px; box-shadow: var(--sbt-shadow-lg);
  width: 100%; max-width: 560px; margin-bottom: 4vh;
}
html[data-sbt-theme="aura"] .sbt-modal {
  background: #1e293b; border-color: rgba(51,65,85,0.5);
  box-shadow: 0 25px 50px -12px rgba(0,0,0,0.5);
}
.sbt-modal-lg { max-width: 860px; }
.sbt-modal-xl { max-width: 1140px; }
.sbt-modal-header {
  display: flex; align-items: center; gap: .75rem; padding: .9rem 1.15rem;
  border-bottom: 1px solid var(--sbt-border);
}
.sbt-modal-header h5 { margin: 0; flex: 1; display: flex; align-items: center;
  gap: .5rem; min-width: 0; }
.sbt-modal-body { padding: 1.15rem; }
.sbt-modal-footer {
  display: flex; justify-content: flex-end; gap: .5rem; padding: .85rem 1.15rem;
  border-top: 1px solid var(--sbt-border);
}
.sbt-modal-close {
  border: 0; background: none; cursor: pointer; color: var(--sbt-muted);
  padding: .3rem; border-radius: 6px; display: inline-flex;
}
.sbt-modal-close:hover { background: var(--sbt-surface-2); color: var(--sbt-text); }

/* ---- toasts ---- */
.sbt-toasts {
  position: fixed; top: 1rem; right: 1rem; z-index: 1400;
  display: flex; flex-direction: column; gap: .5rem; max-width: 340px;
}
.sbt-toast {
  display: flex; align-items: center; gap: .55rem; padding: .65rem .9rem;
  border-radius: 10px; font-size: .875rem; font-weight: 500;
  background: var(--sbt-surface); color: var(--sbt-text);
  border: 1px solid var(--sbt-border); box-shadow: var(--sbt-shadow-lg);
  animation: sbt-toast-in .18s ease-out;
}
html[data-sbt-theme="aura"] .sbt-toast { background: #1e293b; border-color: rgba(51,65,85,0.5); }
.sbt-toast.success { border-left: 3px solid var(--sbt-success); }
.sbt-toast.error { border-left: 3px solid var(--sbt-danger); }
.sbt-toast.info { border-left: 3px solid var(--sbt-info); }
.sbt-toast.warning { border-left: 3px solid var(--sbt-warning); }
@keyframes sbt-toast-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; } }

/* ---- progress ---- */
.sbt-progress { height: 6px; border-radius: 999px; background: var(--sbt-surface-3);
  overflow: hidden; }
.sbt-progress-bar { height: 100%; border-radius: 999px; background: var(--sbt-accent);
  transition: width .15s linear; }

/* ---- spinner ---- */
.sbt-spin {
  display: inline-block; width: 1em; height: 1em; border-radius: 50%;
  border: 2px solid currentColor; border-right-color: transparent;
  animation: sbt-spin .65s linear infinite; vertical-align: -.15em;
}
@keyframes sbt-spin { to { transform: rotate(360deg); } }

/* ---- dropzone ---- */
.sbt-dropzone {
  border: 2px dashed var(--sbt-border-2); border-radius: var(--sbt-radius);
  padding: 1.75rem 1rem; text-align: center; color: var(--sbt-muted);
  cursor: pointer; transition: border-color .15s, background .15s;
}
.sbt-dropzone.dragover { border-color: var(--sbt-accent); background: var(--sbt-accent-weak); }
html[data-sbt-theme="aura"] .sbt-dropzone { border-color: rgba(51,65,85,0.7); }
html[data-sbt-theme="aura"] .sbt-dropzone.dragover {
  border-color: rgba(99,102,241,0.6); background: rgba(99,102,241,0.1);
}

/* ---- aura scrollbar (ported from dtap) ---- */
html[data-sbt-theme="aura"] ::-webkit-scrollbar { width: 6px; height: 6px; }
html[data-sbt-theme="aura"] ::-webkit-scrollbar-track { background: #0f172a; }
html[data-sbt-theme="aura"] ::-webkit-scrollbar-thumb {
  background: rgba(99,102,241,0.3); border-radius: 3px;
}
html[data-sbt-theme="aura"] ::-webkit-scrollbar-thumb:hover {
  background: rgba(99,102,241,0.5);
}

/* ---- aura keyframes (ported verbatim from dtap) ---- */
@keyframes aura-pulse-glow {
  0%, 100% { opacity: 0.3; transform: scale(1); }
  50% { opacity: 0.6; transform: scale(1.05); }
}
@keyframes aura-float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-20px) rotate(5deg); }
}
@keyframes aura-gradient-shift {
  0%, 100% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
}
@keyframes aura-shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}
@keyframes aura-spin-slow {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* ---- misc ---- */
.sbt-empty { text-align: center; color: var(--sbt-muted); padding: 3rem 1rem; }
.sbt-kbd { font-family: var(--sbt-mono); font-size: .8em; background: var(--sbt-surface-3);
  border: 1px solid var(--sbt-border); border-radius: 5px; padding: .05rem .35rem; }
.sbt-pre {
  background: var(--sbt-surface-2); border: 1px solid var(--sbt-border);
  border-radius: var(--sbt-radius-sm); padding: 1rem; overflow: auto;
  font-family: var(--sbt-mono); font-size: .8125rem; margin: 0;
  white-space: pre-wrap; word-break: break-word;
}
.sbt-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- utility + compatibility layer ----
   Small set of layout utilities shared with the self-contained cross-layout
   partials (AI chat widget, impersonation banner) so they render correctly
   on this layout too. */
.d-none { display: none !important; }
.d-block { display: block !important; }
.d-flex { display: flex !important; }
.d-inline { display: inline !important; }
.d-inline-flex { display: inline-flex !important; }
.flex-wrap { flex-wrap: wrap !important; }
.flex-column { flex-direction: column !important; }
.flex-grow-1 { flex-grow: 1 !important; }
.align-items-center { align-items: center !important; }
/* Was MISSING while 11 call sites across 8 blades already used it, so every one
   of them silently fell back to `normal` (= stretch). Measured on the Data &
   Erasure page: a "Cancel this request" button next to a taller text column was
   drawn 127px tall. The set had `center` and `end` but not `start`. */
.align-items-start { align-items: flex-start !important; }
.align-items-end { align-items: flex-end !important; }
.justify-content-center { justify-content: center !important; }
.justify-content-between { justify-content: space-between !important; }
.text-center { text-align: center !important; }
.text-end { text-align: right !important; }
.text-start { text-align: left !important; }
.text-muted { color: var(--sbt-muted) !important; }
.text-danger { color: var(--sbt-danger) !important; }
.text-success { color: var(--sbt-success) !important; }
.text-warning { color: var(--sbt-warning) !important; }
.fw-medium { font-weight: 500 !important; }
.fw-bold { font-weight: 700 !important; }
.small { font-size: .8125rem !important; }
.w-100 { width: 100% !important; }
.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: .25rem !important; }
.mb-2 { margin-bottom: .5rem !important; }
.mb-3 { margin-bottom: 1rem !important; }
.mb-4 { margin-bottom: 1.5rem !important; }
.mt-1 { margin-top: .25rem !important; }
.mt-2 { margin-top: .5rem !important; }
.mt-3 { margin-top: 1rem !important; }
.ms-1 { margin-left: .25rem !important; }
.ms-2 { margin-left: .5rem !important; }
.ms-auto { margin-left: auto !important; }
.me-1 { margin-right: .25rem !important; }
.me-2 { margin-right: .5rem !important; }
.py-0 { padding-top: 0 !important; padding-bottom: 0 !important; }
.py-1 { padding-top: .25rem !important; padding-bottom: .25rem !important; }
.py-2 { padding-top: .5rem !important; padding-bottom: .5rem !important; }
.px-2 { padding-left: .5rem !important; padding-right: .5rem !important; }
.px-4 { padding-left: 1.5rem !important; padding-right: 1.5rem !important; }
.gap-1 { gap: .25rem !important; }
.gap-2 { gap: .5rem !important; }
.gap-3 { gap: 1rem !important; }
@media (min-width: 768px) {
  .d-md-inline { display: inline !important; }
  .d-md-flex { display: flex !important; }
  .d-md-inline-flex { display: inline-flex !important; }
}
/* bootstrap-named pieces used by the shared partials */
.bg-warning { background: #f59e0b !important; }
.text-dark { color: #111827 !important; }
.btn { display: inline-flex; align-items: center; gap: .35rem; border: 1px solid transparent;
  border-radius: 8px; padding: .45rem .9rem; font-size: .875rem; font-weight: 500;
  cursor: pointer; font-family: inherit; }
.btn-sm { padding: .28rem .6rem; font-size: .8125rem; }
.btn-dark { background: #111827; color: #f9fafb; }
.btn-dark:hover { background: #1f2937; color: #fff; }

/* ---- Task F utilities (users/departments + later page ports) ---- */
.sbt-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
.sbt-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .5rem; }
@media (max-width: 640px) { .sbt-grid-2, .sbt-grid-3 { grid-template-columns: 1fr; } }
.font-monospace { font-family: var(--sbt-mono); }
.text-nowrap { white-space: nowrap; }
.text-info { color: var(--sbt-info) !important; }
.border { border: 1px solid var(--sbt-border); }
.rounded { border-radius: var(--sbt-radius-sm); }
.p-2 { padding: .5rem; }
.p-3 { padding: 1rem; }
.py-3 { padding-top: .75rem; padding-bottom: .75rem; }
.mt-4 { margin-top: 1.5rem; }
.sbt-input-group { display: flex; align-items: stretch; }
.sbt-input-group > .sbt-input { flex: 1 1 auto; min-width: 0; }
.sbt-input-group > .sbt-input:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; }
.sbt-input-group > .sbt-input:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.sbt-input-group > .sbt-btn { flex: 0 0 auto; }
.sbt-input-group > .sbt-btn:not(:first-child) { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: -1px; }
.sbt-input-group > .sbt-btn:not(:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; }

/* ---- Task F dashboards (SBTDash widget grid + widgets) ---- */
.sbt-dashgrid { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 1rem; }
.sbt-dashgrid > .sbt-dw { grid-column: span 12; min-width: 0; }
.sbt-dashgrid > .sbt-dw-stat { grid-column: span 6; }
@media (min-width: 992px) {
  .sbt-dashgrid > .sbt-colspan-1 { grid-column: span 1; }
  .sbt-dashgrid > .sbt-colspan-2 { grid-column: span 2; }
  .sbt-dashgrid > .sbt-colspan-3 { grid-column: span 3; }
  .sbt-dashgrid > .sbt-colspan-4 { grid-column: span 4; }
  .sbt-dashgrid > .sbt-colspan-5 { grid-column: span 5; }
  .sbt-dashgrid > .sbt-colspan-6 { grid-column: span 6; }
  .sbt-dashgrid > .sbt-colspan-7 { grid-column: span 7; }
  .sbt-dashgrid > .sbt-colspan-8 { grid-column: span 8; }
  .sbt-dashgrid > .sbt-colspan-9 { grid-column: span 9; }
  .sbt-dashgrid > .sbt-colspan-10 { grid-column: span 10; }
  .sbt-dashgrid > .sbt-colspan-11 { grid-column: span 11; }
  .sbt-dashgrid > .sbt-colspan-12 { grid-column: span 12; }
}
.sbt-dw > .sbt-card { height: 100%; transition: opacity .25s ease; }
/* Aura's own card rule outranks the line above and lists only border-color and
   box-shadow, so aura dashboard cards used to snap back to full opacity with no
   fade. Re-state the transition for aura, keeping its two properties. Written
   without the html type selector so this lands at the same specificity as the
   updating rule below, which therefore still wins on source order and keeps the
   dim itself instant. */
[data-sbt-theme="aura"] .sbt-dw > .sbt-card {
  transition: opacity .25s ease, border-color .25s ease, box-shadow .25s ease;
}
/* Dim instantly when an update starts, fade back only on the way out: a stale
   card must read as stale from the first frame, even when the refresh is fast. */
.sbt-dw.sbt-updating > .sbt-card { opacity: .55; transition-duration: 0s; }
.sbt-dw-head { padding-bottom: .5rem; }
.sbt-dw-head h5 { font-size: .95rem; }
.sbt-dw-ic { width: 34px; height: 34px; border-radius: 8px; display: inline-flex;
  align-items: center; justify-content: center; flex: 0 0 auto; }
.sbt-dw-ic .si { width: 18px; height: 18px; }
.sbt-table-sm th, .sbt-table-sm td { padding: .4rem .6rem; }
.sbt-table tfoot td { border-top: 2px solid var(--sbt-border-2); }
.sbt-decomp-node { width: 210px; border: 1px solid var(--sbt-border); border-radius: 8px;
  padding: .5rem; margin-bottom: .5rem; background: var(--sbt-surface); }
.sbt-decomp-node:hover { border-color: var(--sbt-accent); }
.sbt-decomp-node.sel { border-color: var(--sbt-accent); box-shadow: 0 0 0 2px var(--sbt-accent-weak); }
.sbt-skel { position: relative; overflow: hidden; background: var(--sbt-surface-3);
  border-radius: var(--sbt-radius-sm); }
.sbt-skel::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .28), transparent);
  animation: sbt-skel 1.4s infinite; }
html[data-sbt-theme="dark"] .sbt-skel::after,
html[data-sbt-theme="aura"] .sbt-skel::after {
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .07), transparent);
}
@keyframes sbt-skel { to { transform: translateX(100%); } }

/* ---- notification bell (WO-9) ---- */
#sbt-bell > .sbt-btn { position: relative; }
.sbt-bell-badge { position: absolute; top: 2px; right: 2px; min-width: 15px; height: 15px;
  padding: 0 3px; border-radius: 8px; background: var(--sbt-danger); color: #fff;
  font-size: .62rem; line-height: 15px; font-weight: 600; text-align: center; }
/* The badge hard-codes white, but --sbt-danger is not one colour: the themes
   built for a dark surface pick a LIGHT rose (#fb7185), and white on that is
   2.69:1 — on 10px text, the unread count was the one thing on the bell nobody
   could read. Black on the same rose is 7.80:1, and it is this theme's own
   convention already (--sbt-on-warning is #000 here for exactly this reason,
   while --sbt-on-accent stays #fff on its darker fill). Scoped to prime-dark:
   `aura` and legacy `dark` carry the same #fb7185 and the same 2.69, but
   restyling a legacy theme is the ruling parked since c72 — NEEDS_USER c75. */
html[data-sbt-theme="prime-dark"] .sbt-bell-badge { color: #000; }
#sbt-bell-menu { min-width: 320px; max-width: 360px; padding: 0; overflow: hidden; }
.sbt-bell-head { display: flex; align-items: center; justify-content: space-between;
  padding: .55rem .8rem; border-bottom: 1px solid var(--sbt-border); }
.sbt-bell-empty { color: var(--sbt-muted); text-align: center; padding: 1.1rem .8rem; }
#sbt-bell-list { max-height: 380px; overflow-y: auto; }
.sbt-bell-item { display: flex; flex-direction: column; gap: 2px; padding: .55rem .8rem;
  color: var(--sbt-text); text-decoration: none; font-size: .84rem;
  border-bottom: 1px solid var(--sbt-border); }
.sbt-bell-item.unread { background: var(--sbt-accent-weak); }
/* hover after .unread so it wins for both read and unread rows */
.sbt-bell-item:hover { background: var(--sbt-surface-2); }
.sbt-bell-item:last-child { border-bottom: 0; }
.sbt-bell-title { display: flex; align-items: center; gap: .45rem; font-weight: 500; }
.sbt-bell-title .si { width: 15px; height: 15px; color: var(--sbt-muted); flex: 0 0 auto; }
.sbt-bell-when { color: var(--sbt-muted); font-size: .72rem; padding-left: calc(15px + .45rem); }

/* On a phone the bell menu is wider than the room to the left of the bell, and
   `.end` pins it to the bell's right edge, so the list ran off the LEFT of the
   screen — where nothing can scroll to it (page overflow stays 0). Dropping
   #sbt-bell to static makes the already-sticky, full-width .sbt-nav the menu's
   containing block, so the menu pins to the viewport instead, and the inherited
   `top: calc(100% + 2px)` now follows the nav's own height — including the
   prime themes' safe-area padding on a notched phone. */
@media (max-width: 640px) {
  #sbt-bell { position: static; }
  #sbt-bell-menu { left: .5rem; right: .5rem; min-width: 0; max-width: none; width: auto; }
}

/* The AI tokens / AI credits chip in .sbt-nav-right opens a 300px-wide menu
   pinned to the chip's right edge, and on a phone that chip sits ~200px from
   the left — so the menu ran off the LEFT of the screen with page overflow 0,
   exactly like the bell did, taking its "Usage details" and "Open AI
   Assistant" buttons with it. The width used to be an inline style, which no
   media query could override; it now lives here so the phone rule can.
   Same remedy as the bell: the parent goes static so the sticky, full-width
   .sbt-nav becomes the containing block and the menu pins to the viewport. */
.sbt-money-menu { min-width: 300px; }
@media (max-width: 640px) {
  .sbt-money-dd { position: static; }
  .sbt-dropdown-menu.sbt-money-menu { left: .5rem; right: .5rem; min-width: 0; max-width: none; width: auto; }
}

/* ==========================================================================
   WO5-3 — the prime shell: spacing, radius, focus, motion, and the
   accessibility floor.

   Three layers, deliberately kept apart:

   A. GLOBAL. The `[hidden]` guard, the focus ring, reduced motion, forced
      colors and prefers-contrast. These are not a look, they are a floor, and
      leaving `light`/`dark`/`aura` without them would be shipping a worse app
      to anyone who has not switched. Where a value differs per theme it goes
      through a token, so the floor is shared and the colour is not.
   B. PRIME TOKENS. The spacing and radius scales. Defined on :root so nothing
      downstream can ever hit an undefined var(), but only CONSUMED by the
      prime-scoped rules below — which is what keeps the three legacy themes
      provably where WO5-1 left them.
   C. PRIME FURNITURE. The shared chrome, re-cut to the scales.
   ========================================================================== */

/* ---- A1. the `hidden` guard (workorder §1b) ------------------------------
   mail.js, chips.js and richtext.js hide everything through the `hidden`
   PROPERTY -- 53 sites in mail.js alone -- and `[hidden]{display:none}` is the
   weakest rule there is, so ANY author rule that sets `display` on the same
   element defeats it silently. Six elements are unguarded today and work only
   because their classes happen not to set display: #ml-ct-empty, #ml-acc-empty,
   #ml-acc-shared-empty (.sbt-empty), #ml-acc-ms, #ml-acc-gmail (.ml-notice),
   #ml-acc-form and #ml-a-shared-row. This lands BEFORE anything gives those
   classes a display value, so it can never regress into a debugging session
   about a panel that will not close. (R334/R384) */
[hidden] { display: none !important; }

/* ---- A2. focus-visible: the first author focus style in this codebase -----
   `outline`, never `box-shadow`: forced-colors mode overrides box-shadow but
   keeps outlines, so a shadow ring vanishes for exactly the users who need it
   most. 3px rather than 2px clears SC 2.4.13's "at least as large as a 2px
   perimeter" without anyone having to measure a curve.

   The ring is NEUTRAL, not the accent (§8a-2 -- Linear overrides its own accent
   ring to 40% black in light mode). An accent ring also breaks the moment a
   user picks a pale colour, which is the whole point of the picker. */
:root { --sbt-focus: rgba(17, 24, 39, .55); }
html[data-sbt-theme="dark"],
html[data-sbt-theme="aura"] { --sbt-focus: rgba(255, 255, 255, .65); }
html[data-sbt-theme="prime-light"] { --sbt-focus: rgba(13, 26, 43, .6); }
html[data-sbt-theme="prime-dark"] { --sbt-focus: rgba(235, 240, 245, .7); }

:focus-visible {
  outline: 3px solid var(--sbt-focus);
  outline-offset: 2px;
  border-radius: 2px;
}
/* the inputs already had a :focus ring that also set outline:none -- keep their
   coloured border for mouse users, but let the real ring through for keyboards */
.sbt-input:focus-visible, .sbt-select:focus-visible, .sbt-textarea:focus-visible {
  outline: 3px solid var(--sbt-focus);
  outline-offset: 2px;
}

/* ---- A3. reduced motion --------------------------------------------------
   The reset must also neutralise scroll-behavior, or a `smooth` set anywhere
   survives it and keeps animating for someone who asked it not to. */
@media (prefers-reduced-motion: reduce) {
  html:focus-within { scroll-behavior: auto !important; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---- A4. forced colors (Windows High Contrast) ---------------------------
   This mode forces `box-shadow: none`. A light theme that separates surfaces
   with elevation alone therefore collapses into one undifferentiated slab --
   the single biggest forced-colors failure for exactly the aesthetic this
   workorder builds, and a business suite has a Windows audience. Everything
   that leans on --sbt-shadow to read as foreground gets a real border here. */
@media (forced-colors: active) {
  :focus-visible { outline-color: Highlight; }
  .sbt-card, .sbt-modal-box, .sbt-dropdown-menu, .sbt-toast,
  .sbt-dropzone, .sbt-table { border: 1px solid CanvasText; }
  .sbt-btn { border: 1px solid ButtonText; }
}

/* ---- A5. prefers-contrast: more ------------------------------------------
   --sbt-border is decorative at 1.27:1 on white and is simply invisible here,
   so it is promoted to a real 3:1 edge and muted text is darkened. Measured on
   surface / bg / surface-2: light border 3.47 / 3.23 / 3.11, muted 7.49 / 6.97
   / 6.71; dark border 3.68 on surface-2 and 3.07 on surface-3, muted 10.05. */
@media (prefers-contrast: more) {
  html[data-sbt-theme="prime-light"] {
    --sbt-border: #7c8ba0;
    --sbt-border-2: #5b6b80;
    --sbt-muted: #46566b;
  }
  html[data-sbt-theme="prime-dark"] {
    --sbt-border: #6e8099;
    --sbt-border-2: #8a97a8;
    --sbt-muted: #c2c9d3;
  }
}

/* ---- B. the scales -------------------------------------------------------
   Spacing is a 4pt grid WITH half-steps: the half-step is not padding, it is
   what produces the density these references actually have (Campsite builds its
   whole rhythm on a 2px grid).

   Density is ONE root multiplier, not a two-value enum -- which is how both
   products that ship a density control do it (Missive derives spacing from type
   size, Radix multiplies every space/font/radius token by [data-scaling]).
   Preferences writes --sbt-density; this is what finally consumes it. The
   fallback of 1 matters: the token is absent until someone chooses.

   Radius working set is 4 / 6 / 8 / 12 / pill. Nothing in a dense list exceeds
   12px. --sbt-radius drops 10px -> 8px (the row-plate and card value) and
   --sbt-radius-sm 8px -> 6px (menu item), with the old 10-12px band kept for
   modals and popovers where it belongs. */
:root {
  --sbt-density: 1;
  --sbt-sp-05: calc(2px * var(--sbt-density));
  --sbt-sp-1:  calc(4px * var(--sbt-density));
  --sbt-sp-15: calc(6px * var(--sbt-density));
  --sbt-sp-2:  calc(8px * var(--sbt-density));
  --sbt-sp-25: calc(10px * var(--sbt-density));
  --sbt-sp-3:  calc(12px * var(--sbt-density));
  --sbt-sp-4:  calc(16px * var(--sbt-density));
  --sbt-sp-5:  calc(20px * var(--sbt-density));
  --sbt-sp-6:  calc(24px * var(--sbt-density));
  --sbt-sp-8:  calc(32px * var(--sbt-density));
  --sbt-radius-xs: 4px;
  --sbt-radius-lg: 12px;
  --sbt-radius-pill: 9999px;
}
html[data-sbt-theme^="prime"] {
  --sbt-radius: 8px;
  --sbt-radius-sm: 6px;
}

/* ---- C. prime furniture --------------------------------------------------
   Scoped at the ROOT, never under #ml-wrap/#tc-wrap: .sbt-chips-menu is
   appended to document.body, so a container-scoped rule would leave body-level
   popups unstyled. */

/* the shell breathes: page padding and card padding move onto the scale */
html[data-sbt-theme^="prime"] .sbt-page-head { margin-bottom: var(--sbt-sp-5); }
html[data-sbt-theme^="prime"] .sbt-card-body { padding: var(--sbt-sp-5); }
html[data-sbt-theme^="prime"] .sbt-modal-box { border-radius: var(--sbt-radius-lg); }
html[data-sbt-theme^="prime"] .sbt-dropdown-menu { border-radius: var(--sbt-radius-lg); padding: var(--sbt-sp-1); }
html[data-sbt-theme^="prime"] .sbt-dropdown-item { border-radius: var(--sbt-radius-sm); }
html[data-sbt-theme^="prime"] .sbt-badge { border-radius: var(--sbt-radius-pill); }
html[data-sbt-theme^="prime"] .sbt-input,
html[data-sbt-theme^="prime"] .sbt-select,
html[data-sbt-theme^="prime"] .sbt-textarea { border-radius: var(--sbt-radius-sm); }
html[data-sbt-theme^="prime"] .sbt-toast { border-radius: var(--sbt-radius); }
/* .sbt-btn is already on the working set at 8px; .sbt-btn-sm's 7px is not, and
   .sbt-dropdown-item's 7px is overridden above. Nothing else in the shared
   furniture carries an off-scale radius. */
html[data-sbt-theme^="prime"] .sbt-btn-sm { border-radius: var(--sbt-radius-sm); }

/* scrollbars: thin and neutral, so a dense list does not carry a heavy grey
   gutter down its whole height */
html[data-sbt-theme^="prime"] * { scrollbar-width: thin; scrollbar-color: var(--sbt-border-2) transparent; }
html[data-sbt-theme^="prime"] ::-webkit-scrollbar { width: 10px; height: 10px; }
html[data-sbt-theme^="prime"] ::-webkit-scrollbar-track { background: transparent; }
html[data-sbt-theme^="prime"] ::-webkit-scrollbar-thumb {
  background: var(--sbt-border-2); border-radius: var(--sbt-radius-pill);
  border: 3px solid transparent; background-clip: content-box;
}
html[data-sbt-theme^="prime"] ::-webkit-scrollbar-thumb:hover { background: var(--sbt-muted); background-clip: content-box; }

/* ---- C2. touch + safe area -----------------------------------------------
   24x24 is the normative AA floor (SC 2.5.8) and the spacing exception is
   "at least 24px centre-to-centre", so dense list furniture -- a star, a flag,
   an unread dot -- may stay 24px at 24px pitch rather than bloating every row.
   44px is the DESIGN target for anything a thumb aims at, which is what this
   block gives the chrome. Applied on a coarse POINTER, not a width: a small
   window on a desktop is still a mouse. */
@media (pointer: coarse) {
  html[data-sbt-theme^="prime"] .sbt-btn,
  html[data-sbt-theme^="prime"] .sbt-dropdown-item,
  html[data-sbt-theme^="prime"] .sbt-nav-link {
    min-height: 44px;
  }
  html[data-sbt-theme^="prime"] .sbt-btn-icon { min-width: 44px; }
  /* .sbt-btn-sm is the deliberately dense variant and it lives inside table rows
     and list furniture across ~30 blades. It measures ~30px, comfortably above
     SC 2.5.8's normative 24px floor, and bloating it to 44px is exactly the "do
     not bloat dense rows" case -- so it is excluded, not overlooked. */
  html[data-sbt-theme^="prime"] .sbt-btn.sbt-btn-sm { min-height: 0; }
}
/* env() is 0 unless the viewport meta carries viewport-fit=cover, and a bare
   env() with no fallback makes the whole calc() invalid on desktop -- so always
   the two-argument form. Padding, not margin, so the bar still paints into the
   inset rather than leaving a bare strip. */
html[data-sbt-theme^="prime"] .sbt-nav { padding-top: env(safe-area-inset-top, 0px); }
html[data-sbt-theme^="prime"] .sbt-nav-inner {
  padding-left: calc(var(--sbt-sp-5) + env(safe-area-inset-left, 0px));
  padding-right: calc(var(--sbt-sp-5) + env(safe-area-inset-right, 0px));
}
html[data-sbt-theme^="prime"] .sbt-toasts {
  top: calc(var(--sbt-sp-4) + env(safe-area-inset-top, 0px));
  right: calc(var(--sbt-sp-4) + env(safe-area-inset-right, 0px));
}

/* manu code for c696 command palette starts here
   The ctrl+K palette (sbt.js SBT.palette). Every colour is a theme token, so it
   follows the five themes and both colour schemes with no per-theme rules of its
   own; the only hard-coded value is the backdrop's shadow, which is a shadow in
   every theme. */
.sbt-cmdk {
  display: none; position: fixed; inset: 0; z-index: 1080;
  background: rgba(15, 23, 42, .45);
  /* Not centred: a box that sits a little above the middle is where the eye
     already is, and it leaves room for the list to grow downwards. */
  padding: 12vh var(--sbt-sp-4) var(--sbt-sp-4);
}
.sbt-cmdk.open { display: block; }
.sbt-cmdk-panel {
  max-width: 38rem; margin: 0 auto;
  background: var(--sbt-surface); color: var(--sbt-text);
  border: 1px solid var(--sbt-border); border-radius: var(--sbt-radius);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .28);
  overflow: hidden;
}
.sbt-cmdk-head {
  display: flex; align-items: center; gap: .6rem;
  padding: .7rem .9rem; border-bottom: 1px solid var(--sbt-border);
}
.sbt-cmdk-head .si { flex: none; color: var(--sbt-muted); }
.sbt-cmdk-input {
  flex: 1 1 auto; min-width: 0; border: 0; outline: 0; background: transparent;
  color: var(--sbt-text); font: inherit; font-size: 1rem; padding: .15rem 0;
}
.sbt-cmdk-kbd {
  flex: none; font-size: .68rem; color: var(--sbt-muted);
  border: 1px solid var(--sbt-border); border-radius: .35rem; padding: .1rem .35rem;
}
.sbt-cmdk-list { max-height: 22rem; overflow-y: auto; padding: .35rem; }
.sbt-cmdk-row {
  display: flex; align-items: baseline; gap: .6rem; width: 100%;
  padding: .55rem .6rem; border: 0; border-radius: var(--sbt-radius-sm);
  background: transparent; color: var(--sbt-text); text-align: left; cursor: pointer;
}
/* One highlight for hover AND for the keyboard's own position, so the mouse and
   the arrow keys cannot disagree about which row Enter would open. */
.sbt-cmdk-row:hover, .sbt-cmdk-row.active { background: var(--sbt-accent-weak); }
.sbt-cmdk-row.active { box-shadow: inset 0 0 0 1px var(--sbt-accent); }
.sbt-cmdk-row-name { flex: 1 1 auto; font-weight: 500; overflow-wrap: anywhere; }
.sbt-cmdk-row-group { flex: none; font-size: .75rem; color: var(--sbt-muted); }
.sbt-cmdk-empty { padding: 1.1rem .9rem; color: var(--sbt-muted); text-align: center; }
/* The trigger reads as a search field on a roomy screen and collapses to its
   icon when the nav bar runs out of room. */
.sbt-cmdk-btn { gap: .45rem; color: var(--sbt-muted); }
.sbt-cmdk-btn .sbt-cmdk-kbd { margin-left: .2rem; }
@media (max-width: 992px) {
  .sbt-cmdk-btn-text, .sbt-cmdk-btn .sbt-cmdk-kbd { display: none; }
}
@media (max-width: 640px) {
  .sbt-cmdk { padding-top: 6vh; }
  .sbt-cmdk-list { max-height: 60vh; }
}
/* manu code for c696 command palette ends here */

/* manu code for c705 link graph starts here */
/* The linked-items rail: a floating chip above the bottom-right corner, and a
   small panel it opens. Chrome, not app UI — it renders on any page that
   declares an identity, so it uses suite tokens only and sits below the
   toast/modal layers (toasts must never be hidden by a rail). */
/* manu code for c706 the rail chip stacks ABOVE the assistant fab starts here */
/* 🔴 MEASURED COLLISION, FOUND BY WALKING IT (c706). #sbtai-fab claims this exact
   corner — 3.5rem square at right/bottom 1.5rem, z-index 1085 — so it covered this
   2.6rem chip COMPLETELY and outranked it: elementFromPoint at the chip's own centre
   returned the fab, and the rail was unreachable on EVERY page of the suite, because
   sbt.blade.php includes both (the widget at :622, this rail at :646). A chip that
   cannot be clicked is not an affordance, so the newcomer yields: the assistant keeps
   the corner and the rail stacks above it.
   ⚠ The bottom MIRRORS THE FAB'S OWN EXPRESSION (team-chat.css: an open chat composer
   lifts the fab by --tc-comp-h) — otherwise the composer would slide the fab back up
   underneath this chip and re-create the collision it is here to prevent. */
#sbt-linked {
  position: fixed;
  right: 1.95rem;                 /* centres the 2.6rem chip on the 3.5rem fab's axis */
  bottom: calc(max(1.5rem, calc(var(--tc-comp-h, 0px) + .75rem)) + 4.1rem);  /* fab 3.5rem + .6rem gap */
  z-index: 1040;
}
/* manu code for c706 the rail chip stacks ABOVE the assistant fab ends here */
.sbt-linked-chip {
  display: flex; align-items: center; justify-content: center; gap: .3rem;
  width: 2.6rem; height: 2.6rem; border-radius: 50%;
  border: 1px solid var(--sbt-border); background: var(--sbt-surface);
  color: var(--sbt-muted); cursor: pointer; box-shadow: var(--sbt-shadow);
  position: relative;
}
.sbt-linked-chip:hover { color: var(--sbt-accent); border-color: var(--sbt-accent); }
.sbt-linked-count {
  position: absolute; top: -.35rem; right: -.35rem; min-width: 1.15rem;
  padding: 0 .3rem; border-radius: var(--sbt-radius-pill);
  background: var(--sbt-accent); color: var(--sbt-on-accent);
  font-size: .68rem; line-height: 1.15rem; text-align: center;
}
.sbt-linked-panel {
  position: absolute; right: 0; bottom: 3.2rem; width: 21rem; max-width: 92vw;
  border: 1px solid var(--sbt-border); border-radius: var(--sbt-radius);
  background: var(--sbt-surface); box-shadow: var(--sbt-shadow-lg);
  display: flex; flex-direction: column; overflow: hidden;
}
.sbt-linked-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: .6rem .75rem; border-bottom: 1px solid var(--sbt-border);
}
.sbt-linked-head strong { display: flex; align-items: center; gap: .4rem; font-size: .85rem; }
.sbt-linked-list { max-height: 16rem; overflow-y: auto; padding: .45rem .6rem; }
.sbt-linked-row {
  display: flex; align-items: baseline; gap: .45rem;
  padding: .3rem 0; font-size: .82rem;
}
.sbt-linked-kind { flex: none; color: var(--sbt-muted); font-size: .72rem; }
.sbt-linked-title { flex: 1 1 auto; color: var(--sbt-text); overflow-wrap: anywhere; text-decoration: none; }
.sbt-linked-title:hover { color: var(--sbt-accent); }
.sbt-linked-app, .wk-link-app {
  display: inline-block; padding: 0 .3rem; border-radius: var(--sbt-radius-xs);
  background: var(--sbt-accent-weak); color: var(--sbt-accent);
  font-size: .68rem; text-transform: capitalize; vertical-align: baseline;
}
.sbt-linked-meta { flex: none; color: var(--sbt-muted); font-size: .72rem; }
.sbt-linked-x {
  flex: none; border: 0; background: transparent; color: var(--sbt-muted);
  cursor: pointer; padding: 0 .1rem;
}
.sbt-linked-x:hover { color: var(--sbt-danger); }
.sbt-linked-empty { margin: 0; padding: .5rem 0; color: var(--sbt-muted); font-size: .8rem; text-align: center; }
.sbt-linked-add {
  display: flex; gap: .4rem; padding: .55rem .6rem; border-top: 1px solid var(--sbt-border);
}
.sbt-linked-add .sbt-input { flex: 1 1 auto; }
.sbt-linked-results { max-height: 11rem; overflow-y: auto; padding: .3rem .6rem .55rem; }
.sbt-linked-opt {
  display: block; width: 100%; text-align: left; border: 0; cursor: pointer;
  border-radius: var(--sbt-radius-sm); background: transparent; color: var(--sbt-text);
  padding: .4rem .45rem; font-size: .8rem; overflow-wrap: anywhere;
}
.sbt-linked-opt:hover { background: var(--sbt-accent-weak); }
@media (max-width: 640px) {
  /* manu code for c706: ⛔ NO position override here. The fab it stacks on is
     width-invariant (no @media touches #sbtai-fab), so pulling the chip back to the
     corner on a narrow screen would restore the very collision fixed above. */
  .sbt-linked-panel { width: 19rem; }
}
/* manu code for c705 link graph ends here */

/* manu code for a1 shared a11y layer starts here */
/* ==========================================================================
   SHARED A11Y LAYER (A1, 17-Oct-2026): the keyboard focus ring and the button
   labels readable in every look, a dialog that holds focus itself, and the
   toast's new action button (sbt.js, the a11y block at its end). Every ratio
   below is WCAG 2.1 (text 4.5:1; the focus ring 3:1), measured on the parent
   commit and pinned by tests/golden/shared_a11y_layer_test.js.
   ========================================================================== */

/* 1. The focus ring in the two dark looks that had none.
   WHY: bluebell-dark and fruits-dark never set --sbt-focus, so they kept the
   light look's dark ring (rgba 17,24,39 at .55) on their own dark ground:
   1.01:1, the ring could not be seen at all.
   HOW: each look's own text colour at 70%, the recipe prime-dark already uses
   (its #ebf0f5 at .7). On --sbt-bg / --sbt-surface: bluebell-dark 8.11 / 7.43,
   fruits-dark 8.15 / 7.72 (and still 5.79 / 6.48 on their --sbt-surface-3). */
html[data-sbt-theme="bluebell-dark"] { --sbt-focus: rgba(236, 239, 251, .7); }
html[data-sbt-theme="fruits-dark"] { --sbt-focus: rgba(244, 237, 241, .7); }

/* 2. The main button's label.
   WHY: .sbt-btn-primary paints a hard-coded white label (the buttons section
   above). Where a look's accent is light, white fails: dark 4.47:1 (2.98:1 on
   hover), fruits-dark 2.84:1 (2.52:1). As a LINK (a.sbt-btn-primary) both
   fruits looks were worse: fruits.css's link colour (grape) outranks the white
   rule, so the label was grape on raspberry — 1.21:1 and 1.38:1.
   HOW: in those looks only, the label takes --sbt-on-accent, the colour every
   look defines for text ON its accent: dark black 4.70:1 (7.04:1 on hover),
   fruits-dark deep plum 6.04:1 (6.82:1), fruits-light white 5.28:1 (the link
   only; its <button> already passed). These selectors outrank both the white
   rules and the fruits link rule. aura keeps white on its gradient (black would
   be 3.34:1), and the looks that already pass are not touched. */
html[data-sbt-theme="dark"] .sbt-btn-primary,
html[data-sbt-theme="dark"] .sbt-btn-primary:hover,
html[data-sbt-theme="dark"] .sbt-btn-primary:active,
html[data-sbt-theme="dark"] .sbt-body a.sbt-btn-primary,
html[data-sbt-theme="dark"] .sbt-body a.sbt-btn-primary:hover,
html[data-sbt-theme="dark"] .sbt-body a.sbt-btn-primary:active,
html[data-sbt-theme="fruits-dark"] .sbt-btn-primary,
html[data-sbt-theme="fruits-dark"] .sbt-btn-primary:hover,
html[data-sbt-theme="fruits-dark"] .sbt-btn-primary:active,
html[data-sbt-theme="fruits-dark"] .sbt-body a.sbt-btn-primary,
html[data-sbt-theme="fruits-dark"] .sbt-body a.sbt-btn-primary:hover,
html[data-sbt-theme="fruits-dark"] .sbt-body a.sbt-btn-primary:active,
html[data-sbt-theme="fruits-light"] .sbt-body a.sbt-btn-primary,
html[data-sbt-theme="fruits-light"] .sbt-body a.sbt-btn-primary:hover,
html[data-sbt-theme="fruits-light"] .sbt-body a.sbt-btn-primary:active { color: var(--sbt-on-accent); }

/* 3. The label on a solid danger fill, as one token.
   WHY: the design rule (no hex in rules), and one name for "text on
   --sbt-danger", so a later rule cannot pick a different colour per look.
   HOW: white where the danger fill is a deep red (the light looks); black
   where it is a light rose (prime-dark — which already paints black, see the
   buttons section above; this only names it — bluebell-dark, fruits-dark).
   dark and aura keep white: their 2.69:1 is the parked c72 ruling, and no
   rule here uses this token in those two looks. */
:root { --sbt-on-danger: #ffffff; }
html[data-sbt-theme="prime-dark"],
html[data-sbt-theme="bluebell-dark"],
html[data-sbt-theme="fruits-dark"] { --sbt-on-danger: #000000; }

/* 4. The danger button labels in bluebell-dark and fruits-dark (new; dark and
   aura are the parked ruling and are not touched).
   WHY: their --sbt-danger is a light rose and white on it is 2.47:1 / 2.42:1 —
   on the solid button (the Delete of every danger confirm) and on the light
   danger button's hover, which fills with the same rose.
   HOW: the label takes --sbt-on-danger (black): 8.52:1 / 8.67:1, and 7.25:1 /
   7.37:1 under the solid button's hover filter (brightness .92). */
html[data-sbt-theme="bluebell-dark"] .sbt-btn-danger-solid,
html[data-sbt-theme="bluebell-dark"] .sbt-btn-danger-solid:hover,
html[data-sbt-theme="bluebell-dark"] .sbt-btn-danger-solid:active,
html[data-sbt-theme="bluebell-dark"] .sbt-btn-danger:hover,
html[data-sbt-theme="fruits-dark"] .sbt-btn-danger-solid,
html[data-sbt-theme="fruits-dark"] .sbt-btn-danger-solid:hover,
html[data-sbt-theme="fruits-dark"] .sbt-btn-danger-solid:active,
html[data-sbt-theme="fruits-dark"] .sbt-btn-danger:hover { color: var(--sbt-on-danger); }

/* 5. The solid danger button keeps its red fill on hover.
   WHY: its hover rule sets a filter but no background, so the generic
   .sbt-btn:hover repainted it in --sbt-surface-3: white on a pale grey,
   1.24:1 (bluebell) and 1.31:1 (fruits-light), and in the two dark looks the
   Delete button stopped looking like one. prime-light, light and prime-dark
   already keep the fill (the buttons section above).
   HOW: the same fill in the other four looks outside the parked ruling; the
   hover filter (brightness .92) still marks the hover. With it, bluebell's
   white label is 5.34:1 and fruits-light's 6.16:1. dark and aura: untouched. */
html[data-sbt-theme="bluebell"] .sbt-btn-danger-solid:hover,
html[data-sbt-theme="bluebell-dark"] .sbt-btn-danger-solid:hover,
html[data-sbt-theme="fruits-light"] .sbt-btn-danger-solid:hover,
html[data-sbt-theme="fruits-dark"] .sbt-btn-danger-solid:hover { background: var(--sbt-danger); }

/* 6. A dialog that took focus itself (sbt.js gives it tabindex="-1" when its
   body has no field).
   WHY: the dialog box is only where focus rests until the next Tab, not a
   control; and the global :focus-visible rule would also square its corners
   to 2px for as long as it holds focus.
   HOW: no ring on the box itself, and its own 14px corners back (.sbt-modal,
   the modal section above). Every control inside keeps the ring. */
.sbt-modal[tabindex="-1"]:focus,
.sbt-modal[tabindex="-1"]:focus-visible { outline: none; border-radius: 14px; }

/* 7. The toast's action button: SBT.toast(type, msg, { action: { label, onClick } }).
   WHY: an Undo must be a real button that a person can see, reach and read.
   HOW: a text button in the look's accent text colour, which every look makes
   for text on a surface: 4.5:1 or more on the toast in all nine looks (aura's
   toast is #1e293b: 7.34:1). At least 24px tall — the SC 2.5.8 floor, fixed so
   the density setting can never shrink it below — with its padding and corners
   from the scale. Hover underlines it; the global :focus-visible ring shows
   the keyboard. */
.sbt-toast-action {
  flex: none; margin-left: auto; min-height: 24px;
  padding: var(--sbt-sp-1) var(--sbt-sp-2);
  border: 0; border-radius: var(--sbt-radius-sm);
  background: transparent; color: var(--sbt-accent-text);
  font: inherit; font-weight: 600; cursor: pointer;
}
.sbt-toast-action:hover { text-decoration: underline; }
.sbt-toast-action:disabled { cursor: default; }
/* manu code for a1 shared a11y layer ends here */
/* manu code for a1 tasks visual system starts here */
/* ---- D. the type scale and the click-target sizes ---------------------------
   WHY: Tasks (and every module that follows) needs ONE set of font sizes and
   target sizes, so a new look or a density change reaches it, and nothing is
   ever drawn under 12 px (the user's rule: easy to see and understand).
   HOW: six font steps, 12 px upwards, NOT multiplied by --sbt-density: compact
   spacing must never shrink text below 12 px. Icon-only buttons are a 32 px
   square (--sbt-target); nothing clickable is smaller than 24 px
   (--sbt-target-min, WCAG 2.5.8). */
:root {
  --sbt-fs-xs: .75rem;     /* 12 px: meta, pills, counts */
  --sbt-fs-sm: .8125rem;   /* 13 px: secondary text, menus */
  --sbt-fs-md: .875rem;    /* 14 px: body, card titles */
  --sbt-fs-lg: 1rem;       /* 16 px: section titles */
  --sbt-fs-xl: 1.125rem;   /* 18 px */
  --sbt-fs-2xl: 1.375rem;  /* 22 px: page titles */
  --sbt-target: 32px;
  --sbt-target-min: 24px;
}
/* manu code for a1 tasks visual system ends here */
/* manu code for a1 shared a11y layer prime-dark starts here */
/* WHY: prime-dark's light danger button (.sbt-btn-danger) fills with its light
   rose on hover and keeps a white label: 2.69:1, unreadable (found by the A1-T1
   review). prime-dark is not part of the parked dark/aura ruling.
   HOW: the label takes --sbt-on-danger (black in prime-dark, set in the a11y
   layer above), the same fix bluebell-dark and fruits-dark got. */
html[data-sbt-theme="prime-dark"] .sbt-btn-danger:hover { color: var(--sbt-on-danger); }
/* manu code for a1 shared a11y layer prime-dark ends here */
/* manu code for a1 look menu starts here */
/* WHY: the user's order (19-Oct-2026 16:18 IST): the look button in the top bar is now a dropdown with
   names (layouts/sbt.blade.php, #sbt-look). Its trigger is wider than the old square icon button, and
   the top bar must not wrap on a laptop.
   HOW: the trigger keeps the old button's height (2.1rem, as .sbt-btn-icon) and puts the icon, the name
   and a chevron in one row. The name shows only from 1200 px wide, where the top bar has room; below
   that the trigger is the icon and the chevron, and its aria-label still says the look's name. The menu
   is a little narrower than the shared 220px and scrolls if a short window cannot show all nine looks.
   Colours, the tick and the focus ring are the shared ones (.sbt-dropdown-item, :focus-visible). */
.sbt-look-btn { display: inline-flex; align-items: center; gap: .35rem; height: 2.1rem; padding: .38rem .55rem; }
.sbt-look-name { display: none; max-width: 9rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (min-width: 1200px) { .sbt-look-name { display: inline; } }
.sbt-look-menu { min-width: 200px; max-height: calc(100vh - 5rem); overflow-y: auto; }
/* manu code for a1 look menu ends here */

/* manu code for a1 summer kit starts here */
/* ---- the Summer kit: one set of soft colours, one ribbon and a few quiet motions for Tasks, Team Chat,
   Email and the Files Manager (A1 s23, 20-Oct-2026) ----------------------------------------------------
   WHY: the user (20-Oct): "implement the same for chat system, email system, filemanager system … ribbons …
   colors like maybe monday.com … touches and hints of colors at places and ui looking less bland. better
   shadows/sections switching and filling css animations when clicked on ribbon elements. subtle but nothing
   that's already working should get affected … in an efficient global manner that doesn't bonk other
   themes. summer could be light and dark."
   HOW: (1) Nine soft hues as tokens. Summer (prime-light) gets soft light pairs (the same values as the
   Tasks board's tag colours) and its dark partner (prime-dark) gets deep grounds with light inks. Every
   other look maps all nine to its OWN accent chip, so those looks keep their colours. An element names its
   hue with data-sbt-hue="purple|pink|orange|yellow|lime|green|aqua|blue|grey" and reads --sbt-hue-bg /
   --sbt-hue-ink. (2) .sbt-ribbon: the Office-style strip of square tiles (an icon over a short word, in
   captioned groups) that Tasks has as .wk-ribbon, as shared classes. It is a LAYOUT, the same in every
   look; a look changes only its colours. (3) Motions: a tile "fills" with its hue from the middle when
   pointed at or picked, its bottom line grows from the middle when picked, a press dips it by 1 px, and a
   switched panel fades up 4 px (SBT.kitIn in sbt.js). All motion stops when the person asks the system for
   less motion. (4) Soft cards: --sbt-kit-card-* (Summer: white card, ring-first shadow, a lift on hover;
   other looks: the look's own surface and border, no shadow). New classes and tokens only: no existing
   rule of this sheet changes. Colours (hex) only inside token definitions. */
/* s43 (23-Oct-2026, the user's ruling): Winter is a look of its own, drawn as prime-dark plus the mark
   data-sbt-look="prime-winter" (User::UI_LOOK_BASE), and plain Prime Dark is back to master's look. So every "prime"
   selector in A1's Summer/Winter styling blocks carries a :where(): [data-sbt-theme^="prime"]:where(not prime-dark, or
   the mark) = Summer or Winter only; [data-sbt-theme="prime-dark"]:where(the mark) = Winter only. :where() adds no
   specificity, so Summer and Winter cascade exactly as before; A1's layout and fix blocks still serve every prime look. */
:root {
  --sbt-hue-purple-bg: var(--sbt-accent-weak); --sbt-hue-purple-ink: var(--sbt-accent-text);
  --sbt-hue-pink-bg: var(--sbt-accent-weak);   --sbt-hue-pink-ink: var(--sbt-accent-text);
  --sbt-hue-orange-bg: var(--sbt-accent-weak); --sbt-hue-orange-ink: var(--sbt-accent-text);
  --sbt-hue-yellow-bg: var(--sbt-accent-weak); --sbt-hue-yellow-ink: var(--sbt-accent-text);
  --sbt-hue-lime-bg: var(--sbt-accent-weak);   --sbt-hue-lime-ink: var(--sbt-accent-text);
  --sbt-hue-green-bg: var(--sbt-accent-weak);  --sbt-hue-green-ink: var(--sbt-accent-text);
  --sbt-hue-aqua-bg: var(--sbt-accent-weak);   --sbt-hue-aqua-ink: var(--sbt-accent-text);
  --sbt-hue-blue-bg: var(--sbt-accent-weak);   --sbt-hue-blue-ink: var(--sbt-accent-text);
  --sbt-hue-grey-bg: var(--sbt-accent-weak);   --sbt-hue-grey-ink: var(--sbt-accent-text);
  /* an element with no hue of its own: the look's accent chip */
  --sbt-hue-bg: var(--sbt-accent-weak);
  --sbt-hue-ink: var(--sbt-accent-text);
  /* the ribbon strip and its tiles */
  --sbt-rb-bg: var(--sbt-surface);
  --sbt-rb-border: var(--sbt-border);
  --sbt-rb-shadow: none;
  --sbt-rb-radius: var(--sbt-radius-lg, 12px);
  --sbt-rb-tile-w: 64px;
  --sbt-rb-tile-h: 56px;
  --sbt-rb-tile-w-sm: 56px;
  --sbt-rb-tile-h-sm: 48px;
  --sbt-rb-ic: 22px;
  --sbt-rb-cap-ink: var(--sbt-muted);
  --sbt-rb-new-bg: var(--sbt-accent);
  --sbt-rb-new-ink: var(--sbt-on-accent);
  --sbt-rb-new-hover: var(--sbt-accent-strong);
  /* soft cards (Summer and its dark partner: a ring-first shadow and a lift on hover) */
  --sbt-kit-card-bg: var(--sbt-surface);
  --sbt-kit-card-border: var(--sbt-border);
  --sbt-kit-card-shadow: none;
  --sbt-kit-card-shadow-hover: none;
  --sbt-kit-card-radius: var(--sbt-radius-lg, 12px);
  /* motion */
  --sbt-kit-dur: .18s;
  --sbt-kit-ease: cubic-bezier(.2, .7, .3, 1);
}
html[data-sbt-theme="prime-light"] {
  --sbt-hue-purple-bg: #eee6ff; --sbt-hue-purple-ink: #5a2db0;
  --sbt-hue-pink-bg: #ffe4f0;   --sbt-hue-pink-ink: #a2215d;
  --sbt-hue-orange-bg: #ffe9d9; --sbt-hue-orange-ink: #9a4100;
  --sbt-hue-yellow-bg: #fff3bf; --sbt-hue-yellow-ink: #6e5300;
  --sbt-hue-lime-bg: #ebf8cc;   --sbt-hue-lime-ink: #3d6000;
  --sbt-hue-green-bg: #daf5e3;  --sbt-hue-green-ink: #11683a;
  --sbt-hue-aqua-bg: #d3f4f1;   --sbt-hue-aqua-ink: #08645f;
  --sbt-hue-blue-bg: #dfecff;   --sbt-hue-blue-ink: #1b58bb;
  --sbt-hue-grey-bg: #e8edf3;   --sbt-hue-grey-ink: #3a4a5e;
  --sbt-rb-shadow: var(--sbt-shadow);
  --sbt-kit-card-shadow: var(--sbt-shadow);
  --sbt-kit-card-shadow-hover: var(--sbt-shadow-lg);
}
/* Summer's dark partner: deep grounds (17% of each hue over the dark card) with light inks;
   ink on its ground 6.86-9.02:1, ink on the card 9.08-13.46:1 */
html[data-sbt-theme="prime-dark"]:where([data-sbt-look="prime-winter"]) {
  --sbt-hue-purple-bg: #30314a; --sbt-hue-purple-ink: #c4b5fd;
  --sbt-hue-pink-bg: #3d2c3e;   --sbt-hue-pink-ink: #f9a8d4;
  --sbt-hue-orange-bg: #3f322a; --sbt-hue-orange-ink: #fdba74;
  --sbt-hue-yellow-bg: #3e3c23; --sbt-hue-yellow-ink: #fde68a;
  --sbt-hue-lime-bg: #304029;   --sbt-hue-lime-ink: #bef264;
  --sbt-hue-green-bg: #1d3d3a;  --sbt-hue-green-ink: #6ee7b7;
  --sbt-hue-aqua-bg: #1c3d40;   --sbt-hue-aqua-ink: #5eead4;
  --sbt-hue-blue-bg: #24354a;   --sbt-hue-blue-ink: #93c5fd;
  --sbt-hue-grey-bg: #2d353f;   --sbt-hue-grey-ink: #cbd5e1;
  --sbt-rb-shadow: var(--sbt-shadow);
  --sbt-kit-card-shadow: var(--sbt-shadow);
  --sbt-kit-card-shadow-hover: var(--sbt-shadow-lg);
}
[data-sbt-hue="purple"] { --sbt-hue-bg: var(--sbt-hue-purple-bg); --sbt-hue-ink: var(--sbt-hue-purple-ink); }
[data-sbt-hue="pink"]   { --sbt-hue-bg: var(--sbt-hue-pink-bg);   --sbt-hue-ink: var(--sbt-hue-pink-ink); }
[data-sbt-hue="orange"] { --sbt-hue-bg: var(--sbt-hue-orange-bg); --sbt-hue-ink: var(--sbt-hue-orange-ink); }
[data-sbt-hue="yellow"] { --sbt-hue-bg: var(--sbt-hue-yellow-bg); --sbt-hue-ink: var(--sbt-hue-yellow-ink); }
[data-sbt-hue="lime"]   { --sbt-hue-bg: var(--sbt-hue-lime-bg);   --sbt-hue-ink: var(--sbt-hue-lime-ink); }
[data-sbt-hue="green"]  { --sbt-hue-bg: var(--sbt-hue-green-bg);  --sbt-hue-ink: var(--sbt-hue-green-ink); }
[data-sbt-hue="aqua"]   { --sbt-hue-bg: var(--sbt-hue-aqua-bg);   --sbt-hue-ink: var(--sbt-hue-aqua-ink); }
[data-sbt-hue="blue"]   { --sbt-hue-bg: var(--sbt-hue-blue-bg);   --sbt-hue-ink: var(--sbt-hue-blue-ink); }
[data-sbt-hue="grey"]   { --sbt-hue-bg: var(--sbt-hue-grey-bg);   --sbt-hue-ink: var(--sbt-hue-grey-ink); }

/* the ribbon: captioned groups of square tiles on one card-like strip */
.sbt-ribbon {
  display: flex; flex-wrap: wrap; align-items: stretch; row-gap: var(--sbt-sp-2);
  padding: var(--sbt-sp-2) var(--sbt-sp-2) var(--sbt-sp-15);
  background: var(--sbt-rb-bg); border: 1px solid var(--sbt-rb-border); border-radius: var(--sbt-rb-radius); box-shadow: var(--sbt-rb-shadow);
}
.sbt-rb-group {
  display: flex; flex-direction: column; align-items: center; justify-content: space-between; gap: var(--sbt-sp-1);
  padding: 0 var(--sbt-sp-3); border-left: 1px solid var(--sbt-rb-border); min-width: 0;
}
.sbt-rb-group:first-child { border-left: 0; padding-left: var(--sbt-sp-1); }
.sbt-rb-tiles { display: flex; align-items: center; gap: var(--sbt-sp-1); }
.sbt-rb-cap { font-size: var(--sbt-fs-xs); line-height: 1.25; color: var(--sbt-rb-cap-ink); white-space: nowrap; user-select: none; }
/* a tile: an icon over a short word; quiet at rest. Its hue fills it from the middle (::before) and its
   bottom line grows from the middle when it is picked (::after); both layers sit under the words */
.sbt-rb-btn {
  position: relative; isolation: isolate; display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sbt-sp-1); min-width: var(--sbt-rb-tile-w); height: var(--sbt-rb-tile-h); margin: 0; padding: var(--sbt-sp-1) var(--sbt-sp-2);
  border: 1px solid transparent; border-radius: var(--sbt-radius); background: transparent; color: var(--sbt-text-2);
  font-family: inherit; font-size: var(--sbt-fs-xs); font-weight: 500; line-height: 1.2; white-space: nowrap; cursor: pointer;
  text-decoration: none; transition: color var(--sbt-kit-dur) var(--sbt-kit-ease), transform .08s ease;
}
.sbt-rb-btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit; background: var(--sbt-hue-bg);
  opacity: 0; transform: scale(.82); transition: opacity var(--sbt-kit-dur) var(--sbt-kit-ease), transform var(--sbt-kit-dur) var(--sbt-kit-ease);
}
.sbt-rb-btn::after {
  content: ""; position: absolute; left: 16%; right: 16%; bottom: 0; height: 2px; border-radius: 2px; background: var(--sbt-hue-ink);
  transform: scaleX(0); transition: transform var(--sbt-kit-dur) var(--sbt-kit-ease);
}
.sbt-rb-btn > .si { width: var(--sbt-rb-ic); height: var(--sbt-rb-ic); flex: 0 0 auto; color: var(--sbt-hue-ink); }
.sbt-rb-label { display: inline-flex; align-items: center; gap: var(--sbt-sp-05); }
.sbt-rb-btn .sbt-rb-caret { width: .75rem; height: .75rem; }
.sbt-rb-btn:hover { color: var(--sbt-text); }
.sbt-rb-btn:hover::before { opacity: 1; transform: none; }
/* picked (a view or a tab), open (a menu), on (a toggle): the hue's ground, its ink and the bottom line */
.sbt-rb-btn[aria-selected="true"], .sbt-rb-btn[aria-expanded="true"], .sbt-rb-btn[aria-pressed="true"], .sbt-rb-btn.active {
  color: var(--sbt-hue-ink); font-weight: 600;
}
.sbt-rb-btn[aria-selected="true"]::before, .sbt-rb-btn[aria-expanded="true"]::before,
.sbt-rb-btn[aria-pressed="true"]::before, .sbt-rb-btn.active::before { opacity: 1; transform: none; }
.sbt-rb-btn[aria-selected="true"]::after, .sbt-rb-btn[aria-expanded="true"]::after,
.sbt-rb-btn[aria-pressed="true"]::after, .sbt-rb-btn.active::after { transform: scaleX(1); }
.sbt-rb-btn:active:not(:disabled):not([aria-disabled="true"]) { transform: translateY(1px); }
.sbt-rb-btn:focus-visible { outline: 3px solid var(--sbt-focus); outline-offset: 2px; }
.sbt-rb-btn:disabled, .sbt-rb-btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.sbt-rb-btn:disabled::before, .sbt-rb-btn[aria-disabled="true"]::before { opacity: 0; }
/* the one filled tile of a ribbon (New task, Compose, New chat, Upload) */
.sbt-rb-new { min-width: calc(var(--sbt-rb-tile-w) + var(--sbt-sp-4)); background: var(--sbt-rb-new-bg); color: var(--sbt-rb-new-ink); font-weight: 600; }
.sbt-rb-new::before, .sbt-rb-new::after { display: none; }
.sbt-rb-new > .si { color: inherit; }
.sbt-rb-new:hover { background: var(--sbt-rb-new-hover); color: var(--sbt-rb-new-ink); }
/* a count on a tile's corner, ringed off the tile */
.sbt-rb-bubble {
  position: absolute; top: calc(var(--sbt-sp-1) * -1); right: calc(var(--sbt-sp-1) * -1); z-index: 1;
  min-width: 1.15rem; height: 1.15rem; padding: 0 .3rem; border-radius: var(--sbt-radius-pill, 9999px);
  display: inline-flex; align-items: center; justify-content: center; font-size: .6875rem; font-weight: 600; line-height: 1;
  background: var(--sbt-surface-3); color: var(--sbt-text-2); box-shadow: 0 0 0 2px var(--sbt-rb-bg);
}
.sbt-rb-bubble:empty { display: none; }
.sbt-rb-btn.active .sbt-rb-bubble, .sbt-rb-btn[aria-selected="true"] .sbt-rb-bubble { background: var(--sbt-accent); color: var(--sbt-on-accent); }
/* a laptop at 1024 px: slimmer tiles so a ribbon still fits one line */
@media (max-width: 1199px) {
  :root { --sbt-rb-tile-w: 56px; }
  .sbt-rb-group { padding: 0 var(--sbt-sp-2); }
  .sbt-rb-btn { padding: var(--sbt-sp-1) var(--sbt-sp-15); }
}
/* a tablet: the groups may wrap, so no dividing line at a line's start */
@media (max-width: 999px) and (min-width: 768px) {
  .sbt-rb-group { border-left-width: 0; }
}
/* a phone: smaller tiles, no captions, the strip scrolls sideways inside itself (never the page) */
@media (max-width: 767px) {
  .sbt-ribbon { flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; padding: var(--sbt-sp-15); scrollbar-width: thin; }
  .sbt-rb-group { flex: 0 0 auto; padding: 0 var(--sbt-sp-2); }
  .sbt-rb-cap { display: none; }
  .sbt-rb-btn { min-width: var(--sbt-rb-tile-w-sm); height: var(--sbt-rb-tile-h-sm); }
  .sbt-rb-new { min-width: calc(var(--sbt-rb-tile-w-sm) + var(--sbt-sp-2)); }
}

/* a soft card (a section, a tile, a file): Summer and its dark partner lift it a little on hover */
.sbt-kit-card {
  background: var(--sbt-kit-card-bg); border: 1px solid var(--sbt-kit-card-border); border-radius: var(--sbt-kit-card-radius);
  box-shadow: var(--sbt-kit-card-shadow); transition: box-shadow var(--sbt-kit-dur) var(--sbt-kit-ease), transform var(--sbt-kit-dur) var(--sbt-kit-ease);
}
.sbt-kit-card.sbt-kit-lift:hover { box-shadow: var(--sbt-kit-card-shadow-hover); }
/* a small rounded-square chip in an element's hue, for an icon before a heading or a name */
.sbt-hue-chip {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 1.5rem; height: 1.5rem;
  border-radius: var(--sbt-radius-sm); background: var(--sbt-hue-bg); color: var(--sbt-hue-ink);
}
.sbt-hue-chip .si { width: .95rem; height: .95rem; }
/* a switched panel fades up 4 px (SBT.kitIn adds the class and takes it off when the motion ends) */
@keyframes sbt-kit-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.sbt-kit-in { animation: sbt-kit-in var(--sbt-kit-dur) var(--sbt-kit-ease) both; }
@media (prefers-reduced-motion: reduce) {
  .sbt-rb-btn, .sbt-rb-btn::before, .sbt-rb-btn::after, .sbt-kit-card { transition: none; }
  .sbt-rb-btn:active:not(:disabled):not([aria-disabled="true"]) { transform: none; }
  .sbt-kit-in { animation: none; }
}
/* manu code for a1 summer kit ends here */

/* manu code for a1 summer glass starts here */
/* ---- Summer + Winter: wallpaper, glass, glow, the app's name in the top bar, the AI meter (A1 s31, 21-Oct-2026) ------
   WHY: the user (21-Oct 01:53 IST): "glassmorphism on cards. a subtle wallpaper and proper shadows and glow effects.
   rounded borders … summer should have default accent that's better … the top title … next to my cloud logo separated
   by pipes … the weekly token … in top bar … a better animated bar … from now on summer will have another theme called
   winter … summer and winter are only two that we work on and no other theme should be touched."
   Winter is the old Prime Dark (same key, prime-dark), renamed: Summer's colouring after dark.
   HOW: (1) tokens for the two looks only (html[data-sbt-theme="prime-light" | "prime-dark"]). The other seven looks never
   define them: a rule that uses one either sits under html[data-sbt-theme^="prime"] or writes var(--x, <today's value>).
   (2) the wallpaper: a fixed layer behind the page (body::before), pure CSS, over the old ground colour.
   (3) the glass kit (.sbt-glass, .sbt-glass-strong, .sbt-glass-card, .sbt-glow-hover) and the shared frame in glass:
   the top bar, menus, cards, dialogs, toasts, buttons. Blur only on big containers (never a card or a dialog: a blurred
   box also becomes the box its position:fixed children are placed in). (4) the app's name in the top bar, the AI meter
   and the top-bar slot (layouts/sbt.blade.php adds them; outside Summer/Winter they are hidden). (5) the duotone Fluent
   icons of the sbt.js block "a1 summer icons" and their small moves. Every move stops under "reduce motion"; colours
   (hex / rgb) only inside token definitions.
   s34 (21-Oct-2026, A1 fix round): --sbt-on-app added to both token blocks of section 2: the words on a module fill.
   accent.js rewrites --sbt-on-accent to black for a person's light accent pick, and black fails on the module gradients
   (reviewer s33, FC1); --sbt-on-app is never rewritten. The top bar's muted words got their own ink in the block
   "a1 s34 bar ink" at the end of this file. */
/* s43 (23-Oct-2026): every "prime" selector here carries a :where() = Summer or Winter only (plain Prime Dark is back
   to master's look); why and how: sbt.css "a1 summer kit". */

/* 1. the accent: Summer's default is azure -> violet (white on #2f5bea 5.52:1, on #6d3df0 5.87:1, on the hover #2547c9
   7.44:1); Winter keeps the pair, lifted for the dark (light ink #8ea8ff; fills dark enough for white words). A person's
   own accent still wins: accent.js writes these tokens INLINE on <html>, which beats every sheet, and the gradient is
   built from --sbt-accent. The Preferences swatches (.sbt-theme-scope) preview the same values. */
html[data-sbt-theme="prime-light"],
.sbt-theme-scope[data-sbt-theme="prime-light"] {
  --sbt-accent: #2f5bea;
  --sbt-accent-strong: #2547c9;
  --sbt-accent-2: #6d3df0;
  --sbt-accent-grad: linear-gradient(135deg, var(--sbt-accent) 0%, var(--sbt-accent-2) 100%);
  --sbt-accent-weak: #eef2fe;
  --sbt-accent-tint: #e3eafd;
  --sbt-accent-text: #2f5bea;
  --sbt-accent-bright: #5b7ff2;
  --sbt-accent-vivid: #4a74f5;
  --sbt-nav-active-border: #2f5bea;
  --sbt-on-accent: #ffffff;
}
html[data-sbt-theme="prime-dark"]:where([data-sbt-look="prime-winter"]),
.sbt-theme-scope[data-sbt-theme="prime-dark"]:where([data-sbt-look="prime-winter"]) {
  --sbt-accent: #3f5fe8;
  --sbt-accent-strong: #4567f0;
  --sbt-accent-2: #7048e8;
  --sbt-accent-grad: linear-gradient(135deg, var(--sbt-accent) 0%, var(--sbt-accent-2) 100%);
  --sbt-accent-weak: rgba(120, 146, 255, .16);
  --sbt-accent-tint: rgba(120, 146, 255, .26);
  --sbt-accent-text: #8ea8ff;
  --sbt-accent-bright: #8ea8ff;
  --sbt-accent-vivid: #8ea8ff;
  --sbt-nav-active-border: #8ea8ff;
  --sbt-on-accent: #ffffff;
}
/* while a picked accent is on (the inline style accent.js writes holds "--sbt-accent:"), the gradient's second stop is the
   pick's own stronger step and the glow takes the pick's colour, so nothing of the default azure / violet is left */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"])[style*="--sbt-accent:"] {
  --sbt-accent-2: var(--sbt-accent-strong);
  --sbt-glow-c: color-mix(in srgb, var(--sbt-accent) 30%, transparent);
}

/* 2. the wallpaper, glass, glow, module and meter tokens.
   Wallpaper: layer 1 is a faint dot grid (1.5 px dots on a 22 px grid); the others are big soft blobs written
   radial-gradient(<w>vmax <h>vmax at <x>% <y>%, <colour>, transparent <stop>%) over the old ground (--sbt-wall-base).
   tests/golden/summer_glass_test.js reads that shape to find the darkest and lightest points (overlaps included).
   Glass: --sbt-glass-bg for panels, -strong for dense content (lists, tables, cards, the top bar), -solid for what can
   float over ANY content (menus, dialogs, toasts): almost opaque, because a menu inside the blurred top bar cannot blur
   the page under it and nothing should show through behind its words.
   Module colours (D4): an element with data-sbt-app="tasks|email|chat|files" reads --sbt-app-ink / -grad / -glow /
   -weak; each grad carries white words at 4.5:1 or more at both ends. */
html[data-sbt-theme="prime-light"] {
  --sbt-wall-base: #f4f7fb;
  --sbt-wall:
    radial-gradient(circle at 1px 1px, rgba(36, 52, 92, .055) 1px, transparent 1.6px),
    radial-gradient(46vmax 38vmax at 4% 2%, rgba(255, 196, 166, .28), transparent 72%),
    radial-gradient(44vmax 36vmax at 98% 8%, rgba(176, 188, 255, .20), transparent 72%),
    radial-gradient(42vmax 36vmax at 6% 98%, rgba(160, 232, 204, .34), transparent 72%),
    radial-gradient(46vmax 38vmax at 96% 94%, rgba(160, 214, 255, .26), transparent 72%);
  --sbt-wall-size: 22px 22px, 100% 100%, 100% 100%, 100% 100%, 100% 100%;
  --sbt-glass-bg: rgba(255, 255, 255, .62);
  --sbt-glass-bg-strong: rgba(255, 255, 255, .86);
  --sbt-glass-bg-solid: rgba(255, 255, 255, .985);
  --sbt-glass-edge: rgba(28, 44, 82, .10);
  --sbt-glass-hi: rgba(255, 255, 255, .85);
  --sbt-glass-blur: blur(18px) saturate(1.5);
  --sbt-glass-shadow: 0 1px 2px rgba(22, 34, 66, .06), 0 10px 28px -14px rgba(22, 34, 66, .22);
  --sbt-glass-shadow-hover: 0 2px 4px rgba(22, 34, 66, .07), 0 18px 40px -16px rgba(22, 34, 66, .30);
  --sbt-glass-radius: 16px;
  --sbt-glass-radius-sm: 12px;
  --sbt-glow-c: rgba(47, 91, 234, .30);
  --sbt-app-tasks-ink: #6d28d9;
  --sbt-app-tasks-grad: linear-gradient(135deg, #7c3aed 0%, #9333ea 100%);
  --sbt-app-tasks-glow: rgba(109, 40, 217, .28);
  --sbt-app-tasks-weak: #f3eeff;
  --sbt-app-email-ink: #1d4ed8;
  --sbt-app-email-grad: linear-gradient(135deg, #2563eb 0%, #4f46e5 100%);
  --sbt-app-email-glow: rgba(29, 78, 216, .26);
  --sbt-app-email-weak: #ebf1ff;
  --sbt-app-chat-ink: #047857;
  --sbt-app-chat-grad: linear-gradient(135deg, #047857 0%, #0f766e 100%);
  --sbt-app-chat-glow: rgba(4, 120, 87, .26);
  --sbt-app-chat-weak: #e6f6ef;
  --sbt-app-files-ink: #c2410c;
  --sbt-app-files-grad: linear-gradient(135deg, #c2410c 0%, #b45309 100%);
  --sbt-app-files-glow: rgba(194, 65, 12, .26);
  --sbt-app-files-weak: #fff0e6;
  /* s34: words on a module fill (the four --sbt-app-*-grad): white, which accent.js never rewrites (unlike --sbt-on-accent) */
  --sbt-on-app: #ffffff;
  --sbt-meter-fill: var(--sbt-accent-grad);
  --sbt-meter-track: rgba(47, 91, 234, .14);
  --sbt-meter-sheen: rgba(255, 255, 255, .55);
  --sbt-fi-tint: .22;
  --sbt-fi-tint-on: .4;
}
html[data-sbt-theme="prime-dark"]:where([data-sbt-look="prime-winter"]) {
  --sbt-wall-base: #0b1118;
  --sbt-wall:
    radial-gradient(circle at 1px 1px, rgba(255, 255, 255, .045) 1px, transparent 1.6px),
    radial-gradient(50vmax 40vmax at 6% 0%, rgba(99, 102, 241, .20), transparent 72%),
    radial-gradient(44vmax 38vmax at 100% 30%, rgba(20, 184, 166, .14), transparent 72%),
    radial-gradient(48vmax 40vmax at 30% 104%, rgba(139, 92, 246, .18), transparent 72%);
  --sbt-wall-size: 22px 22px, 100% 100%, 100% 100%, 100% 100%;
  --sbt-glass-bg: rgba(16, 22, 34, .58);
  --sbt-glass-bg-strong: rgba(14, 19, 29, .84);
  --sbt-glass-bg-solid: rgba(20, 27, 39, .985);
  --sbt-glass-edge: rgba(255, 255, 255, .09);
  --sbt-glass-hi: rgba(255, 255, 255, .07);
  --sbt-glass-blur: blur(18px) saturate(1.3);
  --sbt-glass-shadow: 0 1px 2px rgba(0, 0, 0, .35), 0 12px 32px -14px rgba(0, 0, 0, .65);
  --sbt-glass-shadow-hover: 0 2px 4px rgba(0, 0, 0, .4), 0 20px 44px -16px rgba(0, 0, 0, .75);
  --sbt-glass-radius: 16px;
  --sbt-glass-radius-sm: 12px;
  --sbt-glow-c: rgba(120, 146, 255, .32);
  --sbt-app-tasks-ink: #c4b5fd;
  --sbt-app-tasks-grad: linear-gradient(135deg, #7c3aed 0%, #9333ea 100%);
  --sbt-app-tasks-glow: rgba(196, 181, 253, .30);
  --sbt-app-tasks-weak: rgba(196, 181, 253, .14);
  --sbt-app-email-ink: #93c5fd;
  --sbt-app-email-grad: linear-gradient(135deg, #2563eb 0%, #4f46e5 100%);
  --sbt-app-email-glow: rgba(147, 197, 253, .28);
  --sbt-app-email-weak: rgba(147, 197, 253, .14);
  --sbt-app-chat-ink: #6ee7b7;
  --sbt-app-chat-grad: linear-gradient(135deg, #047857 0%, #0f766e 100%);
  --sbt-app-chat-glow: rgba(110, 231, 183, .26);
  --sbt-app-chat-weak: rgba(110, 231, 183, .12);
  --sbt-app-files-ink: #fdba74;
  --sbt-app-files-grad: linear-gradient(135deg, #c2410c 0%, #b45309 100%);
  --sbt-app-files-glow: rgba(253, 186, 116, .26);
  --sbt-app-files-weak: rgba(253, 186, 116, .12);
  /* s34: words on a module fill (the four --sbt-app-*-grad): white, which accent.js never rewrites (unlike --sbt-on-accent) */
  --sbt-on-app: #ffffff;
  --sbt-meter-fill: linear-gradient(90deg, #8ea8ff 0%, #b49bff 100%);
  --sbt-meter-track: rgba(142, 168, 255, .16);
  --sbt-meter-sheen: rgba(255, 255, 255, .35);
  --sbt-fi-tint: .30;
  --sbt-fi-tint-on: .5;
}
/* the glow is a soft halo in --sbt-glow-c, felt more than seen at rest. Custom properties inherit as finished values, so
   the halo is worked out again on every element that may carry its own glow colour (a module, a glass panel or card, a
   glow hover, or anything marked data-sbt-glow). */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]),
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) :is([data-sbt-app], [data-sbt-glow], .sbt-glass, .sbt-glass-strong, .sbt-glass-card, .sbt-glow-hover) {
  --sbt-glow: 0 6px 22px -10px var(--sbt-glow-c);
  --sbt-glow-strong: 0 0 0 1px var(--sbt-glow-c), 0 14px 34px -12px var(--sbt-glow-c);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) [data-sbt-app="tasks"] {
  --sbt-app-ink: var(--sbt-app-tasks-ink); --sbt-app-grad: var(--sbt-app-tasks-grad);
  --sbt-app-glow: var(--sbt-app-tasks-glow); --sbt-app-weak: var(--sbt-app-tasks-weak);
  --sbt-glow-c: var(--sbt-app-tasks-glow);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) [data-sbt-app="email"] {
  --sbt-app-ink: var(--sbt-app-email-ink); --sbt-app-grad: var(--sbt-app-email-grad);
  --sbt-app-glow: var(--sbt-app-email-glow); --sbt-app-weak: var(--sbt-app-email-weak);
  --sbt-glow-c: var(--sbt-app-email-glow);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) [data-sbt-app="chat"] {
  --sbt-app-ink: var(--sbt-app-chat-ink); --sbt-app-grad: var(--sbt-app-chat-grad);
  --sbt-app-glow: var(--sbt-app-chat-glow); --sbt-app-weak: var(--sbt-app-chat-weak);
  --sbt-glow-c: var(--sbt-app-chat-glow);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) [data-sbt-app="files"] {
  --sbt-app-ink: var(--sbt-app-files-ink); --sbt-app-grad: var(--sbt-app-files-grad);
  --sbt-app-glow: var(--sbt-app-files-glow); --sbt-app-weak: var(--sbt-app-files-weak);
  --sbt-glow-c: var(--sbt-app-files-glow);
}
/* more contrast asked for, or no backdrop-filter in this browser: the glass turns (almost) solid and still reads as the look */
@media (prefers-contrast: more) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) { --sbt-glass-bg: var(--sbt-glass-bg-solid); --sbt-glass-bg-strong: var(--sbt-glass-bg-solid); }
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) { --sbt-glass-bg: var(--sbt-glass-bg-solid); --sbt-glass-bg-strong: var(--sbt-glass-bg-solid); }
}

/* 3. the new elements of the layout: hidden in the seven other looks (each is shown again below, Summer/Winter only) */
.sbt-app-title, .sbt-app-h1, #sbt-nav-slot, .sbt-ai-meter, .fi-f, .fi-r { display: none; }

/* 4. the wallpaper: one fixed layer behind everything (it never moves while the page scrolls and never takes a click);
   the body lets it through, <html> keeps the old ground underneath */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) body.sbt-body { background: transparent; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) body.sbt-body::before {
  content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-color: var(--sbt-wall-base); background-image: var(--sbt-wall); background-size: var(--sbt-wall-size);
  background-repeat: repeat;
}

/* 5. the glass kit (phase 2 uses these). .sbt-glass skips the sign-in page's own .sbt-glass (inside its .sbt-hero). */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) :is(.sbt-glass, .sbt-glass-strong):not(.sbt-hero *) {
  background: var(--sbt-glass-bg); border: 1px solid var(--sbt-glass-edge); border-radius: var(--sbt-glass-radius);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow), var(--sbt-glow);
  -webkit-backdrop-filter: var(--sbt-glass-blur); backdrop-filter: var(--sbt-glass-blur);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-glass-strong:not(.sbt-hero *) { background: var(--sbt-glass-bg-strong); }
/* a repeated card: no blur (many of them), the strong glass, a glow; it lifts 2 px and glows more on hover */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-glass-card {
  background: var(--sbt-glass-bg-strong); border: 1px solid var(--sbt-glass-edge); border-radius: var(--sbt-glass-radius);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow), var(--sbt-glow);
  transition: transform var(--sbt-kit-dur) var(--sbt-kit-ease), box-shadow var(--sbt-kit-dur) var(--sbt-kit-ease);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-glass-card:hover {
  transform: translateY(-2px); box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow-hover), var(--sbt-glow-strong);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-glow-hover { transition: box-shadow var(--sbt-kit-dur) var(--sbt-kit-ease); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-glow-hover:is(:hover, :focus-within) {
  box-shadow: var(--sbt-glass-shadow-hover), var(--sbt-glow-strong);
}

/* 6. the shared frame in glass */
/* the top bar: strong glass over the wallpaper (and over the page as it scrolls under it), blurred */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav {
  background: var(--sbt-glass-bg-strong); border-bottom: 1px solid var(--sbt-glass-edge); box-shadow: var(--sbt-glass-shadow);
  -webkit-backdrop-filter: var(--sbt-glass-blur); backdrop-filter: var(--sbt-glass-blur);
}
/* the logo mark wears the accent gradient and its glow */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav .sbt-brand-mark {
  background: var(--sbt-accent-grad); color: var(--sbt-on-accent); border-radius: 10px; box-shadow: var(--sbt-glow);
}
/* the top bar's own buttons (Jump to, the AI chip, the bell, the look, the user, the menu): round glass pills */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > :is(.sbt-user-btn, .sbt-btn),
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > .sbt-dropdown > :is(.sbt-user-btn, .sbt-btn) {
  background: var(--sbt-glass-bg); border: 1px solid var(--sbt-glass-edge); border-radius: var(--sbt-radius-pill);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi);
  transition: background var(--sbt-kit-dur) var(--sbt-kit-ease), box-shadow var(--sbt-kit-dur) var(--sbt-kit-ease);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > :is(.sbt-user-btn, .sbt-btn):hover,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > .sbt-dropdown > :is(.sbt-user-btn, .sbt-btn):hover,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > .sbt-dropdown.open > :is(.sbt-user-btn, .sbt-btn) {
  background: var(--sbt-glass-bg-strong); box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glow);
}
/* menus float over anything: near-solid glass (inside the blurred top bar a menu cannot blur the page under it) */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-dropdown-menu {
  background: var(--sbt-glass-bg-solid); border-color: var(--sbt-glass-edge); border-radius: var(--sbt-glass-radius-sm);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow-hover);
}
@media (max-width: 991px) {
  /* the phone menu lists the top-bar groups inline: no box of their own there, as before */
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-links .sbt-dropdown-menu { background: transparent; border: 0; box-shadow: none; }
}
/* cards: strong glass (dense content sits on it), a hairline edge, a light inner edge, a two-layer shadow, a glow */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-card {
  background: var(--sbt-glass-bg-strong); border-color: var(--sbt-glass-edge); border-radius: var(--sbt-glass-radius);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow), var(--sbt-glow);
}
/* dialogs, the Jump-to palette and toasts float over anything: near-solid glass */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-modal {
  background: var(--sbt-glass-bg-solid); border-color: var(--sbt-glass-edge); border-radius: var(--sbt-glass-radius);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow-hover), var(--sbt-glow);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-modal[tabindex="-1"]:focus,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-modal[tabindex="-1"]:focus-visible { border-radius: var(--sbt-glass-radius); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-cmdk-panel {
  background: var(--sbt-glass-bg-solid); border-color: var(--sbt-glass-edge); border-radius: var(--sbt-glass-radius);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow-hover), var(--sbt-glow);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-toast {
  background: var(--sbt-glass-bg-solid); border-radius: var(--sbt-glass-radius-sm);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow-hover);
}
/* buttons: rounder; the main button wears the accent gradient and glows (its words: --sbt-on-accent, so a light picked
   accent gets dark words); a field on glass matches the rounder corners. The button's gradient is written out (the same
   two tokens as --sbt-accent-grad) so the contrast harness of tests/golden/shared_a11y_layer_test.js reads its stops. */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-btn { border-radius: 10px; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-btn.sbt-btn-sm { border-radius: 8px; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-btn-primary,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-body a.sbt-btn-primary {
  background: linear-gradient(135deg, var(--sbt-accent) 0%, var(--sbt-accent-2) 100%); color: var(--sbt-on-accent);
  border-color: transparent; box-shadow: var(--sbt-glow);
  transition: box-shadow var(--sbt-kit-dur) var(--sbt-kit-ease), background var(--sbt-kit-dur) var(--sbt-kit-ease);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-btn-primary:hover,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-body a.sbt-btn-primary:hover {
  background: linear-gradient(135deg, var(--sbt-accent-strong) 0%, var(--sbt-accent-2) 100%);
  color: var(--sbt-on-accent); box-shadow: var(--sbt-glow-strong);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) :is(.sbt-card, .sbt-modal, .sbt-dropdown-menu, .sbt-glass, .sbt-glass-strong, .sbt-glass-card,
  .sbt-nav) :is(.sbt-input, .sbt-select, .sbt-textarea) {
  border-radius: 10px;
}

/* 7. the app's name in the top bar: [logo] MyCloud | <icon> TASKS (layouts/sbt.blade.php, from the page's sbt-app
   section). Strong capitals in the module colour: Summer paints them with the module gradient (solid ink where text
   cannot be clipped), Winter in its light ink with a soft glow. On a phone: [logo] | TASKS. The page's real heading is
   a visually hidden <h1> at the start of <main>, there only while the page head is hidden (sbt-ph-app). */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-title {
  display: flex; align-items: center; gap: var(--sbt-sp-2); min-width: 0; margin-right: var(--sbt-sp-6);
  color: var(--sbt-app-ink);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-inner:has(> .sbt-app-title) > .sbt-brand { margin-right: var(--sbt-sp-3); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-pipe {
  flex: none; width: 1px; height: 22px; margin-right: var(--sbt-sp-1); background: var(--sbt-border-2);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-title svg.fi { flex: none; width: 22px; height: 22px; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-name {
  font-size: .95rem; font-weight: 800; letter-spacing: .08em; line-height: 1.2; text-transform: uppercase;
  white-space: nowrap; color: var(--sbt-app-ink);
}
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  html[data-sbt-theme="prime-light"] .sbt-app-name {
    background: var(--sbt-app-grad); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  }
}
html[data-sbt-theme="prime-dark"]:where([data-sbt-look="prime-winter"]) .sbt-app-name { text-shadow: 0 0 14px var(--sbt-app-glow); }
@media (forced-colors: active) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-name { background: none; -webkit-text-fill-color: currentColor; }
}
@media (max-width: 767px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-inner:has(> .sbt-app-title) .sbt-brand-text { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-title svg.fi { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-title { gap: var(--sbt-sp-15); margin-right: var(--sbt-sp-2); }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-name { font-size: .85rem; letter-spacing: .06em; }
}
/* the page head of a module (class sbt-ph-app) has moved into the top bar: hidden here, and the gap above the first block
   shrinks from 24 to 12 px (the app frame of Email / Team Chat stays flush at desktop width) */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-page-head.sbt-ph-app { display: none; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-main:has(> .sbt-page-head.sbt-ph-app) { padding-top: var(--sbt-sp-3); }
@media (min-width: 1024px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-main.is-app:has(> .sbt-page-head.sbt-ph-app) { padding-top: 0; }
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-main:has(> .sbt-page-head.sbt-ph-app) > .sbt-app-h1 {
  display: block; position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* 8. the AI meter in the top bar's AI chip: a small label, an 8 px bar that grows to its value once and catches a soft
   sheen every few seconds (warning from 80 %, danger at 100 %), and "X of Y" under it. The chip's old words stay for the
   other looks. On a phone: the bar and a short "X/Y" only. */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-dd > .sbt-user-btn > .small { display: none; }
/* three short rows in the chip, packed so the top bar keeps its height (the chip's own padding is trimmed to match) */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-dd > .sbt-user-btn { padding-top: .2rem; padding-bottom: .2rem; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter { display: inline-grid; row-gap: 2px; min-width: 7.5rem; text-align: left; line-height: 1.05; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-label {
  font-size: var(--sbt-fs-xs); font-weight: 600; color: var(--sbt-muted); white-space: nowrap;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-track {
  position: relative; display: block; height: 8px; border-radius: var(--sbt-radius-pill);
  background: var(--sbt-meter-track); overflow: hidden;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-fill {
  position: absolute; top: 0; bottom: 0; left: 0; width: var(--sbt-meter-pct, 0%); border-radius: inherit; overflow: hidden;
  background: var(--sbt-meter-fill); transform-origin: left center; animation: sbt-fi-meter-grow .6s var(--sbt-kit-ease) both;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-fill::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(100deg, transparent 25%, var(--sbt-meter-sheen) 50%, transparent 75%);
  animation: sbt-fi-meter-sheen 5s ease-in-out 1.4s infinite;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter[data-state="warning"] .sbt-ai-meter-fill { background: var(--sbt-warning); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter[data-state="danger"] .sbt-ai-meter-fill { background: var(--sbt-danger); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-num {
  font-size: var(--sbt-fs-xs); font-weight: 700; color: var(--sbt-text-2); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-of { font-weight: 500; color: var(--sbt-muted); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-short { display: none; }
@keyframes sbt-fi-meter-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes sbt-fi-meter-sheen { 0% { transform: translateX(-100%); } 35%, 100% { transform: translateX(100%); } }
@media (max-width: 767px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter { min-width: 3.75rem; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-label, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-num { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-short {
    display: block; font-size: var(--sbt-fs-xs); font-weight: 700; color: var(--sbt-text-2); white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
}

/* 9. the top-bar slot (#sbt-nav-slot, before the AI chip): shown only in Summer/Winter and only when something that is not
   empty sits in it. A page moves ONE compact item into it (Tasks: its time pill); whatever sits there, and anything
   marked .sbt-nav-pill, is a small glass pill: an icon, a few words, a link cut short with "…", a pulsing dot while a
   timer runs (.sbt-nav-pill-dot). */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) #sbt-nav-slot { display: flex; align-items: center; min-width: 0; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) #sbt-nav-slot:not(:has(> :not(:empty))) { display: none; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) #sbt-nav-slot > :empty { display: none; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) :is(#sbt-nav-slot > *, .sbt-nav-pill) {
  display: inline-flex; align-items: center; gap: var(--sbt-sp-15); min-height: 34px; max-width: 22rem; padding: 0 var(--sbt-sp-3);
  border: 1px solid var(--sbt-glass-edge); border-radius: var(--sbt-radius-pill); background: var(--sbt-glass-bg);
  box-shadow: inset 0 1px 0 var(--sbt-glass-hi); color: var(--sbt-text-2); font-size: var(--sbt-fs-xs);
  white-space: nowrap; overflow: hidden;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) :is(#sbt-nav-slot > *, .sbt-nav-pill) a {
  display: inline-block; max-width: 10rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: bottom;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-pill-dot {
  flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--sbt-danger); color: var(--sbt-danger);
  box-shadow: 0 0 0 0 currentColor; animation: sbt-fi-pulse 1.6s ease-out infinite;
}
@keyframes sbt-fi-pulse { 0% { box-shadow: 0 0 0 0 currentColor; } 70%, 100% { box-shadow: 0 0 0 7px transparent; } }

/* 10. the duotone Fluent icons (sbt.js "a1 summer icons" upgrades <svg class="si"> to class "si fi" with a tint layer and
   an outline layer from public/sbt-ui/fluent-icons.svg). The icon's own <use> stays in place but hidden; the tint
   brightens when the control is pointed at or picked; each meaning has a small move on hover or keyboard focus (data-fi-
   motion: pop by default; turn, spin, rise, drop, shake, ring, tilt, wiggle, lift); a ribbon's icons come in once, one
   after another, on page load (.sbt-fi-enter, --fi-i). */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi { stroke: none; fill: currentColor; overflow: visible; transform-origin: 50% 50%; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi > use:not(.fi-f):not(.fi-r) { display: none; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi > :is(.fi-f, .fi-r) { display: inline; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi > .fi-f { opacity: var(--sbt-fi-tint); transition: opacity var(--sbt-kit-dur) var(--sbt-kit-ease); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) :is(button, a, label, summary, [role="button"], [role="tab"], [role="menuitem"],
  [role="menuitemradio"]):is(:hover, :focus-visible, [aria-selected="true"], [aria-pressed="true"], [aria-expanded="true"],
  .active) svg.fi > .fi-f { opacity: var(--sbt-fi-tint-on); }
/* each icon names its move (data-fi-motion, set by the engine or by the page); the one rule after these plays it on
   hover or keyboard focus of the control the icon sits in */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="turn"] { --sbt-fi-anim: sbt-fi-turn; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="spin"] { --sbt-fi-anim: sbt-fi-spin; --sbt-fi-dur: .7s; --sbt-fi-ease: ease-in-out; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="rise"] { --sbt-fi-anim: sbt-fi-rise; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="drop"] { --sbt-fi-anim: sbt-fi-drop; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="shake"] {
  --sbt-fi-anim: sbt-fi-shake; --sbt-fi-dur: .55s; --sbt-fi-ease: ease-in-out;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="ring"] {
  --sbt-fi-anim: sbt-fi-ring; --sbt-fi-dur: .8s; --sbt-fi-ease: ease-in-out; transform-origin: 50% 12%;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="tilt"] { --sbt-fi-anim: sbt-fi-tilt; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="wiggle"] {
  --sbt-fi-anim: sbt-fi-wiggle; --sbt-fi-dur: .55s; --sbt-fi-ease: ease-in-out;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi[data-fi-motion="lift"] { --sbt-fi-anim: sbt-fi-lift; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) :is(button, a, label, summary, [role="button"], [role="tab"], [role="menuitem"],
  [role="menuitemradio"]):is(:hover, :focus-visible) > svg.fi {
  animation: var(--sbt-fi-anim, sbt-fi-pop) var(--sbt-fi-dur, .5s) var(--sbt-fi-ease, cubic-bezier(.34, 1.56, .64, 1)) both;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-fi-enter svg.fi {
  animation: sbt-fi-enter .45s var(--sbt-kit-ease) both; animation-delay: calc(var(--fi-i, 0) * 45ms);
}
@keyframes sbt-fi-pop { 0%, 100% { transform: none; } 45% { transform: scale(1.18) rotate(-6deg); } }
@keyframes sbt-fi-turn { from { transform: none; } to { transform: rotate(90deg); } }
@keyframes sbt-fi-spin { from { transform: none; } to { transform: rotate(180deg); } }
@keyframes sbt-fi-rise { 0%, 100% { transform: none; } 45% { transform: translateY(-3px); } }
@keyframes sbt-fi-drop { 0%, 100% { transform: none; } 45% { transform: translateY(3px); } }
@keyframes sbt-fi-shake {
  0%, 100% { transform: none; } 20% { transform: rotate(-9deg); } 40% { transform: rotate(8deg); }
  60% { transform: rotate(-6deg); } 80% { transform: rotate(4deg); }
}
@keyframes sbt-fi-ring {
  0%, 100% { transform: none; } 15% { transform: rotate(14deg); } 30% { transform: rotate(-12deg); }
  45% { transform: rotate(9deg); } 60% { transform: rotate(-6deg); } 75% { transform: rotate(3deg); }
}
@keyframes sbt-fi-tilt { 0%, 100% { transform: none; } 45% { transform: rotate(-10deg) translateY(-1px); } }
@keyframes sbt-fi-wiggle {
  0%, 100% { transform: none; } 25% { transform: translateX(-2px) rotate(-6deg); }
  50% { transform: translateX(2px) rotate(5deg); } 75% { transform: translateX(-1px); }
}
@keyframes sbt-fi-lift { 0%, 100% { transform: none; } 45% { transform: translateY(-3px) scale(1.06); } }
@keyframes sbt-fi-enter { from { opacity: 0; transform: translateY(6px) scale(.85); } to { opacity: 1; transform: none; } }

/* 11. "reduce motion": no icon moves, no entrance, no growing bar, no sheen, no pulse, no lift */
@media (prefers-reduced-motion: reduce) {
  /* !important on the icon itself beats its hover and entrance rules, whatever their weight */
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-fill,
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-fill::after, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-pill-dot { animation: none !important; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-glass-card, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-glow-hover,
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) svg.fi > .fi-f { transition: none !important; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-glass-card:hover { transform: none !important; }
}
/* manu code for a1 summer glass ends here */

/* manu code for a1 s38 title ink starts here */
/* ---- Summer: the app title's own ink on the see-through top bar (A1 s38, 21-Oct-2026) -----------------------------------
   WHY: Summer paints the app title's words ("MyCloud | TASKS", section 7) with the module gradient, straight on the
   glass bar (white at 86 %), and the page scrolls under it. Black page content under the bar (a photo, a video, a dark
   mail) turns the bar grey (#dbdbdb), and the gradient ends fall to 3.64-4.13:1 (files #b45309 the lowest; text needs
   4.5:1; frame found-not-fixed (b)). Winter's title is a light ink on the dark bar (6.30:1 or more) and stays as it is.
   HOW: the title's words take the next darker shade of each of their two module colours (violet/purple 700, blue/indigo
   700, emerald/teal 800, orange/amber 800): 4.84-5.71:1 over black content under the bar, 6.70-7.90:1 on white. Only the
   two tokens the words already read are set, on the words alone, so the gradient, its solid fallback, the forced-colours
   rule and the title's icon keep their own rules; the module colours elsewhere (ribbons, tiles, fills, glows) do not
   change. Summer only. */
html[data-sbt-theme="prime-light"] [data-sbt-app="tasks"] > .sbt-app-name {
  --sbt-app-ink: #6d28d9; --sbt-app-grad: linear-gradient(135deg, #6d28d9 0%, #7e22ce 100%);
}
html[data-sbt-theme="prime-light"] [data-sbt-app="email"] > .sbt-app-name {
  --sbt-app-ink: #1d4ed8; --sbt-app-grad: linear-gradient(135deg, #1d4ed8 0%, #4338ca 100%);
}
html[data-sbt-theme="prime-light"] [data-sbt-app="chat"] > .sbt-app-name {
  --sbt-app-ink: #065f46; --sbt-app-grad: linear-gradient(135deg, #065f46 0%, #115e59 100%);
}
html[data-sbt-theme="prime-light"] [data-sbt-app="files"] > .sbt-app-name {
  --sbt-app-ink: #9a3412; --sbt-app-grad: linear-gradient(135deg, #9a3412 0%, #92400e 100%);
}
/* manu code for a1 s38 title ink ends here */
/* manu code for a1 s34 bar ink starts here */
/* ---- Summer + Winter: the top bar's own muted ink (A1 s34, 21-Oct-2026) ------------------------------------------------
   WHY: the top bar is see-through glass (Summer: white at 86 %, Winter: near-black at 84 %) and the page scrolls under
   it. Dark page content under Summer's bar (a photo, a video, a dark mail) turns the bar grey (#dbdbdb over pure black),
   and the menu links in the muted ink (#5b6b80) fall to 3.94:1; white content under Winter's bar does the same to its
   muted ink (#97a1af on #353941: 4.45:1). Text needs 4.5:1 (frame found-not-fixed (a)). Measured in the browser: the
   menu links are the only muted words straight on the bar; Jump to, Ctrl K and the meter's words sit on the buttons' own
   glass (4.84 Summer / 5.91 Winter at worst) and keep the muted ink.
   HOW: one bar ink per look, a hair darker (Summer #526073: 4.64:1 on the bar over black, 6.40 on white) or a hair
   lighter (Winter #9ba5b2: 4.66:1 on the bar over white) than the look's muted grey, so the bar keeps its calm grey.
   The menu links read it through their own --sbt-muted (the hub's .sbt-nav-link colour is var(--sbt-muted) !important),
   so no colour rule is overridden; hover (--sbt-text-2) and the picked link (--sbt-text) do not change. With "more
   contrast" asked for, the glass is solid and the look's own darker muted ink is used. Summer and Winter only. */
/* s43 (23-Oct-2026): every "prime" selector here carries a :where() = Summer or Winter only (plain Prime Dark is back
   to master's look); why and how: sbt.css "a1 summer kit". */
html[data-sbt-theme="prime-light"] { --sbt-nav-muted: #526073; }
html[data-sbt-theme="prime-dark"]:where([data-sbt-look="prime-winter"]) { --sbt-nav-muted: #9ba5b2; }
@media (prefers-contrast: more) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) { --sbt-nav-muted: var(--sbt-muted); }
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav .sbt-nav-link { --sbt-muted: var(--sbt-nav-muted); }
/* manu code for a1 s34 bar ink ends here */
/* manu code for a1 top bar n6 starts here */
/* ---- Summer + Winter: the top bar's AI chip and its card, the profile button, the drop-down arrows, the phone bar ----------
   (A1 N6, 24-Oct-2026)
   WHY: the user (23-Oct-2026): "the pill has too much text info in it. card can have dense info but bar has to be animated w
   preferably animated bar. the inside card for info needs to replicate themes when changed and designed better. the profile
   at top needs to be just picture and drop down rather than profile name. too much clutter that is. make proper cornered
   target for profile and all preferences rested drops the arrow triggers like projects usually do"; and the phone bar: the
   user button dropped to another row at 390 px and narrower, and its buttons were 30-38 px where a finger needs about 40.
   Summer and Winter only: every other look keeps master's bar (the one default rule below hides the new elements there).
   HOW (design: work/scratch/a1/s54_s5/N6_DESIGN_NOTE.md + work/scratch/a1/s55_s5/N6_DESIGN_ADDENDUM_s55.md):
   - the AI chip from 768 px: one row, 40 px tall: the icon, a 4.5rem bar (it still grows once and catches the sheen), the
     percent (only when there is a cap) and an arrow. Its words are hidden for the eye only (clip pattern), so the button
     still says everything to a screen reader. No cap: the icon and the short number.
   - the card: a summary on top (the window, the percent, "X of Y credits", a 10 px bar that grows each time the card
     opens); master's rows line up (tabular figures), its bars are drawn like the meter, its lines in the glass edge;
     18-22rem wide (at 640 px and less master's full width). Tokens only, so it keeps following a live look switch.
   - the profile button: the picture and the arrow; the name is hidden for the eye only. All six targets take the ribbon
     tiles' corner (var(--sbt-radius), 8 px here) and are 40 px tall; 44 px on a touch screen (the shared a11y layer's size).
   - the arrows: one muted chevron at the end of the AI chips, the look and the profile button, half a turn while its menu
     is open (the shared dropdown code sets .open on the .sbt-dropdown). The look and profile chevrons carry an inline em
     size, so on a phone they are sized through their own font size.
   - phones (767 px and less): row 1 = the logo and the six targets as 40 px squares (arrows as corner marks, the AI chip
     its icon over a small bar), never wrapping inside; row 2 = the app title with its icon, on the pages that have one
     (Tasks, Email, Team Chat and Files hide their page head in these looks, so it is their only visible name); the logo's
     word is hidden for the eye only; 12 px sides plus the screen's safe area, as master keeps them.
   - the menu button (three lines) is hidden from 992 px, where its click changes nothing a person can use.
   - "reduce motion": no growing bar, no sheen, no turning arrow. */
.sbt-n6-pct, .sbt-n6-caret, .sbt-n6-sum { display: none; }
/* the card's summary (layout: first thing in #sbt-credits-menu, only with a cap) */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum {
  display: grid; gap: .35rem; margin: 0 0 .65rem; padding: 0 0 .7rem; border-bottom: 1px solid var(--sbt-glass-edge);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sbt-sp-2); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-label { font-size: var(--sbt-fs-xs); font-weight: 600; color: var(--sbt-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-pct { font-size: var(--sbt-fs-xs); font-weight: 700; color: var(--sbt-text-2); font-variant-numeric: tabular-nums; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-num { font-size: 1.15rem; font-weight: 700; line-height: 1.2; color: var(--sbt-text); font-variant-numeric: tabular-nums; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-of { font-size: var(--sbt-fs-xs); font-weight: 500; color: var(--sbt-muted); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-track {
  position: relative; display: block; height: 10px; overflow: hidden;
  background: var(--sbt-meter-track); border-radius: var(--sbt-radius-pill);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-fill {
  position: absolute; top: 0; bottom: 0; left: 0; width: var(--sbt-meter-pct, 0%); border-radius: inherit; overflow: hidden;
  background: var(--sbt-meter-fill); transform-origin: left center; animation: sbt-fi-meter-grow .6s var(--sbt-kit-ease) both;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-fill::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(100deg, transparent 25%, var(--sbt-meter-sheen) 50%, transparent 75%);
  animation: sbt-fi-meter-sheen 5s ease-in-out 1.4s infinite;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum[data-state="warning"] .sbt-n6-sum-fill { background: var(--sbt-warning); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum[data-state="danger"] .sbt-n6-sum-fill { background: var(--sbt-danger); }
/* both cards (credits and own key): width, lines, master's bars drawn like the meter, the value column lined up */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-menu { min-width: 18rem; max-width: min(22rem, calc(100vw - 2rem)); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-menu .sbt-dropdown-divider { border-top-color: var(--sbt-glass-edge); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-menu .sbt-badge { border-radius: var(--sbt-radius-pill); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-menu .sbt-progress { background: var(--sbt-meter-track); border-radius: var(--sbt-radius-pill); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-menu .sbt-progress-bar { background: var(--sbt-meter-fill); border-radius: inherit; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-menu .justify-content-between > :last-child { font-variant-numeric: tabular-nums; }
/* one shape for the bar's six targets (Jump, AI, bell, look, profile, menu): the ribbon tiles' corner, 40 px high */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > :is(.sbt-user-btn, .sbt-btn),
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > .sbt-dropdown > :is(.sbt-user-btn, .sbt-btn) { border-radius: var(--sbt-radius); height: 40px; min-width: 40px; }
/* the profile button: the picture and the arrow; the name stays for screen readers */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-user-btn:has(> .sbt-avatar) { height: 40px; border-radius: var(--sbt-radius); gap: .25rem; padding: 0 .45rem 0 .25rem; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-user-btn:has(> .sbt-avatar) > .sbt-avatar { width: 32px; height: 32px; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-user-btn:has(> .sbt-avatar) > .sbt-truncate {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}
/* the arrows */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-caret,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) #sbt-look > .sbt-look-btn > .si:last-child,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-user-btn:has(> .sbt-avatar) > .si:last-child {
  width: .75rem; height: .75rem; color: var(--sbt-muted); transition: transform var(--sbt-kit-dur) var(--sbt-kit-ease);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-caret { display: inline-block; flex: none; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-dropdown.open > [data-sbt-dropdown] > .sbt-n6-caret,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-dropdown.open > .sbt-look-btn > .si:last-child,
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-dropdown.open > .sbt-user-btn:has(> .sbt-avatar) > .si:last-child { transform: rotate(180deg); }
/* the AI chip from 768 px: one row */
@media (min-width: 768px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-dd > .sbt-user-btn { display: inline-flex; align-items: center; gap: .45rem; padding: 0 .55rem 0 .65rem; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter { display: inline-flex; align-items: center; min-width: 0; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-label, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-num {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0);
    white-space: nowrap; border: 0;
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-track { width: 4.5rem; height: 6px; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-pct { display: inline; font-size: var(--sbt-fs-xs); font-weight: 700; color: var(--sbt-text-2); font-variant-numeric: tabular-nums; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-nobar .sbt-ai-meter-short {
    display: inline; font-size: var(--sbt-fs-xs); font-weight: 700; color: var(--sbt-text-2); white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
}
/* the menu button only below 992 px (there it opens the menu) */
@media (min-width: 992px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-burger { display: none; }
}
/* phones: the logo and six 40 px squares in one row; the app title on its own row under them */
@media (max-width: 767px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-inner {
    padding-left: calc(.75rem + env(safe-area-inset-left, 0px)); padding-right: calc(.75rem + env(safe-area-inset-right, 0px));
    padding-top: .5rem; padding-bottom: .5rem;
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-brand, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-inner:has(> .sbt-app-title) > .sbt-brand { margin-right: 0; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-brand-text, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-inner:has(> .sbt-app-title) .sbt-brand-text {
    display: block; position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
    clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-title { order: 1; flex-basis: 100%; margin: 0; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-pipe { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-app-title svg.fi { display: block; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-links { order: 2; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right { flex-wrap: nowrap; gap: 4px; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > :is(.sbt-user-btn, .sbt-btn),
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > .sbt-dropdown > :is(.sbt-user-btn, .sbt-btn) { width: 40px; height: 40px; padding: 0; justify-content: center; position: relative; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-dd > .sbt-user-btn { flex-direction: column; gap: 3px; }
  /* the bar ends before the corner arrow: the two sit side by side, centred together under the icon */
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter { min-width: 0; margin-right: 10px; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-track { width: 20px; height: 4px; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-ai-meter-short { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-pct { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-caret,
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) #sbt-look > .sbt-look-btn > .si:last-child,
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-user-btn:has(> .sbt-avatar) > .si:last-child { position: absolute; right: 2px; bottom: 2px; width: .6rem; height: .6rem; font-size: .7rem; }
}
/* at 640 px and less the cards keep master's full width (sbt.css "AI tokens / AI credits chip" phone rule) */
@media (max-width: 640px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-money-menu { min-width: 0; max-width: none; }
}
/* touch screens: the shared a11y layer's 44 px thumb size for all six (it already gives it to the bell, look and menu) */
@media (pointer: coarse) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > :is(.sbt-user-btn, .sbt-btn),
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > .sbt-dropdown > :is(.sbt-user-btn, .sbt-btn) { height: 44px; min-width: 44px; }
}
@media (pointer: coarse) and (max-width: 767px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > :is(.sbt-user-btn, .sbt-btn),
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-right > .sbt-dropdown > :is(.sbt-user-btn, .sbt-btn) { width: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-fill, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-sum-fill::after { animation: none !important; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n6-caret,
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) #sbt-look > .sbt-look-btn > .si:last-child,
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-user-btn:has(> .sbt-avatar) > .si:last-child { transition: none !important; }
}
/* manu code for a1 top bar n6 ends here */
/* manu code for a1 mega menu n7 starts here */
/* ---- Summer + Winter: the top menu as a mega menu (tiles with big coloured icons; phones: a sheet and a cascade) ------------
   (A1 N7, 24-Oct-2026)
   WHY: the user (23-Oct-2026): "i want tiles w proper bug icons wnd c9lors. glass rounded corners. we will have to account
   for responsive mobile view here as cards can be too long. so preferably like amazon app mega menu or cascades that don't
   introduce noise to clarity of use." Master's menu is a row of words that wraps to two rows at 1440 px, its groups open
   short lists without icons, and on a phone the ☰ list gets very long (Company alone is 18 rows).
   Summer and Winter only: every other look keeps master's menu (the one default rule below hides A1's row there).
   HOW (test: tests/golden/mega_n7_test.js):
   - the layout draws A1's own menu row (.sbt-n7) from master's model, right after master's list. From 992 px it shows in
     one line and master's list leaves the view (display: none; it stays in the page, so the Jump-to palette and the ☰
     still find it). Each group is a 40 px square: its icon in its own colour, the N6 arrow as a corner mark (as the N6
     phone squares). The names cannot fit one row (703 px of names, at most 551 px free beside the right-hand buttons at
     1440 px, 235 px at 1024), so there a name leaves the view for the eye only (a screen reader still reads it) and shows
     as a small tip under its square when pointed at or focused; the open panel names itself in its top row.
   - a group opens a glass card centred under the bar (at most 52rem wide, never taller than the screen; it scrolls inside).
     In it, a grid of tiles: a 48 px square in the page's own colour with a big icon, and the page name under it. The page
     you are on wears the accent ring. Company comes in small captioned sections.
   - below 992 px master's ☰ opens A1's sheet instead of master's long list (the two swap only through :has(), so a browser
     without :has() keeps master's list): three big tiles per row, one per top item. A group's tile opens its cascade: the
     group's own tiles replace the sheet's grid, with a "Back" row on top. The sheet scrolls inside itself, never sideways.
   - opening and closing is master's shared drop-down code (no new script): a trigger or Back toggles its group; a tile, a
     click outside it or another trigger closes it.
   - colours: the kit's nine hues (data-sbt-hue on each trigger and tile) and the look's glass tokens; no colour of its own.
   - touch screens: every trigger, tile and Back button at least 44 px. "Reduce motion": no fill, lift or turn. */
.sbt-n7 { display: none; }
/* the trigger: a 40 px target with the N6 corner; its icon in its own colour; open = its colour's ground */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top {
  display: inline-flex; align-items: center; gap: .4rem; height: 40px; padding: 0 .55rem; border: 0;
  border-radius: var(--sbt-radius); background: transparent; color: var(--sbt-nav-muted); font: inherit;
  font-size: var(--sbt-fs-md); font-weight: 500; line-height: 1.2; white-space: nowrap; text-decoration: none;
  cursor: pointer; transition: background var(--sbt-kit-dur) var(--sbt-kit-ease), color var(--sbt-kit-dur) var(--sbt-kit-ease);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top > svg.fi { flex: none; width: 20px; height: 20px; color: var(--sbt-hue-ink); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-caret {
  width: .75rem; height: .75rem; margin-left: -.1rem; color: var(--sbt-muted);
  transition: transform var(--sbt-kit-dur) var(--sbt-kit-ease);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top:hover { background: var(--sbt-glass-bg-strong); color: var(--sbt-text); }
/* the group of the page you are on */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top.active { background: var(--sbt-accent-weak); color: var(--sbt-accent-text); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-dd.open > .sbt-n7-top { background: var(--sbt-hue-bg); color: var(--sbt-hue-ink); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-dd.open > .sbt-n7-top > .sbt-n7-caret { transform: rotate(180deg); }
/* the panel: a glass card with the big corner (Summer and Winter already give every menu the glass edge and shadow) */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-panel {
  padding: var(--sbt-sp-3); background: var(--sbt-glass-bg-solid); border-radius: var(--sbt-glass-radius);
  overscroll-behavior: contain;
}
/* the panel's top row: the group's name (its heading); the Back button in it is for the phone cascade only */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-bar { display: flex; align-items: center; gap: .5rem; margin: 0 .25rem .35rem; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-back {
  display: inline-flex; align-items: center; gap: .3rem; height: 40px; padding: 0 .75rem 0 .5rem; border: 0;
  border-radius: var(--sbt-radius); background: var(--sbt-accent-weak); color: var(--sbt-accent-text); font: inherit;
  font-size: var(--sbt-fs-sm); font-weight: 600; cursor: pointer;
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-title {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; color: var(--sbt-text);
}
/* Company's section captions */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-sec {
  margin: .85rem .25rem .4rem; font-size: var(--sbt-fs-xs); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--sbt-muted);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-sec:first-of-type { margin-top: .15rem; }
/* the tiles: a big icon on its colour's ground over the page name (no description lines: no noise) */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr)); gap: var(--sbt-sp-2); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-tile {
  display: flex; flex-direction: column; align-items: center; gap: .45rem; min-width: 0; padding: .7rem .35rem .6rem;
  border-radius: var(--sbt-glass-radius-sm); color: var(--sbt-text); font-size: var(--sbt-fs-sm); font-weight: 500;
  line-height: 1.25; text-decoration: none;
  transition: background var(--sbt-kit-dur) var(--sbt-kit-ease), transform var(--sbt-kit-dur) var(--sbt-kit-ease);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-ico {
  display: grid; place-items: center; flex: none; width: 48px; height: 48px; border-radius: var(--sbt-radius);
  background: var(--sbt-hue-bg); color: var(--sbt-hue-ink); transition: box-shadow var(--sbt-kit-dur) var(--sbt-kit-ease);
}
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-ico > svg.fi { width: 28px; height: 28px; }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-label { max-width: 100%; text-align: center; overflow-wrap: anywhere; }
/* pointed at or focused: the tile takes its colour's ground and lifts 1 px; its square stands out by a soft shadow */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-tile:is(:hover, :focus-visible) { background: var(--sbt-hue-bg); transform: translateY(-1px); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-tile:is(:hover, :focus-visible) .sbt-n7-ico { box-shadow: inset 0 1px 0 var(--sbt-glass-hi), var(--sbt-glass-shadow); }
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-tile.active { box-shadow: 0 0 0 2px var(--sbt-accent); }
/* the icon makes the shared Summer/Winter move (it is not the control's direct child, so the shared rule misses it) */
html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-tile:is(:hover, :focus-visible) .sbt-n7-ico > svg.fi {
  animation: var(--sbt-fi-anim, sbt-fi-pop) var(--sbt-fi-dur, .5s) var(--sbt-fi-ease, cubic-bezier(.34, 1.56, .64, 1)) both;
}
/* from 992 px: A1's row in one line, master's list out of view; a panel hangs centred under the whole bar (the group is
   not positioned, so the panel's box is the sticky top bar) */
@media (min-width: 992px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7 { display: flex; align-items: center; flex-wrap: nowrap; gap: 2px; min-width: 0; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-links { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-dd { position: static; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-panel {
    top: 100%; left: 0; right: 0; margin-top: .375rem; margin-left: auto; margin-right: auto;
    width: min(52rem, calc(100% - 2rem)); max-height: calc(100vh - 100% - 1rem); max-height: calc(100dvh - 100% - 1rem);
    overflow-y: auto; padding: var(--sbt-sp-3) 1rem 1rem;
  }
  /* the names do not fit one row: a trigger is a 40 px square, its arrow a corner mark, its name a tip */
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top { position: relative; width: 40px; padding: 0; justify-content: center; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-caret { position: absolute; right: 2px; bottom: 2px; width: .6rem; height: .6rem; margin: 0; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-name {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0);
    white-space: nowrap; border: 0;
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top:is(:hover, :focus-visible) > .sbt-n7-name {
    top: calc(100% + 6px); left: 50%; z-index: 2; width: auto; height: auto; margin: 0; padding: .2rem .5rem;
    overflow: visible; clip: auto; transform: translateX(-50%); border-radius: var(--sbt-radius-sm);
    background: var(--sbt-text); color: var(--sbt-surface); font-size: var(--sbt-fs-xs); font-weight: 600;
    pointer-events: none;
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-dd.open > .sbt-n7-top > .sbt-n7-name { opacity: 0; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-back { display: none; }
}
/* below 992 px: master's ☰ opens A1's sheet instead of master's long list, both only through :has() */
@media (max-width: 991px) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-inner:has(> .sbt-nav-links.open) > .sbt-n7 {
    display: grid; position: absolute; top: 100%; left: 0; right: 0;
    grid-template-columns: repeat(3, minmax(0, 1fr)); align-content: start; gap: var(--sbt-sp-2);
    max-height: calc(100vh - 100%); max-height: calc(100dvh - 100%); overflow-y: auto; overflow-x: hidden;
    overscroll-behavior: contain;
    padding: .75rem calc(.75rem + env(safe-area-inset-right, 0px)) 1rem calc(.75rem + env(safe-area-inset-left, 0px));
    background: var(--sbt-glass-bg-solid); border-bottom: 1px solid var(--sbt-glass-edge);
    box-shadow: var(--sbt-glass-shadow-hover);
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-nav-inner:has(> .sbt-nav-links.open) > .sbt-nav-links { display: none; }
  /* a top item is a big tile: its icon on its colour's 48 px square over its name, no arrow */
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-dd { flex-direction: column; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top {
    flex-direction: column; justify-content: flex-start; gap: .4rem; width: 100%; height: auto; padding: .6rem .3rem;
    white-space: normal; text-align: center; font-size: var(--sbt-fs-sm); overflow-wrap: anywhere;
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top > svg.fi {
    box-sizing: content-box; width: 28px; height: 28px; padding: 10px; border-radius: var(--sbt-radius);
    background: var(--sbt-hue-bg);
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-caret { display: none; }
  /* the cascade: an open group's tiles replace the sheet's grid, the Back row on top */
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7:has(> .sbt-n7-dd.open) > :not(.open) { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-dd.open { grid-column: 1 / -1; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-dd.open > .sbt-n7-top { display: none; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-dd.open > .sbt-n7-panel {
    position: static; width: auto; min-width: 0; max-height: none; padding: 0; border: 0; border-radius: 0;
    background: transparent; box-shadow: none;
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-bar {
    display: flex; align-items: center; gap: .5rem; margin: 0 0 .6rem; padding: 0 0 .6rem;
    border-bottom: 1px solid var(--sbt-glass-edge);
  }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* touch screens: the shared a11y layer's thumb size */
@media (pointer: coarse) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-tile, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-back { min-height: 44px; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top { min-width: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-top, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-tile, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-caret, html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-ico { transition: none !important; }
  html[data-sbt-theme^="prime"]:where(:not([data-sbt-theme="prime-dark"]), [data-sbt-look="prime-winter"]) .sbt-n7-tile:is(:hover, :focus-visible) { transform: none !important; }
}
/* manu code for a1 mega menu n7 ends here */
/* manu code for c3 bell number starts here */
/* WHY: the bell's unread number is white on the look's --sbt-danger (block "notification bell (WO-9)" above), and
   Bluebell Dark's rose (#fb7d9c, "night rose") is light, so the number was 2.47:1: unreadable at 10px (measured in a
   browser on the test site, 25-Oct-2026). This look's own notes already say a solid badge takes black.
   HOW: the number takes --sbt-on-danger, the a11y layer's token for text on --sbt-danger (black in this look, as in
   Prime Dark, whose bell rule does the same): 8.52:1. A token, not a colour: the a11y layer allows no colour in a
   rule here. It is added at the end of the file so the older bytes stay an exact prefix (the summer_kit and
   summer_glass goldens pin that), and the goldens that pin this file's end name it. The legacy dark and aura looks
   keep white until the user rules (the note in that block). Fruits Dark's twin is in fruits.css. */
html[data-sbt-theme="bluebell-dark"] .sbt-bell-badge { color: var(--sbt-on-danger); }
/* manu code for c3 bell number ends here */
