/* @foundation/ui design tokens — CSS custom-property mirror of tokens.js.
   COMBINATION B "Ivory Study" — The Study's ceremonial structure in the
   Broadsheet's warm cream + gold palette; Playfair Display type. */

:root {
  /* --- Viewport insets ----------------------------------------------------
     ONE owner for the iPhone home-indicator allowance. It used to be applied
     in two places at once (the chat wrapper AND the composer), so the phone
     double-counted it and left ~86px of dead cream under the message box.
     Anything that needs the allowance reads this, and nothing adds env() itself.

     --cc-kb is how much of the layout viewport an on-screen keyboard is
     covering, published by useKeyboardInset(). Zero on desktop and whenever the
     keyboard is down. */
  --cc-kb: 0px;
  --cc-safe-bottom: env(safe-area-inset-bottom, 0px);

  --cc-bg:         #f4f1e9;
  --cc-bg-soft:    #ece7d9;
  --cc-bg-deep:    #e3dcc9;
  --cc-bg-thread: #f1ead7;
  --cc-card:       #fbfaf4;

  --cc-navy:        #171410;
  --cc-navy-soft:   #272219;
  --cc-navy-medium: #332c20;
  --cc-navy-deep:   #0d0b07;

  /* A real navy blue for the "you" chat bubble — the --cc-navy role is a dark
     neutral in this palette (near-black), so the sender bubble needs its own
     genuinely-blue fill that carries white text on both grounds. */
  --cc-chat-mine:   #33466b;

  /* Meeting scratchpad "pens" — the two members write in one shared pad, so
     authorship has to read at a glance without a label: Alice in a dark
     neutral grey, Bob in a dark navy. Both must clear text contrast on
     the cream card, and lighten (never invert) on the dark ground. */
  --cc-pen-member-a:      #4a4a4a;
  --cc-pen-member-b:    #1e3a5f;
  --cc-pen-member-a-bg:   rgba(74, 74, 74, 0.05);
  --cc-pen-member-b-bg: rgba(30, 58, 95, 0.05);

  --cc-gold:       #b07a24;
  --cc-gold-bold:  #8f5f14;
  /* The accent as a FILL that carries WHITE content (the demo banner, the
     primary action button on Proposals/Brainstorm/Meetings/agent chat).
     --cc-gold is tuned for rules and seals and is held to no contrast target,
     so white on it measured 3.33:1 here. This is the same accent walked until
     white clears the 4.5:1 AA floor: 4.50:1 on white, 3.82:1 against the
     masthead so the button is still findable (WCAG 1.4.11). */
  --cc-gold-fill:  #a16c0c;
  --cc-gold-soft:  #a67c2e;
  --cc-gold-tint:  #f1e7d3;
  --cc-gold-pale:  #f1e7d3;
  --cc-gold-faint: rgba(176, 122, 36, 0.32);
  /* RGB triplet form of the accent, for rgba(var(--cc-gold-rgb), a) literals
     (masthead rules, borders) that need theme-aware alpha. Light = brass. */
  --cc-gold-rgb:   176, 122, 36;

  /* Interaction-layer accents (hover text, hover borders, hover tints) — kept
     as their own vars so interactions.css hovers turn orange in dark alongside
     the base accent. Light values = the original brass hover palette. */
  --cc-accent-hi:       #d8bf85;
  --cc-accent-line:     #c2a35d;
  --cc-accent-line-2:   #a98b4f;
  --cc-accent-tint-rgb: 169, 139, 79;

  --cc-ink:   #171410;
  --cc-ink-2: #57534a;
  --cc-ink-3: #8a867a;
  --cc-ink-4: #b0ab9b;

  --cc-line:   #e2dccb;
  --cc-line-2: #ece7d9;

  --cc-green: #4d7c54;
  --cc-amber: #b5791f;
  --cc-red:   #b0483e;
  --cc-green-rgb: 77, 124, 84;

  --cc-font-sans:         'Public Sans', system-ui, sans-serif;
  --cc-font-display:      'Playfair Display', Georgia, serif;
  --cc-font-display-soft: 'Playfair Display', Georgia, serif;
  --cc-font-mono:         'IBM Plex Mono', 'SF Mono', Menlo, monospace;
  /* The brand lockup (header wordmark + mobile drawer). Its own token because a
     STAMPED client's wordmark must render in THEIR display face — this was
     hardcoded as 'Cinzel' in three components, so every client's own name was
     drawn in the template's typeface. src/generated/theme.css overrides it. */
  --cc-font-wordmark:     'Cinzel', 'Trajan Pro', Georgia, serif;

  --cc-shadow-card: 0 1px 2px rgba(23, 20, 16, 0.05), 0 10px 30px rgba(23, 20, 16, 0.05);
  --cc-radius:    6px;
  --cc-radius-sm: 4px;

  /* Semantic chrome surfaces — the masthead band and the header button/pill
     "face". Broken out as their own tokens so dark mode can retune them
     without touching the components that consume them. */
  --cc-masthead: #f1ece0;
  --cc-btn-face: rgba(23, 20, 16, 0.03);

  /* Scrollbar + text selection — retuned per theme below. */
  --cc-scrollbar:       #d4cdbc;
  --cc-scrollbar-hover:  #c3bba6;
  --cc-selection: rgba(176, 122, 36, 0.20);

  /* Legacy-compat aliases — federation-remote agents (e.g. Oracle) reference
     these older var names; defined here so they resolve to Ivory values when
     an agent renders IN-SHELL (the agent's own :root only applies standalone). */
  --cc-cloud: var(--cc-bg);
  --cc-white: var(--cc-card);
  --cc-cream: var(--cc-gold-tint);
  --cc-muted: var(--cc-ink-2);
  --cc-serif: var(--cc-font-display);

  /* --- THE AGENT TOKEN BRIDGE -------------------------------------------
     Every agent built by the agent pipeline styles through `--bbl-*`. This
     Command Center defines `--cc-*`. Different namespaces — so before this
     block existed, an agent installed here rendered with EVERY `--bbl-*`
     UNDEFINED.

     That failure is worth spelling out, because it does not look like a
     failure. An undefined custom property does NOT fall back to a sensible
     value: the declaration becomes invalid at computed-value time, so
     `background: var(--bbl-card)` computes to TRANSPARENT while
     `color: var(--bbl-ink)` merely INHERITS. The result is an agent whose text
     is readable and whose cards, borders, badges and accents have all silently
     vanished — it reads as a thin or half-loaded page rather than a broken one,
     which is exactly why it survived a screenshot review. (Measured in a
     browser 2026-08-14: transparent background, inherited colour.)

     Aliases rather than copies, and that is the whole trick: a custom property
     that references another resolves AT USE, not at declaration. So these point
     at `--cc-*` and automatically follow whatever `src/generated/theme.css`
     sets for this client — including the dark-mode block, with no dark
     counterpart needed here. Verified in a browser across a theme flip.

     One block, and every agent this client ever installs inherits their brand
     with ZERO changes to the agent. Keep it exhaustive: a `--bbl-*` an agent
     can reference and this block does not name is an invisible element. */
  --bbl-bg:            var(--cc-bg);
  --bbl-bg-soft:       var(--cc-bg-soft);
  --bbl-bg-deep:       var(--cc-bg-deep);
  --bbl-card:          var(--cc-card);

  --bbl-navy:          var(--cc-navy);
  --bbl-navy-soft:     var(--cc-navy-soft);
  --bbl-navy-medium:   var(--cc-navy-medium);
  --bbl-navy-deep:     var(--cc-navy-deep);

  /* The accent family. Named "gold" in the agent kit for historical reasons —
     it is the ACCENT role, whatever colour the client actually chose. */
  --bbl-gold:          var(--cc-gold);
  --bbl-gold-bold:     var(--cc-gold-bold);
  --bbl-gold-soft:     var(--cc-gold-soft);
  --bbl-gold-tint:     var(--cc-gold-tint);
  --bbl-gold-faint:    var(--cc-gold-faint);
  --bbl-gold-rgb:      var(--cc-gold-rgb);

  --bbl-ink:           var(--cc-ink);
  --bbl-ink-2:         var(--cc-ink-2);
  --bbl-ink-3:         var(--cc-ink-3);
  --bbl-ink-4:         var(--cc-ink-4);

  --bbl-line:          var(--cc-line);
  --bbl-line-2:        var(--cc-line-2);

  --bbl-green:         var(--cc-green);
  --bbl-green-rgb:     var(--cc-green-rgb);
  --bbl-amber:         var(--cc-amber);
  --bbl-red:           var(--cc-red);

  --bbl-font-sans:     var(--cc-font-sans);
  --bbl-font-display:  var(--cc-font-display);
  --bbl-font-mono:     var(--cc-font-mono);

  --bbl-shadow-card:   var(--cc-shadow-card);

  /* Viewport insets: ONE owner (see the top of this file). An agent that reads
     these must get the host's values, never its own — double-counting the home
     indicator is what left ~86px of dead space under a composer. */
  --bbl-safe-bottom:   var(--cc-safe-bottom);
  --bbl-kb:            var(--cc-kb);

  /* The agent kit's own legacy aliases, which some older agents still use. */
  --bbl-cloud:         var(--cc-bg);
  --bbl-white:         var(--cc-card);
  --bbl-cream:         var(--cc-gold-tint);
  --bbl-muted:         var(--cc-ink-2);
  --bbl-serif:         var(--cc-font-display);

  /* Native controls (time picker, checkbox, default scrollbar) follow this. */
  color-scheme: light;
}

/* ---------------------------------------------------------------------------
   DARK MODE — "Ivory Study, after hours".
   The same warm cream + brass system relit on a warm near-black ground
   (browns, not cold grays) so the palette still reads as ivory paper turned
   down for the evening. Activated by data-theme="dark" on <html> (set pre-paint
   from localStorage in index.html; toggled at runtime by shell/theme.js).

   The saturated brass accents (--cc-gold / --cc-gold-soft) are deliberately
   NOT overridden — they read on both grounds and back the SVG icon strokes that
   consume the literal token values. Only --cc-gold-bold (text/links) brightens.
   ------------------------------------------------------------------------- */
:root[data-theme="dark"] {
  color-scheme: dark;

  --cc-bg:         #14120d;
  --cc-bg-soft:    #1b1811;
  --cc-bg-deep:    #201c14;
  --cc-bg-thread: #1d1912;
  --cc-card:       #1e1a13;

  /* "navy" is the raised-fill role (buttons, pills, icon squares, stat bands),
     always paired with light content — so in dark mode it inverts to a warm
     surface that sits ABOVE the card, not below it. Navy-as-text was migrated
     to --cc-ink so this inversion is safe. */
  --cc-navy:        #423a29;
  --cc-navy-soft:   #4d4432;
  --cc-navy-medium: #574d39;
  --cc-navy-deep:   #383021;

  /* Dark ground: lift the chat navy so it still reads blue over the warm-brown
     surface (not a muddy near-black). */
  --cc-chat-mine:   #3d5382;

  /* Scratchpad pens on the dark ground: the light-mode values are near-black
     here and would vanish, so both lift to legible tints that KEEP the
     grey-vs-navy distinction — the whole point of the two colours. */
  --cc-pen-member-a:      #b6b2aa;
  --cc-pen-member-b:    #7fa8d4;
  --cc-pen-member-a-bg:   rgba(182, 178, 170, 0.07);
  --cc-pen-member-b-bg: rgba(127, 168, 212, 0.09);

  /* Dark mode trades the ivory brass for a warm ORANGE accent — it contrasts
     harder against the warm-brown ground and reads more vividly than gold did.
     The base drives the agent-medallion rings/glyphs (via currentColor) and
     every gold fill/border; -bold is the brighter text/link/active tone. */
  --cc-gold:       #e07d33;
  --cc-gold-bold:  #f39a4d;
  /* Dark mode's white-on-gold measured WORSE than light (2.54:1), because the
     dark accent is brighter. The fill role is therefore darker than the accent
     here rather than lighter: 4.52:1 on white, 3.98:1 against the masthead. */
  --cc-gold-fill:  #bb5c00;
  --cc-gold-soft:  #cf7330;
  --cc-gold-tint:  #2c1c0f;
  --cc-gold-pale:  #2c1c0f;
  --cc-gold-faint: rgba(224, 125, 51, 0.30);
  --cc-gold-rgb:   224, 125, 51;

  --cc-accent-hi:       #f6a860;
  --cc-accent-line:     #e5893f;
  --cc-accent-line-2:   #cf7734;
  --cc-accent-tint-rgb: 224, 125, 51;

  --cc-ink:   #f2ede1;
  --cc-ink-2: #c4bca9;
  --cc-ink-3: #948c7b;
  --cc-ink-4: #6c6555;

  --cc-line:   #322c20;
  --cc-line-2: #2a251b;

  --cc-green: #6bb07a;
  --cc-amber: #d4972f;
  --cc-red:   #d9695f;
  --cc-green-rgb: 107, 176, 122;

  --cc-shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4), 0 12px 32px rgba(0, 0, 0, 0.5);

  --cc-masthead: #1a1610;
  --cc-btn-face: rgba(255, 255, 255, 0.05);

  --cc-scrollbar:       #3a3428;
  --cc-scrollbar-hover:  #4a4334;
  --cc-selection: rgba(215, 165, 63, 0.28);
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  background: var(--cc-bg);
  color: var(--cc-ink);
  font-family: var(--cc-font-sans);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--cc-selection); }
* { scrollbar-color: var(--cc-scrollbar) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--cc-scrollbar); border-radius: 999px; border: 3px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--cc-scrollbar-hover); border: 3px solid transparent; background-clip: content-box; }

/* Keyboard up: the keyboard COVERS the home indicator, so the safe-area
   allowance is no longer protecting anything — it just becomes dead space
   between the message box and the top of the keys. Zero it while the keyboard
   is open; useKeyboardInset() puts this class on <html>. */
:root.cc-kb-open {
  --cc-safe-bottom: 0px;
}

/* Keyboard up ALSO retires the phone tab bar. The layout viewport is already
   collapsed to a strip above the keys; a row of navigation between the field
   you are typing in and the keyboard is the most expensive 56px on the screen,
   and nobody changes tab mid-sentence. It comes back when the keyboard drops. */
:root.cc-kb-open [data-testid="mobile-tab-bar"] {
  display: none;
}

/* ---------------------------------------------------------------------------
   iOS FOCUS ZOOM — the one-rule fix.

   Mobile Safari ZOOMS THE WHOLE PAGE IN when you focus a form control whose
   font-size is under 16px, and it does not zoom back out when you leave the
   field. Every text input in this product was 13.5px (the shared INPUT_STYLE)
   or smaller, so tapping any of them — the client search, the dossier
   assistant, every field of every dialog — lurched the layout sideways and left
   it there. Measured on a stamped client 2026-08-25 across every form surface.

   The usual "fix" is `maximum-scale=1, user-scalable=no` on the viewport meta.
   That is not a fix, it is a WCAG 1.4.4 failure: it disables pinch-zoom for
   everyone, permanently, to paper over a font size. index.html deliberately
   does NOT do that, which is why this rule has to.

   `!important` because every control in this codebase is styled with an INLINE
   px font-size, and an inline declaration outranks any stylesheet rule without
   it. Scoped to `pointer: coarse` so the desktop's denser 13.5px controls are
   untouched — this is a touch-device correction, not a redesign.

   16px is the floor, not a target: `max(16px, …)` would be the same thing with
   more moving parts, since nothing in here is above 16 to begin with. */
/* Gated on `pointer: coarse` ALONE, unlike the touch-target rules, and that
   asymmetry is deliberate. The zoom bug exists only on a touch device, so a
   desktop browser resized to phone width has nothing to fix — and raising its
   inputs to 16px there WOULD be a visible regression in the one place the
   layout is reviewed. A control that is merely narrow is not a control being
   touched. */
@media (pointer: coarse) {
  input,
  textarea,
  select {
    font-size: 16px !important;
  }
}

/* ---------------------------------------------------------------------------
   THE TOUCH-TARGET FLOOR, app-wide.

   Measured across every phone surface of a stamped client 2026-08-25: the
   dashboard's month arrows 28x28, its panel buttons 30, the support footer's
   button 31, page actions 36, the masthead hamburger 40. The craft bar is 44
   (Apple 44pt / Material 48dp), the research minimum for a one-handed thumb is
   ~35px, and WCAG 2.5.8's hard floor is 24 -- so the smallest of these was
   failing the floor, not just the bar.

   Fixing forty inline style objects one at a time is how half of them get
   missed and how the next component added to the product starts under the bar
   again. One rule, at the root, is the invariant.

   `(pointer: coarse), (max-width: 700px)` is a union for the reason the bespoke
   sheet's twin is: coarse is the honest signal on the device and is FALSE in a
   desktop browser at 390px, which is where this layout is actually reviewed.

   THE EXCLUSIONS ARE THE LOAD-BEARING PART. Everything here is a control whose
   height is DERIVED from something other than ergonomics, and forcing 44px on
   it corrupts the thing it is derived from:
     .cc-cal-event  - absolutely positioned, sized in minutes. A 30-minute
                      meeting stretched to 44px detaches from its hour grid.
     .cc-cal-slot   - the hour cells behind it, already 46px, same geometry.
     .cc-skip-link  - visually hidden until focused; sizing it reveals it.
     [role="tab"] inside a scrolling tab row and the month grid's day cells are
     left alone for the same reason -- they are already >=44 by construction.
   A control that is inline BY NATURE (a mailto: inside a sentence) is also out:
   `display` is untouched here, so an inline element ignores min-height and is
   unaffected rather than broken. Those are sized where they are written.
   --------------------------------------------------------------------------- */
/* Desktop placement for the dashboard calendar's control group. It lives in the
   stylesheet rather than inline so the phone rule further down can recentre it
   by ordinary cascade — an inline `justify-self` would have forced an
   !important. It must stay ABOVE that media block: the two selectors have equal
   specificity, so document order is the only thing deciding the winner. */
.cc-cal-head > .cc-cal-nav {
  justify-self: end;
}

@media (pointer: coarse), (max-width: 700px) {
  button:not(.cc-cal-event):not(.cc-cal-slot):not(.cc-skip-link),
  [role="button"]:not(.cc-cal-event):not(.cc-cal-slot),
  input:not([type="checkbox"]):not([type="radio"]),
  select {
    min-height: 44px;
  }

  /* The craft bar is about the SMALLER axis, so a 40px-wide button fails it
     however tall it is -- which is exactly how the Rolodex "Edit" survived a
     min-height-only pass at 40px while "Delete" beside it passed at 55. */
  button:not(.cc-cal-event):not(.cc-cal-slot):not(.cc-skip-link) {
    min-width: 44px;
  }
}

@media (max-width: 700px) {
  /* THE DASHBOARD CALENDAR HEAD, restacked. This is the direct COST of the touch
     floor immediately above, and it belongs beside it.

     CalendarPanel's head is one row: [spacer] [month title] [Today | < | > |
     New event]. Growing those four controls from 28px to the 44px floor took the
     control group from 236px to 268px, and the row's minimum from something that
     fitted a phone to something that does not. MEASURED 2026-08-27 on emulated
     iPhone 13 / iPhone SE / Pixel 7, in the fullest configuration this head row
     ever renders — a client with a bespoke calendar page (so "New event" is
     present) viewing a month other than the current one (so "Today" is present
     too). That combination is live on a real client today, which is why it is
     the one that was measured rather than the bare four-control default:

       before: "SEPTEMBER 2026" took TWO line boxes, head row 54px not 27px,
               and the document scrolled sideways at 445px against a 390px phone.

     Two lines of defect from one cause, and the wrap was only the visible half.
     Restacking to title-over-controls fixes both: the title gets the full width
     (so it never wraps) and the control group gets its own row (so nothing
     overflows).

     WIDTH ONLY, not the touch floor's `(pointer: coarse), (max-width: 700px)`
     union, and the asymmetry is the point. What breaks the row is that it is too
     NARROW to hold 268px of controls beside a 195px title; a wide touch device
     has room for both. Gating on the union would have restacked an iPad at
     820px, where one row fits with ~330px to spare. 700px is also exactly the
     breakpoint HomePage's own useViewportNarrow(700) uses to switch to
     MobileHome, so the head restacks precisely when the app is in its phone
     layout — one number, not two that can drift apart.
     Swept 2026-08-27 at 320/375/390/412/430/600/700/701/768/900/1024/1280/1440:
     one line box and zero horizontal overflow at every width, stacked at <=700
     and one row at >=701.

     `!important` for the same reason the iOS focus-zoom rule above needs it, and
     it is the only pair here that does: the head row's track definition is
     written as an INLINE style object in CalendarPanel.jsx (HEAD_STYLE), and an
     inline declaration outranks any stylesheet rule without it. The CHILDREN do
     not need it — they are placed with `grid-area`, which reads correctly
     against either template, which is exactly why they were written that way. */
  .cc-cal-head {
    grid-template-areas: "title" "nav" !important;
    grid-template-columns: minmax(0, 1fr) !important;
  }

  /* The spacer only exists to balance the control group across a three-track
     row. With one track there is nothing to balance, and leaving it in place
     would draw an empty third row. */
  .cc-cal-head > .cc-cal-pad {
    display: none;
  }

  .cc-cal-head > .cc-cal-nav {
    justify-self: center;
    flex-wrap: wrap;
    justify-content: center;
  }
}

/* ---------------------------------------------------------------------------
   NO BROWSER BACK-SWIPE (2026-08-26). A left-to-right swipe on a phone is the
   shell's own gesture — it opens the nav drawer (Header.jsx) — and the
   browser's history-back swipe was winning the race: "swiping left to right
   is taking me back to last page. it should always open up the sidebar."
   `overscroll-behavior-x: none` is the standard switch that disables the
   navigation gesture in Chrome, Edge and Android WebView while leaving
   vertical scrolling untouched. iOS Safari does not offer web content this
   control for its edge swipe; there the edge stays the OS's and everything
   inboard of it is ours, which the drawer handler already handles.
   --------------------------------------------------------------------------- */
html, body {
  overscroll-behavior-x: none;
}
/* GENERATED FILE (scaffold-owned) — src/generated/theme.css
 *
 * Frank Benton's palette, generated from
 * clients/frank-benton/client.config.json by scripts/lib/palette.mjs.
 *
 * Source brand colors:
 *   primary #1E0693   accent #03541B
 *   neutral #ebeddf
 *   background #f7f7f8   background (dark) derived
 *   ANCHORED: --cc-bg is the literal colour above; the other grounds hold
 *   their relative offsets from it.
 *
 * Ramps are built in OKLCH (perceptually uniform), so lightness moves without
 * the hue drift plain hex arithmetic produces. Every foreground role is then
 * walked until it clears its WCAG target against the ground it actually sits
 * on — a brand color chosen for a logo is not automatically a legible UI color.
 *
 * Measured contrast, light: ink 13.06:1 on bg-deep, ink-2 5.85:1 on bg-deep, ink-3 3.05:1 on bg-deep, gold-bold 6.96:1 on bg-deep, green 3.82:1 on bg-deep, amber 4.08:1 on bg-deep, red 4.32:1 on bg-deep, white on navy 15.07:1, white on chat-mine 9.92:1, white on gold-fill 9.18:1
 * Measured contrast, dark:  ink 14.06:1 on bg-deep, ink-2 8.7:1 on bg-deep, ink-3 4.68:1 on bg-deep, gold-bold 6.38:1 on bg-deep, green 6.77:1 on bg-deep, amber 6.45:1 on bg-deep, red 6.15:1 on bg-deep, white on navy 9.92:1, white on chat-mine 7.66:1, white on gold-fill 4.62:1
 *
 * Loaded AFTER tokens.css and overrides it. HAND-EDITS ARE WRONG: rebrand by
 * editing the client config and re-running the scaffolder, so the config and
 * the UI can never disagree.
 */

:root {
  --cc-bg: #f7f7f8;
  --cc-bg-soft: #ececed;
  --cc-bg-deep: #e0e0e1;
  --cc-bg-thread: #f0f0f1;
  --cc-card: #ffffff;
  --cc-masthead: #f1f1f2;
  --cc-navy: #1a0087;
  --cc-navy-soft: #241ca0;
  --cc-navy-medium: #3137b7;
  --cc-navy-deep: #150075;
  --cc-chat-mine: #2c2eaf;
  --cc-pen-member-a: #4d4e48;
  --cc-pen-member-b: #2c2eaf;
  --cc-pen-member-a-bg: rgba(77, 78, 72, 0.05);
  --cc-pen-member-b-bg: rgba(44, 46, 175, 0.05);
  --cc-gold: #03541b;
  --cc-gold-bold: #03541b;
  --cc-gold-fill: #03541b;
  --cc-gold-soft: #00460c;
  --cc-gold-tint: #d4ecd5;
  --cc-gold-pale: #d4ecd5;
  --cc-gold-faint: rgba(3, 84, 27, 0.32);
  --cc-gold-rgb: 3, 84, 27;
  --cc-accent-hi: #3e8348;
  --cc-accent-line: #21682f;
  --cc-accent-line-2: #004c12;
  --cc-accent-tint-rgb: 0, 76, 18;
  --cc-ink: #1a1c12;
  --cc-ink-2: #525448;
  --cc-ink-3: #7e8073;
  --cc-ink-4: #a4a699;
  --cc-line: #d0d3c1;
  --cc-line-2: #e2e5d5;
  --cc-green: #447b46;
  --cc-amber: #965e00;
  --cc-red: #b24039;
  --cc-green-rgb: 68, 123, 70;
  --cc-shadow-card: 0 1px 2px rgba(26, 28, 18, 0.05), 0 10px 30px rgba(26, 28, 18, 0.05);
  --cc-btn-face: rgba(26, 28, 18, 0.03);
  --cc-scrollbar: #bdc0ab;
  --cc-scrollbar-hover: #a4a793;
  --cc-selection: rgba(3, 84, 27, 0.2);
  --cc-font-sans: 'Inter', system-ui, -apple-system, sans-serif;
  --cc-font-display: 'Playfair Display', Georgia, serif;
  --cc-font-display-soft: 'Playfair Display', Georgia, serif;
  --cc-font-wordmark: 'Playfair Display', Georgia, serif;
  --cc-font-mono: 'IBM Plex Mono', 'SF Mono', Menlo, monospace;
  --cc-brand-primary: #1E0693;
  --cc-brand-accent: #03541B;
  --cc-brand-background: #f7f7f8;
}

:root[data-theme="dark"] {
  --cc-bg: #10110a;
  --cc-bg-soft: #191a13;
  --cc-bg-deep: #20211a;
  --cc-bg-thread: #1c1d16;
  --cc-card: #1d1e17;
  --cc-masthead: #15160f;
  --cc-navy: #2c2eaf;
  --cc-navy-soft: #3841c1;
  --cc-navy-medium: #4451d3;
  --cc-navy-deep: #241ca0;
  --cc-chat-mine: #3942c3;
  --cc-pen-member-a: #aaaca4;
  --cc-pen-member-b: #7d96ff;
  --cc-pen-member-a-bg: rgba(170, 172, 164, 0.07);
  --cc-pen-member-b-bg: rgba(125, 150, 255, 0.09);
  --cc-gold: #6cb274;
  --cc-gold-bold: #6cb274;
  --cc-gold-fill: #3e8348;
  --cc-gold-soft: #5da265;
  --cc-gold-tint: #0f2512;
  --cc-gold-pale: #0f2512;
  --cc-gold-faint: rgba(108, 178, 116, 0.3);
  --cc-gold-rgb: 108, 178, 116;
  --cc-accent-hi: #88cf8f;
  --cc-accent-line: #72b87a;
  --cc-accent-line-2: #63a86b;
  --cc-accent-tint-rgb: 99, 168, 107;
  --cc-ink: #eef0e2;
  --cc-ink-2: #bdbfb2;
  --cc-ink-3: #898b7e;
  --cc-ink-4: #636559;
  --cc-line: #2e2f24;
  --cc-line-2: #24251c;
  --cc-green: #7cb57d;
  --cc-amber: #d49838;
  --cc-red: #f47c70;
  --cc-green-rgb: 124, 181, 125;
  --cc-shadow-card: 0 1px 2px rgba(0, 0, 0, 0.4), 0 12px 32px rgba(0, 0, 0, 0.5);
  --cc-btn-face: rgba(255, 255, 255, 0.05);
  --cc-scrollbar: #38392c;
  --cc-scrollbar-hover: #4d4f41;
  --cc-selection: rgba(108, 178, 116, 0.28);
}
/* Atelier profile — token overrides, CLIENT edition.
 *
 * The port of BBL's own atelier/tokens-atelier.css onto a client Command
 * Center. Everything here is scoped under :root[data-ui="atelier"], stamped
 * pre-paint by index.html, so with the stamp removed this file is completely
 * inert and the classic UI is byte-identical.
 *
 * ── THE ONE RULE THAT MAKES THIS DIFFERENT FROM BBL'S ─────────────────────
 *
 * BBL's Atelier profile hardcodes BBL's palette: pure white, #15160f ink,
 * #b08a3c gold, Bodoni. A client Command Center may not do that. The client's
 * palette is GENERATED from their own brand colours by scripts/lib/palette.mjs
 * (src/generated/theme.css), walked to WCAG targets, and it is the entire
 * reason a client CC looks like the client rather than like us. Overwriting it
 * here would ship the operator's own gold to every client we have.
 *
 * So this file overrides COMPOSITION ROLES ONLY:
 *
 *   grounds       page/card/masthead become one sheet of paper
 *   hairlines     a second, stronger rule weight for control borders
 *   elevation     cards go FLAT; only floating layers keep a shadow
 *   radii         8px panels / 6px controls (the locked "Bento" density)
 *   button face   the card ground rather than a tinted wash
 *
 * and touches NO hue role. --cc-navy*, --cc-gold*, --cc-accent*, the status
 * hues, --cc-chat-mine, the member pens and every font var are left exactly as
 * the client's generated theme set them. A client whose brand is indigo and
 * green stays indigo-and-green in the Atelier; it just wears the Atelier's
 * composition.
 *
 * The wash grounds are mixed from --cc-line — itself derived from the client's
 * `neutral` brand colour — rather than from a literal grey, so a client who
 * chose a warm neutral gets a warm wash and a cool one gets a cool wash. Each
 * color-mix() is preceded by a plain fallback for any engine that cannot parse
 * it: the fallback is a correct, slightly flatter answer, never a broken one.
 *
 * ── LOAD ORDER IS LOAD-BEARING ────────────────────────────────────────────
 *
 * index.html links this AFTER src/generated/theme.css. :root[data-ui="atelier"]
 * ties :root on specificity, so document order is what makes these values win.
 * The member's own brand-colour override (the inline <style> injected later in
 * index.html) still wins over both — it sets hues, which this file does not
 * touch, so the two never collide.
 *
 * ── DARK MODE SURVIVES ────────────────────────────────────────────────────
 *
 * BBL's Atelier is deliberately light-only: its profile block overrides the
 * same properties the dark block sets, so with Atelier on the dark toggle does
 * nothing. That is not acceptable here — a client CC ships a working Appearance
 * setting and taking it away in a re-skin is a regression, not a redesign. So
 * every override below is written twice, once per theme, and the dark half is
 * scoped :root[data-ui="atelier"][data-theme="dark"] so it outranks the light
 * half on specificity regardless of order.
 */

:root[data-ui="atelier"] {
  /* ── Grounds: the page IS the paper ──────────────────────────────────────
     The classic client CC separates page from card (#f7f7f8 under #ffffff) and
     gives the masthead a third tint again, so a panel reads as a tile ON a
     surface and the masthead as a band ACROSS it. The Atelier composition
     removes both separations: page, card and masthead are one sheet and the
     hairlines do all the dividing.

     ── WHY THESE POINT AT --cc-bg AND NEVER AT A LITERAL WHITE ─────────────

     Because --cc-bg is the CLIENT'S ground and this file must not have an
     opinion about it. Two reasons, and the second one is a bug I shipped and
     had to come back for:

     1. A client whose brand background is a warm cream keeps their cream. The
        composition is "card and page are the same sheet", not "the sheet is
        white" — and pinning it white would quietly delete a brand decision the
        palette engine had already made.
     2. It is the ONLY way dark mode survives. :root[data-ui="atelier"] and
        theme.css's :root[data-theme="dark"] have IDENTICAL specificity, and
        this file loads second — so a literal --cc-bg here beats the dark
        ground and paints a dark-mode session's light-ink text onto a white
        page. Which is exactly what it did: unreadable, and it looked fine in
        every light-mode screenshot. Never assigning --cc-bg means there is
        nothing to lose that fight with.

     The washes mix from the client's own hairline toward their own ground, so
     they work in BOTH directions without being written twice: --cc-line is
     darker than the ground in light and lighter than it in dark, so the same
     expression darkens a light wash and lifts a dark one. */
  --cc-card:      var(--cc-bg);
  --cc-masthead:  var(--cc-bg);

  --cc-bg-soft:   color-mix(in srgb, var(--cc-line) 26%, var(--cc-bg));
  --cc-bg-deep:   color-mix(in srgb, var(--cc-line) 44%, var(--cc-bg));
  --cc-bg-thread: color-mix(in srgb, var(--cc-line) 14%, var(--cc-bg));

  /* ── Hairlines: a second weight ─────────────────────────────────────────
     --cc-line stays the client's own default rule. --cc-line-strong is NEW and
     Atelier-only: the mockup's control-border weight, used by pills, icon
     buttons, table heads and the sheet grab-handle. Mixed toward ink from the
     client's own line so it is the same hue, one step firmer. */
  --cc-line-strong: #d5d5d2;
  --cc-line-strong: color-mix(in srgb, var(--cc-line) 78%, var(--cc-ink));

  /* ── Elevation: FLAT ─────────────────────────────────────────────────────
     Variation 3 "Bento" (locked 2026-09-04): panels and cards carry no shadow
     at all — the hairline is the edge. Floating layers (dropdowns, the search
     overlay, popovers) are the exception and take --at-shadow-pop, because a
     layer that genuinely sits above the page has to say so. */
  --cc-shadow-card: none;
  --at-shadow-pop:
    0 1px 2px rgba(0, 0, 0, 0.04),
    0 18px 44px rgba(0, 0, 0, 0.07);

  /* ── Radii: the Bento density ───────────────────────────────────────────
     8px panels, 6px controls. tokens.js resolves bblRadius.md/.sm through
     these custom properties, so every inline-styled component moves with them
     — which is the whole reason that indirection exists. */
  --cc-radius:    8px;
  --cc-radius-sm: 6px;

  /* Button faces sit ON the paper rather than being a tinted panel of their
     own; the hairline is what makes them a button. */
  --cc-btn-face: var(--cc-bg);
}

/* ── The corrections dark actually needs ────────────────────────────────────
   Almost nothing, because the block above is written in terms of the client's
   own ground and hairline and therefore already follows the theme. Only two
   things genuinely differ after dark, and both are about a hairline having
   less to work with on a near-black ground:

     · a card given EXACTLY the page ground disappears — in light the hairline
       carries the edge on its own, in dark it needs the panel lifted a step
       off the page as well;
     · --cc-line-strong takes a longer walk toward the ink. The light
       expression is already correct in both themes (--cc-ink inverts with the
       theme, so mixing toward it darkens a light rule and lightens a dark
       one); it simply needs MORE of that walk here, because a near-black
       ground gives a hairline less to separate itself from.

   Higher specificity than the block above (three compound parts against two),
   so this wins regardless of source order. */
:root[data-ui="atelier"][data-theme="dark"] {
  --cc-card: color-mix(in srgb, var(--cc-line) 34%, var(--cc-bg));

  --cc-line-strong: #46473b;
  --cc-line-strong: color-mix(in srgb, var(--cc-line) 62%, var(--cc-ink));

  --at-shadow-pop:
    0 1px 2px rgba(0, 0, 0, 0.4),
    0 20px 48px rgba(0, 0, 0, 0.55);
}

/* index.html's pre-mount loader stamps a font shorthand literal (it renders
   before any bundle, so it cannot read tokens.js). Point it at the client's own
   display face so the very first frame is already in their typography. */
:root[data-ui="atelier"] #root:empty::before {
  font-family: var(--cc-font-display, 'Playfair Display', Georgia, serif);
}
/* Atelier profile — component styles, CLIENT edition.
 *
 * Ported from BBL's own atelier/atelier.css (the approved cc-full-template
 * mockup, locked 2026-09-04). Two systematic changes were made in the port and
 * nothing else was invented:
 *
 *   1. --bbl-* became --cc-*, the client template's token namespace.
 *   2. Every literal BBL hue was replaced by the token that carries it, so a
 *      focus ring, a hover glow and an underline are the CLIENT's accent
 *      rather than the operator's gold. rgba() literals became
 *      color-mix(in srgb, var(--cc-gold) N%, transparent) for the same reason.
 *
 * BBL-only sections were dropped rather than ported dead: the forest agency
 * roster band, the engraved agent marks, the Records dev-log accordion, the
 * Time .barrow bars, the Tasks toolbar and the Consults lobby rows have no
 * counterpart in a client Command Center.
 *
 * EVERYTHING here is scoped under [data-ui="atelier"]; keyframe names are
 * at-prefixed (keyframes cannot be attribute-scoped, so the prefix is the
 * collision guard). With the stamp removed, no element carries these classes
 * and no rule can match — the classic UI is untouched.
 */

/* ================= THE ARRIVAL — "The Composition" =================
   Mark rises, rule draws, page lifts in. Timings locked in the mockup:
   veil-out at 1.6s, mark-in .9s@.05s, word .7s@.5s, rule .8s@.35s. */
:root[data-ui="atelier"] .at-veil {
  position: fixed; inset: 0; z-index: 80; display: grid; place-items: center;
  background: transparent; pointer-events: none;
}
:root[data-ui="atelier"] .at-veil-bg { position: absolute; inset: 0; background: var(--cc-bg); }
:root[data-ui="atelier"] .at-veil-stage { position: relative; display: grid; place-items: center; gap: 16px; }
:root[data-ui="atelier"] .at-veil img { display: block; width: 74px; height: auto; opacity: 0; }
/* THE MARK IS A BLACK PNG. On the light ground that is the whole design; after
   dark it is a black silhouette on a near-black veil — an arrival that renders
   a gold rule, a wordmark, and a hole where the mark should be.
   BBL's own Atelier never hit this because that profile is light-only; a
   client Command Center ships a working dark mode and so must this.
   Same mechanism the phone bar uses for the same artwork (.cc-mobile-mark in
   home/interactions.css): flatten to black, then invert to a white silhouette.
   Safe here in a way it is NOT on a client's own logo — this file is the
   operator's mark, one known asset, monochrome by construction.
   Scoped to .at-veil-mark, NOT to `.at-veil img`. Under a white-label stamp
   the fallback in this slot is the CLIENT's artwork, and inverting a logo we
   do not own is precisely the destruction BrandMark.jsx refuses to do — see
   its plate note. The class is only ever put on the operator's own file. */
:root[data-ui="atelier"][data-theme="dark"] .at-veil-mark {
  filter: brightness(0) invert(1);
}

/* ── THE ARRIVAL WEARS THE OPERATOR'S TYPOGRAPHY, NOT THE CLIENT'S ────────
   Cinzel and the gold are LITERALS here, and that is the point rather than an
   oversight. Every other rule in this file resolves through the client's
   palette and type tokens, because every other surface is the client's. The
   arrival is not: it is the same composition on every Command Center, so it
   must not move when a client picks a different display face or a different
   accent. Reading --cc-font-wordmark and --cc-gold here is exactly what made
   this one render in Playfair over a green rule.

   Cinzel is loaded by index.html OUTSIDE the CC:FONTS markers, so a re-stamp
   that rewrites the client's own faces cannot take it away. */
:root[data-ui="atelier"] .at-veil-word {
  font-family: 'Cinzel', Constantia, Georgia, serif; font-size: 13px;
  letter-spacing: .5em; text-transform: uppercase;
  /* The ink token, not a literal — this is the one value that SHOULD follow
     the theme, because the veil covers the page with the page's own ground and
     a fixed near-black would be invisible on it after dark. */
  color: var(--cc-ink);
  opacity: 0; padding-left: .5em; text-align: center;
}
:root[data-ui="atelier"] .at-veil-rule {
  width: 0; height: 1px;
  /* The operator's gold. */
  background: #b08a3c;
  /* The drawn rule's final length — the keyframe reads this, so the phone
     block below can shorten the rule without a second keyframe. */
  --at-rule-w: 150px;
}
:root[data-ui="atelier"] .at-run .at-veil-bg { animation: at-veil-out .6s ease 1.6s forwards; }
:root[data-ui="atelier"] .at-run .at-veil-stage { animation: at-veil-out .5s ease 1.6s forwards; }
:root[data-ui="atelier"] .at-run img { animation: at-mark-in .9s cubic-bezier(.2,.7,.2,1) .05s forwards; }
:root[data-ui="atelier"] .at-run .at-veil-word { animation: at-mark-in .7s ease .5s forwards; }
:root[data-ui="atelier"] .at-run .at-veil-rule { animation: at-rule-out .8s cubic-bezier(.4,0,.2,1) .35s forwards; }
@keyframes at-mark-in { from { opacity: 0; transform: translateY(8px) scale(.94); } to { opacity: 1; transform: none; } }
@keyframes at-rule-out { to { width: var(--at-rule-w, 150px); } }
@keyframes at-veil-out { to { opacity: 0; visibility: hidden; } }
@keyframes at-mark-in-m { from { opacity: 0; transform: translateY(14px) scale(.9); } to { opacity: 1; transform: none; } }

/* The arrival on PHONES: retuned rather than scaled down. The stage is lifted
   above true centre, which also masks the downward shift when browser chrome
   collapses mid-animation (a fixed inset:0 layer grows at the BOTTOM edge when
   the address bar hides). Every beat the chime keys on is untouched. */
@media (max-width: 700px) {
  :root[data-ui="atelier"] .at-veil {
    padding-bottom: calc(8vh + env(safe-area-inset-bottom));
    box-sizing: border-box;
  }
  :root[data-ui="atelier"] .at-veil-stage { gap: 14px; }
  :root[data-ui="atelier"] .at-veil img { width: clamp(56px, 17vw, 70px); }
  :root[data-ui="atelier"] .at-veil-word {
    font-size: clamp(10.5px, 3.1vw, 12px);
    letter-spacing: .42em;
    padding-left: .42em;
  }
  :root[data-ui="atelier"] .at-veil-rule { --at-rule-w: clamp(96px, 34vw, 140px); }
  :root[data-ui="atelier"] .at-run img { animation-name: at-mark-in-m; animation-duration: .8s; }
  :root[data-ui="atelier"] .at-run .at-veil-word { animation-duration: .6s; }
  :root[data-ui="atelier"] .at-run .at-veil-rule { animation-duration: .7s; }
}

/* ================= MASTHEAD ================= */
/* Fluid frame — fills the viewport with a readable ceiling; no dead margins.
   NOTE the borderTop: the client template puts a 3px rule of the client's
   PRIMARY colour across the top of every masthead, because primary is
   otherwise nearly invisible on a Command Center (2026-08-24). That rule is
   data about whose Command Center this is, not decoration, so the Atelier
   masthead keeps it. */
:root[data-ui="atelier"] .at-headwrap {
  position: relative;
  background: var(--cc-bg);
  border-top: 3px solid var(--cc-navy);
  border-bottom: 1px solid var(--cc-line);
  flex-shrink: 0;
  /* Its own stacking context ABOVE the page content, so the nav dropdowns
     always paint in front of what follows. */
  z-index: 50;
}
:root[data-ui="atelier"] .at-frame {
  max-width: 1720px; margin: 0 auto; padding: 0 clamp(16px, 3vw, 48px);
}
:root[data-ui="atelier"] .at-header {
  display: flex; align-items: center; gap: 26px; padding: 18px 0 16px;
}

/* Compact single-row lockup: mark + wordmark. The mark is BrandMark, which may
   be a logo, initials set as type, or nothing at all — a client with
   monogram.hidden gets a pure-type lockup, which is the right answer when the
   name IS the identity. */
:root[data-ui="atelier"] .at-lockup {
  display: flex; align-items: flex-end; gap: 13px; flex-shrink: 0;
  text-decoration: none; color: inherit;
  background: transparent; border: none; padding: 0; cursor: pointer;
  font: inherit; text-align: left;
}
:root[data-ui="atelier"] .at-lockup img { display: block; width: auto; }
:root[data-ui="atelier"] .at-wordmark {
  font-family: var(--cc-font-wordmark, var(--cc-font-display)); font-weight: 600;
  font-size: 16px; letter-spacing: .18em; text-transform: uppercase;
  line-height: 1; padding-bottom: 2px; color: var(--cc-ink);
  white-space: nowrap;
}
:root[data-ui="atelier"] .at-wordmark small {
  display: block; font-family: var(--cc-font-sans); font-weight: 600;
  font-size: 8.5px; letter-spacing: .34em; color: var(--cc-ink-3); margin-top: 5px;
}

/* Small-caps horizontal nav with the full-label accent underline. */
:root[data-ui="atelier"] .at-nav { display: flex; gap: 2px; margin-left: 4px; }
:root[data-ui="atelier"] .at-nav a {
  position: relative; color: var(--cc-ink-2); text-decoration: none;
  font-size: 12.5px; letter-spacing: .09em; text-transform: uppercase;
  padding: 10px 13px; transition: color .15s; cursor: pointer;
}
/* The active underline runs edge-to-edge of the tab label (a touch beyond),
   never narrower than the word. */
:root[data-ui="atelier"] .at-nav a::after {
  content: ''; position: absolute; left: 9px; right: 9px; bottom: 4px;
  height: 2px; background: var(--cc-gold); border-radius: 2px;
  transform: scaleX(0); transform-origin: left;
  transition: transform .22s cubic-bezier(.2,.7,.2,1);
}
:root[data-ui="atelier"] .at-nav a:hover { color: var(--cc-ink); }
:root[data-ui="atelier"] .at-nav a:hover::after { transform: scaleX(1); }
:root[data-ui="atelier"] .at-nav a[aria-current] { color: var(--cc-ink); }
:root[data-ui="atelier"] .at-nav a[aria-current]::after { transform: scaleX(1); }

/* THE SUB-TAB ROW (template 1.24.0) — the active page's own children, one tier
   down. It exists here because the Atelier masthead REPLACES the classic one
   outright: without this, a client who declares `children` on a page would get
   a schema-supported feature that renders nowhere, and nothing would say so.

   It is quieter than .at-nav by SIZE and TRACKING, never by contrast. The
   classic Header.jsx SUBNAV comment records why: ink-3 measures 3.40:1 on the
   masthead, under the 4.5:1 AA floor at small sizes, so the second tier holds
   ink-2/ink exactly as the first does and the hierarchy is carried by the type
   scale and by a THINNER rule — a rule is not text and carries no contrast
   floor, which is the same reasoning that moved the accent onto one in
   1.17.0-rc.1. */
:root[data-ui="atelier"] .at-subnav {
  display: flex; flex-wrap: wrap; align-items: center; gap: 2px;
  padding: 0 0 10px; margin-left: 4px;
}
:root[data-ui="atelier"] .at-subnav a {
  position: relative; color: var(--cc-ink-2); text-decoration: none;
  /* The 24px WCAG 2.5.8 target floor the nav row was fixed to in 1.17.0-rc.1.
     A second row of links is not a second-class row of links. */
  display: inline-flex; align-items: center; min-height: 24px;
  font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase;
  padding: 4px 10px; transition: color .15s; cursor: pointer;
}
:root[data-ui="atelier"] .at-subnav a::after {
  content: ''; position: absolute; left: 7px; right: 7px; bottom: 0;
  height: 1px; background: var(--cc-gold); border-radius: 1px;
  transform: scaleX(0); transform-origin: left;
  transition: transform .22s cubic-bezier(.2,.7,.2,1);
}
:root[data-ui="atelier"] .at-subnav a:hover { color: var(--cc-ink); }
:root[data-ui="atelier"] .at-subnav a:hover::after { transform: scaleX(1); }
:root[data-ui="atelier"] .at-subnav a[aria-current] { color: var(--cc-ink); }
:root[data-ui="atelier"] .at-subnav a[aria-current]::after { transform: scaleX(1); }

/* Hover dropdowns — a tab reveals its sub-pages for direct navigation. */
:root[data-ui="atelier"] .at-navitem { position: relative; }
/* Permanent invisible hover extension: during the .15s open delay the pointer
   often drifts DOWN into the 10px gap before the panel exists, killing :hover
   — this strip keeps .at-navitem:hover alive across the gap. */
:root[data-ui="atelier"] .at-navitem::after {
  content: ''; position: absolute; top: 100%; left: 0; right: 0; height: 14px;
}
:root[data-ui="atelier"] .at-drop {
  position: absolute; top: calc(100% + 10px); left: 6px; min-width: 176px;
  background: var(--cc-bg); border: 1px solid var(--cc-line);
  border-radius: 12px; box-shadow: var(--at-shadow-pop); padding: 7px; z-index: 60;
  opacity: 0; visibility: hidden; transform: translateY(7px);
  transition: opacity .18s ease, transform .18s cubic-bezier(.2,.7,.2,1), visibility .18s;
}
/* Invisible bridge so the pointer can cross the gap without closing it. */
:root[data-ui="atelier"] .at-drop::before {
  content: ''; position: absolute; top: -12px; left: 0; right: 0; height: 12px;
}
/* Keyboard focus (focus-visible) opens a dropdown; a mouse CLICK must not pin
   one open — that's how two could show at once. */
:root[data-ui="atelier"] .at-navitem:hover .at-drop,
:root[data-ui="atelier"] .at-navitem:has(:focus-visible) .at-drop {
  opacity: 1; visibility: visible; transform: none; transition-delay: .15s;
}
:root[data-ui="atelier"] .at-drop a {
  display: block; padding: 9px 13px; font-size: 12.5px; letter-spacing: .02em;
  text-transform: none; color: var(--cc-ink-2); border-radius: 7px; white-space: nowrap;
}
:root[data-ui="atelier"] .at-drop a::after { display: none; }
:root[data-ui="atelier"] .at-drop a:hover { background: var(--cc-bg-soft); color: var(--cc-ink); }
/* A clicked navitem's dropdown vanishes at once; hover re-arms on re-entry. */
:root[data-ui="atelier"] .at-navitem.at-drop-lock .at-drop {
  opacity: 0 !important; visibility: hidden !important; transition: none;
}

/* Utility cluster: search pill, bell, support, gear. */
:root[data-ui="atelier"] .at-util { margin-left: auto; display: flex; align-items: center; gap: 9px; }
:root[data-ui="atelier"] .at-iconbtn {
  width: 36px; height: 36px; border: 1px solid var(--cc-line-strong, var(--cc-line));
  background: var(--cc-bg); border-radius: 999px; display: grid;
  place-items: center; cursor: pointer; color: var(--cc-ink-2);
  transition: border-color .15s, color .15s, box-shadow .15s; position: relative;
  padding: 0;
}
:root[data-ui="atelier"] .at-iconbtn:hover {
  border-color: var(--cc-gold); color: var(--cc-ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cc-gold) 12%, transparent);
}
:root[data-ui="atelier"] .at-iconbtn:focus-visible,
:root[data-ui="atelier"] .at-nav a:focus-visible,
:root[data-ui="atelier"] .at-subnav a:focus-visible,
:root[data-ui="atelier"] .at-textbtn:focus-visible,
:root[data-ui="atelier"] .at-lockup:focus-visible {
  outline: 2px solid var(--cc-gold); outline-offset: 2px;
}
/* The word buttons beside the icons — "Support", "Log out". Small caps, no
   box: the client template's masthead carries both and they must not become
   two more circles competing with the bell and the gear. */
:root[data-ui="atelier"] .at-textbtn {
  border: none; background: none; padding: 8px 4px; cursor: pointer;
  font-family: var(--cc-font-sans); font-size: 10.5px; font-weight: 600;
  letter-spacing: .18em; text-transform: uppercase; color: var(--cc-ink-3);
  transition: color .15s; white-space: nowrap;
}
:root[data-ui="atelier"] .at-textbtn:hover { color: var(--cc-ink); }
/* Unread count — a bare superscript numeral at the bell's shoulder. */
:root[data-ui="atelier"] .at-ncount {
  position: absolute; top: 1px; right: 4px; font-family: var(--cc-font-sans);
  font-size: 10px; line-height: 1; color: var(--cc-gold-bold); font-weight: 700;
  background: none; border: 0; padding: 0;
}

/* The masthead nav collapses on narrow windows (the phone bar + drawer keep
   serving navigation there). */
@media (max-width: 980px) {
  :root[data-ui="atelier"] .at-nav,
  :root[data-ui="atelier"] .at-subnav { display: none; }
}

/* ================= NOTICES WIRE ================= */
/* Mockup .wire: a hairlined strip — small-caps accent label, one rotating
   message, index dots, dismiss. Rotation is JS-driven; this is presentation.

   IT ALIGNS ITSELF WITH THE PAGE, because of where it is mounted. The wire
   renders inside AnnouncementBanner, which is a flex SIBLING of <main> and
   therefore spans the full window rather than the padded content column. Left
   alone it would start its label hard against the window edge while the hero
   below it began 48px in — the two most prominent lines on the page,
   misaligned.

   So it carries the SAME padding expression as Shell's PAGE_STYLE and the same
   max-width cap, which is why those numbers are repeated here rather than
   referenced: they belong to a JS style object this file cannot read. If the
   page gutter is ever retuned, this is its second home. The phone block near
   the foot of this file mirrors PAGE_PHONE_STYLE for the same reason. */
:root[data-ui="atelier"] .at-wire {
  display: flex; align-items: center; gap: 14px;
  padding: 10px clamp(16px, 3vw, 48px) 9px;
  /* width:100% is NOT redundant beside max-width. This is a flex ITEM in the
     shell's column, and it is itself display:flex — so without an explicit
     width it takes its shrink-to-fit content width and the strip renders as a
     short centred bar floating in the middle of the page, nowhere near the
     hero's left edge. Measured on the deployed preview, not reasoned about.
     The cap and the auto margins then centre the COLUMN on a wide monitor,
     exactly as PAGE_STYLE does for the content below. */
  width: 100%;
  max-width: 1600px; margin: 0 auto; box-sizing: border-box;
  border-bottom: 1px solid var(--cc-line);
}
@media (max-width: 700px) {
  :root[data-ui="atelier"] .at-wire { padding: 9px 12px 8px; gap: 10px; }
}
/* The body, when a notice has one: quieter than the title and the first thing
   to go when the strip runs out of room. */
:root[data-ui="atelier"] .at-wire-sub { color: var(--cc-ink-3); }
:root[data-ui="atelier"] .at-wire-lbl {
  font-size: 9px; letter-spacing: .32em; text-transform: uppercase;
  color: var(--cc-gold-bold); flex-shrink: 0; font-weight: 600;
}
:root[data-ui="atelier"] .at-wire-msg {
  flex: 1; min-width: 0; font-size: 12px; color: var(--cc-ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
:root[data-ui="atelier"] .at-wire-idx { display: flex; gap: 5px; flex-shrink: 0; }
:root[data-ui="atelier"] .at-wire-idx i {
  width: 4px; height: 4px; border-radius: 50%;
  background: var(--cc-line-strong, var(--cc-line));
}
:root[data-ui="atelier"] .at-wire-idx i.on { background: var(--cc-gold); }
:root[data-ui="atelier"] .at-wire-close {
  flex-shrink: 0; width: 20px; height: 20px; border: 1px solid var(--cc-line);
  background: none; border-radius: 50%; color: var(--cc-ink-3);
  font-size: 10px; line-height: 1; cursor: pointer;
  display: grid; place-items: center; padding: 0;
  transition: color .15s, border-color .15s;
}
:root[data-ui="atelier"] .at-wire-close:hover {
  color: var(--cc-ink); border-color: var(--cc-line-strong, var(--cc-line));
}
:root[data-ui="atelier"] .at-wire-close:focus-visible {
  outline: 2px solid var(--cc-gold); outline-offset: 2px;
}

/* ================= HERO ACTION PILLS (mockup .act) ================= */
:root[data-ui="atelier"] .at-act {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--cc-line-strong, var(--cc-line));
  background: var(--cc-bg); border-radius: 999px; padding: 8px 16px;
  font-size: 12.5px; font-weight: 600; color: var(--cc-ink); cursor: pointer;
  font-family: var(--cc-font-sans);
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
:root[data-ui="atelier"] .at-act:hover {
  border-color: var(--cc-gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cc-gold) 12%, transparent);
  transform: translateY(-1px);
}
:root[data-ui="atelier"] .at-act svg { color: var(--cc-gold-bold); }
/* The primary pill takes the INK, not the brand hue: it is the one filled
   control in the composition and the mockup's filled control is the ink
   itself. The client's primary already owns the masthead rule and every Save
   button; a third claim on it here would make the hero shout. */
:root[data-ui="atelier"] .at-act.at-act-primary {
  background: var(--cc-ink); border-color: var(--cc-ink); color: var(--cc-bg);
}
:root[data-ui="atelier"] .at-act.at-act-primary:hover {
  box-shadow: 0 4px 14px color-mix(in srgb, var(--cc-ink) 26%, transparent);
}
:root[data-ui="atelier"] .at-act.at-act-primary svg { color: var(--cc-bg); }
:root[data-ui="atelier"] .at-act:focus-visible {
  outline: 2px solid var(--cc-gold); outline-offset: 2px;
}

/* ================= THE FIGURES BAND ================= */
/* Mockup .figures: an OPEN band — no card, no fill — of hairline-separated
   cells, each a small-caps label over an oversized serif numeral over a quiet
   caption. Cells are buttons where they lead somewhere. */
:root[data-ui="atelier"] .at-figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  border-top: 1px solid var(--cc-line);
  border-bottom: 1px solid var(--cc-line);
  margin: 4px 0 22px;
}
:root[data-ui="atelier"] .at-fig {
  padding: 18px 20px; text-align: left; border-left: 1px solid var(--cc-line);
  background: none; font: inherit; color: inherit; cursor: default;
  transition: background .18s;
}
:root[data-ui="atelier"] .at-fig:first-child { border-left: 0; padding-left: 0; }
:root[data-ui="atelier"] button.at-fig { cursor: pointer; }
:root[data-ui="atelier"] button.at-fig:hover { background: var(--cc-bg-soft); }
:root[data-ui="atelier"] button.at-fig:focus-visible {
  outline: 2px solid var(--cc-gold); outline-offset: -2px;
}
:root[data-ui="atelier"] .at-fig-lbl {
  display: block; font-family: var(--cc-font-sans); font-size: 9.5px;
  font-weight: 600; letter-spacing: .26em; text-transform: uppercase;
  color: var(--cc-ink-3);
}
:root[data-ui="atelier"] .at-fig-val {
  display: block; font-family: var(--cc-font-display); font-weight: 400;
  font-size: 38px; line-height: 1.1; color: var(--cc-ink); margin-top: 8px;
  font-variant-numeric: lining-nums;
}
:root[data-ui="atelier"] .at-fig-cap {
  display: block; font-family: var(--cc-font-sans); font-size: 11px;
  color: var(--cc-ink-3); margin-top: 7px;
}

/* ================= THE DOSSIER ASSISTANT ================= */
/* The ask bar lights as ONE control when anything inside it takes focus. That
   cannot be written inline — :focus-within has no inline form — so it is
   hooked here on the panel's stable testid. Without it the bar is a box that
   contains a focused input while looking exactly as it did at rest, which is
   the tell that a composed control is really four controls in a row. */
:root[data-ui="atelier"] [data-testid="dossier-assistant"] form:focus-within {
  border-color: var(--cc-gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cc-gold) 12%, transparent);
}
:root[data-ui="atelier"] [data-testid="dossier-assistant"] form {
  transition: border-color .15s, box-shadow .15s;
}
/* The glyph buttons are borderless at rest, so they need a hover ground to be
   discoverable as buttons at all. Not applied while they are live — a filled
   accent does not want a wash over it. */
:root[data-ui="atelier"] [data-testid="assistant-mic"]:hover,
:root[data-ui="atelier"] [data-testid="assistant-converse"]:hover {
  background: var(--cc-bg-soft);
  color: var(--cc-ink);
}
:root[data-ui="atelier"] [data-testid="assistant-mic"][aria-pressed="true"]:hover,
:root[data-ui="atelier"] [data-testid="assistant-converse"][aria-pressed="true"]:hover {
  background: inherit; color: inherit;
}
:root[data-ui="atelier"] [data-testid="assistant-ask"]:not(:disabled):hover {
  box-shadow: 0 4px 14px color-mix(in srgb, var(--cc-ink) 24%, transparent);
}

/* ================= SEGMENTED CONTROLS + PAGERS =================
   The two segmented controls in the product — the calendar's Day/Week/Month
   and Settings' text size — plus the calendar's pager. Both were written as
   6px rectangles with a solid accent fill on the selected item, which is the
   only remaining control shape on these pages that is not a pill.

   Hooked on stable testids rather than restyled in place, for two reasons: the
   selected/unselected colours are computed inline from the palette (so this
   layer only has to change the SHAPE and let the colour through), and the
   files they live in are core, where an inline edit is a hand-edited-core
   finding rather than a skin.

   !important is deliberate and confined: these fight inline styles, and no
   classic session carries data-ui, so none of it can leak. */
:root[data-ui="atelier"] [data-testid^="calendar-view-"],
:root[data-ui="atelier"] [data-testid^="settings-text-size-"] {
  border-radius: 999px !important;
}
/* The pager: three equal round controls, so ← Today → reads as one object
   rather than two squares either side of a wider one. */
:root[data-ui="atelier"] [data-testid="calendar-prev"],
:root[data-ui="atelier"] [data-testid="calendar-next"],
:root[data-ui="atelier"] [data-testid="calendar-today"] {
  border-radius: 999px !important;
  border-color: var(--cc-line-strong, var(--cc-line)) !important;
}
:root[data-ui="atelier"] [data-testid="calendar-prev"]:hover,
:root[data-ui="atelier"] [data-testid="calendar-next"]:hover,
:root[data-ui="atelier"] [data-testid="calendar-today"]:hover {
  border-color: var(--cc-gold) !important;
}

/* The operator-contact CTA in the page footer. Its FILL stays the client's
   navy — that is a deliberate decision recorded in OperatorContact.jsx (primary
   is otherwise nearly invisible on a Command Center, and this button is on
   every route), and the palette engine pins the navy role's lightness so white
   on it is safe whatever primary the client picked. Only the shape changes, so
   it stops being the last rectangle in a product of pills. */
:root[data-ui="atelier"] [data-testid="operator-contact-toggle"] {
  border-radius: 999px !important;
}

/* NO BLANKET `main button:hover` RULE HERE, deliberately. It is the obvious
   way to give the new hairline pills a hover — and it would also repaint the
   border of every calendar day cell, every glyph button in the assistant and
   every toggle, all of which are buttons too and none of which wants a gold
   edge. A hover state that is right on eight controls and wrong on forty is a
   worse design than no hover state. The pills that need one ask for it by
   testid, above and below. */

/* ================= INTERIOR IDIOM LAYER =================
   The preview's interior vocabulary applied over inline-styled components
   through their STABLE hooks (testids, element selectors). !important is
   deliberate: these fight inline styles, and this is a skin layer confined to
   this file and this profile — a classic session carries no data-ui, so none
   of it can leak. */

/* .mh — the quiet small-caps panel head. The dashboard panels print a centred
   serif title; the Atelier head is a quiet sans label that lets the panel's
   CONTENT be the loud thing. */
:root[data-ui="atelier"] [data-testid^="panel-"] > h3 {
  font-family: var(--cc-font-sans) !important;
  font-size: 10px !important;
  letter-spacing: .26em !important;
  text-transform: uppercase !important;
  color: var(--cc-ink-3) !important;
  font-weight: 700 !important;
  text-align: left !important;
}

/* .tbl — every data table reads as the preview's table. */
:root[data-ui="atelier"] main table { border-collapse: collapse !important; }
:root[data-ui="atelier"] main table th {
  text-align: left;
  font-size: 9.5px !important;
  letter-spacing: .22em !important;
  text-transform: uppercase !important;
  color: var(--cc-ink-3) !important;
  font-weight: 700 !important;
  padding: 10px 12px !important;
  border-bottom: 1px solid var(--cc-line-strong, var(--cc-line)) !important;
  background: transparent !important;
}
:root[data-ui="atelier"] main table td {
  padding: 12px !important;
  border-bottom: 1px solid var(--cc-line) !important;
  background: transparent !important;
}
:root[data-ui="atelier"] main table tr:last-child td { border-bottom: 0 !important; }

/* .pinput — every page-level search input becomes the round pill. */
:root[data-ui="atelier"] main input[type="search"] {
  border-radius: 999px !important;
  border: 1px solid var(--cc-line-strong, var(--cc-line)) !important;
  padding: 8px 15px !important;
  background: var(--cc-bg) !important;
}
:root[data-ui="atelier"] main input[type="search"]:focus {
  outline: none;
  border-color: var(--cc-gold) !important;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cc-gold) 14%, transparent) !important;
}

/* The page HEAD on an interior page — mockup .agenthead: an oversized serif
   name over a quiet blurb, with the section rule beneath. Hooked on the
   client-page heading rather than a class, so a bespoke page written before
   this existed still takes the idiom. */
:root[data-ui="atelier"] main > div > div > h1,
:root[data-ui="atelier"] main h1 {
  font-family: var(--cc-font-display) !important;
  font-weight: 400 !important;
  letter-spacing: .004em !important;
}

/* ================= SEARCH OVERLAY (⌘K) ================= */
:root[data-ui="atelier"] .at-scrim {
  position: absolute; inset: 0;
  background: color-mix(in srgb, var(--cc-ink) 34%, transparent);
  backdrop-filter: blur(2px);
}
:root[data-ui="atelier"] .at-searchov { position: fixed; inset: 0; z-index: 85; }
:root[data-ui="atelier"] .at-spanel {
  position: relative; margin: 11vh auto 0; width: min(580px, 92vw);
  background: var(--cc-bg); border: 1px solid var(--cc-line);
  border-radius: 16px; padding: 10px; box-sizing: border-box;
  max-height: 70vh; overflow: auto;
  box-shadow: var(--at-shadow-pop);
}
:root[data-ui="atelier"] .at-sinput {
  width: 100%; box-sizing: border-box; border: 0;
  border-bottom: 1px solid var(--cc-line); border-radius: 0; padding: 14px 12px;
  font-family: var(--cc-font-sans); font-size: 15px; color: var(--cc-ink);
  background: transparent;
}
:root[data-ui="atelier"] .at-sinput:focus { outline: none; border-bottom-color: var(--cc-gold); }
:root[data-ui="atelier"] .at-sgroup {
  font-size: 9px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--cc-gold-bold); font-weight: 700; padding: 14px 12px 5px;
}
:root[data-ui="atelier"] .at-srow {
  display: block; width: 100%; text-align: left; padding: 9px 12px;
  border-radius: 9px; border: none; background: transparent; cursor: pointer;
  font-family: var(--cc-font-sans); color: inherit;
}
:root[data-ui="atelier"] .at-srow:hover,
:root[data-ui="atelier"] .at-srow:focus-visible { background: var(--cc-bg-soft); }
:root[data-ui="atelier"] .at-srow b { display: block; font-size: 13px; font-weight: 600; color: var(--cc-ink); }
:root[data-ui="atelier"] .at-srow span { font-size: 11px; color: var(--cc-ink-3); }

/* The masthead search pill (mockup .search). */
:root[data-ui="atelier"] .at-search {
  display: flex; align-items: center; gap: 9px;
  border: 1px solid var(--cc-line-strong, var(--cc-line));
  border-radius: 999px; padding: 8px 15px; color: var(--cc-ink-3);
  font-size: 12.5px; min-width: 190px; background: var(--cc-bg);
  transition: border-color .15s, box-shadow .15s; cursor: text;
  font-family: var(--cc-font-sans);
}
:root[data-ui="atelier"] .at-search:hover {
  border-color: var(--cc-gold);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--cc-gold) 12%, transparent);
}
:root[data-ui="atelier"] .at-search kbd {
  margin-left: auto; font-family: var(--cc-font-mono); font-size: 10px;
  border: 1px solid var(--cc-line); border-radius: 4px; padding: 1px 5px;
}
@media (max-width: 1240px) {
  :root[data-ui="atelier"] .at-search { display: none; }
}

/* ================= PHONE BAR + DRAWER ================= */
:root[data-ui="atelier"] .at-mbar {
  display: flex; align-items: center; gap: 11px;
  padding: 12px 16px; padding-top: calc(12px + env(safe-area-inset-top));
  background: var(--cc-bg); border-top: 3px solid var(--cc-navy);
  border-bottom: 1px solid var(--cc-line);
  position: relative; z-index: 40; flex-shrink: 0;
}
:root[data-ui="atelier"] .at-mbar-home {
  flex: 1; min-width: 0; display: flex; align-items: center; justify-content: center;
  gap: 8px; background: transparent; border: none; padding: 0; cursor: pointer;
}
:root[data-ui="atelier"] .at-mbar-word {
  font-family: var(--cc-font-wordmark, var(--cc-font-display)); font-weight: 600;
  font-size: 11px; letter-spacing: .24em; text-transform: uppercase;
  padding-left: .24em; color: var(--cc-ink); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
:root[data-ui="atelier"] .at-drawer {
  position: fixed; inset: 0; z-index: 70;
  visibility: hidden; transition: visibility 0s .32s;
}
:root[data-ui="atelier"] .at-drawer.at-open { visibility: visible; transition-delay: 0s; }
:root[data-ui="atelier"] .at-drawer .at-scrim { opacity: 0; transition: opacity .28s; }
:root[data-ui="atelier"] .at-drawer.at-open .at-scrim { opacity: 1; }
:root[data-ui="atelier"] .at-dpanel {
  position: absolute; top: 0; bottom: 0; left: 0; width: min(292px, 82vw);
  background: var(--cc-bg); border-right: 1px solid var(--cc-line);
  padding: calc(16px + env(safe-area-inset-top)) 12px calc(16px + env(safe-area-inset-bottom));
  overflow-y: auto; box-sizing: border-box;
  transform: translateX(-102%); transition: transform .32s cubic-bezier(.2,.7,.2,1);
}
:root[data-ui="atelier"] .at-drawer.at-open .at-dpanel { transform: none; }
:root[data-ui="atelier"] .at-dhead {
  display: flex; align-items: center; gap: 10px;
  padding: 0 8px 16px; border-bottom: 1px solid var(--cc-line); margin-bottom: 10px;
}
:root[data-ui="atelier"] .at-dhead span {
  font-family: var(--cc-font-wordmark, var(--cc-font-display)); font-size: 11px;
  letter-spacing: .22em; text-transform: uppercase; color: var(--cc-ink);
  flex: 1; min-width: 0;
}
:root[data-ui="atelier"] .at-dclose { width: 30px; height: 30px; font-size: 11px; }
:root[data-ui="atelier"] .at-dpanel nav a {
  display: block; padding: 12px 10px; font-size: 13px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--cc-ink-2); text-decoration: none;
  border-radius: 8px;
}
:root[data-ui="atelier"] .at-dpanel nav a:hover { background: var(--cc-bg-soft); color: var(--cc-ink); }
:root[data-ui="atelier"] .at-dpanel nav a[aria-current] {
  color: var(--cc-ink); box-shadow: inset 2px 0 0 var(--cc-gold); background: var(--cc-bg-soft);
}
:root[data-ui="atelier"] .at-dgroup {
  font-size: 8.5px; letter-spacing: .3em; text-transform: uppercase;
  color: var(--cc-gold-bold); font-weight: 700; padding: 16px 10px 6px;
}

/* ================= BOTTOM-SHEET MODALS (phone) ================= */
:root[data-ui="atelier"] .at-sheet { animation: at-sheet-up .32s cubic-bezier(.2,.7,.2,1); }
:root[data-ui="atelier"] .at-sheet::before {
  content: ''; display: block; width: 36px; height: 4px; border-radius: 2px;
  background: var(--cc-line-strong, var(--cc-line)); margin: 0 auto 14px;
}
@keyframes at-sheet-up { from { transform: translateY(105%); } to { transform: none; } }

/* ================= CLIENT ROSTER CARDS ================= */
/* The lift-on-hover the mockup gives a board card. Hooked on the stable
   testid so the component needs no class plumbing. */
:root[data-ui="atelier"] [data-testid^="client-card"],
:root[data-ui="atelier"] [data-testid="clients-card"] {
  transition: transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .25s;
}
:root[data-ui="atelier"] [data-testid^="client-card"]:hover,
:root[data-ui="atelier"] [data-testid="clients-card"]:hover {
  transform: translateY(-4px);
  box-shadow: var(--at-shadow-pop);
}

/* ================= MOBILE HOME ================= */
@media (max-width: 700px) {
  /* Hero: the mobile template's tighter scale. */
  :root[data-ui="atelier"] [data-testid="atelier-hero"] h1 {
    font-size: clamp(32px, 9.5vw, 42px) !important;
  }
  :root[data-ui="atelier"] [data-testid="atelier-hero"] .at-welcome {
    font-size: 16.5px !important;
  }
  /* Action pills ride one edge-to-edge scrolling row (template .actions). */
  :root[data-ui="atelier"] [data-testid="atelier-hero"] .at-actions {
    flex-wrap: nowrap !important;
    overflow-x: auto;
    scrollbar-width: none;
    margin: 0 calc(-1 * clamp(14px, 3vw, 44px));
    padding-left: clamp(14px, 3vw, 44px) !important;
    padding-right: clamp(14px, 3vw, 44px) !important;
  }
  :root[data-ui="atelier"] [data-testid="atelier-hero"] .at-actions::-webkit-scrollbar {
    display: none;
  }
  :root[data-ui="atelier"] [data-testid="atelier-hero"] .at-actions .at-act {
    flex-shrink: 0; white-space: nowrap;
  }
  /* Figures 2-up, each stacked row taking its own hairline and the left-edge
     cells of the lower rows dropping the column rule. */
  :root[data-ui="atelier"] .at-figures { grid-template-columns: 1fr 1fr; }
  :root[data-ui="atelier"] .at-fig { padding: 14px 14px; }
  :root[data-ui="atelier"] .at-fig:nth-child(odd) { border-left: 0; padding-left: 0; }
  :root[data-ui="atelier"] .at-fig:nth-child(n+3) { border-top: 1px solid var(--cc-line); }
  :root[data-ui="atelier"] .at-fig-val { font-size: 34px; }
}

@media (prefers-reduced-motion: reduce) {
  :root[data-ui="atelier"] .at-veil { display: none; }
  :root[data-ui="atelier"] .at-nav a::after,
  :root[data-ui="atelier"] .at-subnav a::after,
  :root[data-ui="atelier"] .at-drop { transition: none; }
  :root[data-ui="atelier"] [data-testid^="client-card"],
  :root[data-ui="atelier"] [data-testid="clients-card"] { transition: none; }
  :root[data-ui="atelier"] [data-testid^="client-card"]:hover,
  :root[data-ui="atelier"] [data-testid="clients-card"]:hover { transform: none; }
  :root[data-ui="atelier"] .at-dpanel { transition: none; }
  :root[data-ui="atelier"] .at-drawer .at-scrim { transition: none; }
  :root[data-ui="atelier"] .at-sheet { animation: none; }
  :root[data-ui="atelier"] .at-act:hover { transform: none; }
}

/* ── SEARCH RESULT SNIPPETS ───────────────────────────────────────────────
   The ⌘K box searches record CONTENT now (see SearchOverlay.jsx), so a row can
   carry a fragment of the sentence that matched. ts_headline marks the matched
   words and the component renders them as <mark> — never as raw HTML.
   The snippet sits on its own line under the subtitle because a dated line is
   meaningless cropped to a few words on the end of a title. */
.at-srow .at-ssnip {
  display: block;
  margin-top: 2px;
  opacity: 0.85;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.at-srow .at-ssnip mark {
  background: transparent;
  color: inherit;
  font-weight: 700;
}
/* Interaction states for the bespoke Clients and Calendar pages.
 *
 * A SEPARATE stylesheet, not additions to foundation-ui/home/interactions.css:
 * that file is frozen core (CORE_MANIFEST hashes it) and these classes exist
 * only in this Command Center. Putting them there would be a core hand-edit,
 * which upgrade-client refuses and conformance reports.
 *
 * Everything resolves through --cc-* tokens, so these states follow the client
 * brand, dark mode, and the member's own colour picks without knowing about any
 * of them. No literal colours.
 *
 * Hover only — every one of these elements is a real <button> or <a>, so
 * :focus-visible is handled here too and keyboard use is never a second class.
 */

/* Roster row in the Clients page.
 *
 * Each row is DIVIDED from the next by a hairline. Without it the roster was a
 * single undifferentiated column of text where three companies read as one
 * block, and the only thing separating "Bronco Industrial" from "United
 * International Partners" was the gap the subtitle line happened to leave.
 *
 * The rule is on the TOP of each row and suppressed on the first, rather than
 * on the bottom of each and suppressed on the last: :first-child is a real
 * selector and :last-child would still draw a line above the card's own bottom
 * edge whenever the list is scrolled. It is drawn with an inset box-shadow, not
 * a border, because these rows have a 3px left border that carries the selected
 * client's colour, and adding a border-top would shift the row's box by 1px the
 * moment it is selected. */
.cc-client-row {
  transition: background 0.12s;
}
.cc-client-row + .cc-client-row {
  box-shadow: inset 0 1px 0 var(--cc-line-2, var(--cc-line));
}
.cc-client-row:hover {
  background: rgba(var(--cc-accent-tint-rgb), 0.10) !important;
}
.cc-client-row:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: -2px;
}

/* An event block or an all-day chip in the calendar. The lift is a shadow
   rather than a colour change: the fill IS the client's identity here, and
   tinting it on hover would make two clients briefly look like each other. */
.cc-cal-event {
  transition: box-shadow 0.12s, transform 0.12s;
}
.cc-cal-event:hover {
  box-shadow: 0 1px 6px rgba(23, 20, 16, 0.18);
}
.cc-cal-event:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: 1px;
}

/* An empty hour cell. It has no visible affordance at rest on purpose — 24
   outlined boxes per day is noise — so hover is what tells you it is clickable. */
.cc-cal-slot {
  transition: background 0.1s;
}
.cc-cal-slot:hover {
  background: rgba(var(--cc-accent-tint-rgb), 0.12);
}
.cc-cal-slot:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: -2px;
}

/* The three ways in to "Add a note" on the dashboard — Dictate, Photo, Type.
   They sit at rest as three outlined tiles; hover tints the fill so the pointer
   says which one it is on, since all three are the same size and shape. */
.cc-note-way {
  transition: background 0.12s, border-color 0.12s;
}
.cc-note-way:hover:not(:disabled) {
  background: rgba(var(--cc-accent-tint-rgb), 0.12);
  border-color: var(--cc-gold-bold, var(--cc-accent-line));
}
.cc-note-way:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: 1px;
}

/* Dialog buttons and the tab row. Kept generic so both pages inherit it. */
[data-testid$="-form"] button:focus-visible,
[role="tab"]:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: 2px;
}


/* ---------------------------------------------------------------------------
   WHAT THE APP-WIDE TOUCH FLOOR CANNOT DO.

   tokens.css now carries the 44px minimum for every control in the product
   (see the note there, including why .cc-cal-event and .cc-cal-slot are
   excluded). What is left here is the part that is specific to these pages and
   is about SPACING and INLINE text rather than about size.
   --------------------------------------------------------------------------- */
@media (pointer: coarse), (max-width: 700px) {
  /* Size alone is insufficient: the finger's contact patch is 16-20mm, larger
     than any of these targets, so adjacent controls need real space between
     them. Measured 2px between Rolodex's Edit and its DESTRUCTIVE Delete. */
  [data-testid="rolodex-page"] button + button,
  [data-testid="clients-page"] button + button {
    margin-left: 8px;
  }

  /* tel: / mailto: on a contact card are the highest-value actions on the page
     and rendered as 15px-tall text. They are INLINE by nature -- inside a line
     that also carries a separator -- so the app-wide min-height does not reach
     them and should not: making them 44px blocks would break the card's
     typography. inline-block plus padding is the honest compromise, and they
     remain a deliberate, stated exception to the 44px bar rather than a miss. */
  [data-testid="rolodex-page"] a[href^="tel:"],
  [data-testid="rolodex-page"] a[href^="mailto:"] {
    display: inline-block;
    padding: 7px 0;
  }
}

/* THE PAGE BLURB IS DESKTOP FURNITURE.
   Every one of these pages opens with a two-to-three line explanation of what
   the page is. On a laptop that is a helpful subtitle in the margin of a wide
   header. On a 390px phone it is ~130px — a sixth of the screen — spent
   re-explaining a page the member navigates to several times a day, above the
   content they came for, on every single visit. The title still says what the
   page is; the tab that brought them here said it too.
   Hidden, not deleted: it is one media query, and the desktop keeps it. */
@media (max-width: 700px) {
  .cc-page-blurb {
    display: none;
  }
}

/* THE BRAND-MARK TAB, BIGGER (2026-09-10: "make the dossier assistant button
   the BB logo be bigger"). 27px -> 38px.

   Done HERE rather than in MobileTabBar.jsx because that file is frozen core —
   a hand-edit there is a conformance finding and blocks upgrades — while the
   size of THIS client's assistant tab is this client's preference, not a fix
   every Command Center should receive. The tab's stable test id is the hook;
   the img's width/height ATTRIBUTES are presentational hints, which any
   author CSS outranks, so no !important is needed.

   2026-09-16, round two: 38px -> 46px ("i just want the actual BB logo at the
   bottom middle of the page where the other tab buttons are to be a bit larger
   without doing anything else to the rest of the page").

   38 WAS the ceiling only while the tab kept its 8px of vertical padding: 56px
   bar - 16 = 40. The padding is what is spent here instead.

   THE ARITHMETIC HAS A THIRD TERM, and leaving it out is what made the first
   attempt 58px: every tab also carries a 2px top border (transparent until the
   tab is active — it is the selected-tab marker). So the box is
   2 + padding + icon + padding, and 2 + 4 + 46 + 4 = 56 EXACTLY. The bar stays
   56px tall at top=788, which is the whole constraint: "without doing anything
   else to the rest of the page". Verified on production, not reasoned about —
   at 5px the bar measured 58px and the tab bar had moved up to 786.

   !important because the tab sets `padding: 8px 4px` INLINE, and an inline
   declaration outranks any author rule without it. The img's width/height are
   plain HTML attributes, which any author CSS already outranks — those two need
   no !important, and keeping them clean says which is which.

   Only the DOSSIER tab is re-padded, not its neighbours: the others carry a
   label under the icon and need their 8px. The horizontal 4px is untouched, so
   the tab's own width and the bar's spacing are unchanged. */
@media (max-width: 700px) {
  [data-testid="mobile-tab-dossier"] img {
    width: 46px;
    height: 46px;
  }

  [data-testid="mobile-tab-dossier"] {
    padding-top: 4px !important;
    padding-bottom: 4px !important;
  }
}

/* ── THE LISTENING GLOW ───────────────────────────────────────────────────
   While the Dossier Assistant has the microphone open, the EDGES of the screen
   breathe. This is the Siri/Alexa affordance: the phone stops looking like a
   page with a form on it and starts looking like a thing that is listening to
   you, from across the room, without reading a word.

   It is deliberately an EDGE treatment and not a tint over the content — the
   conversation underneath still has to be readable while it runs, and a wash
   over the whole screen would make the answer harder to read at exactly the
   moment it arrives.

   Fixed to the viewport rather than the page column so it frames the WHOLE
   screen including the masthead and the tab bar, which is what makes it read
   as a device state rather than a widget state. pointer-events:none so it
   never eats a tap; aria-hidden on the element itself.

   The colour comes from --cc-listen-glow, set inline from the client's own
   accent, so a re-branded Command Center glows in its own colour rather than
   in a hardcoded gold.

   2026-09-10 — stronger, and it MOVES ("slightly more prominent and have some
   movement"). The frame is thicker and brighter and never breathes below 60%
   (it used to dip to 45%, where on a bright screen it all but vanished). The
   frame lives on ::before so its breathing and the orbiting light below are
   separate animations rather than one opacity multiplying the other.

   container-type: size makes the glow its own size container, so the orbit can
   be measured in cqw/cqh — exactly the box it is drawn in — rather than in
   vw/vh, which on iOS Safari describe the LARGE viewport and would run the
   light off the bottom whenever the toolbar is showing. */
.cc-listen-glow {
  position: fixed;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  overflow: hidden;
  container-type: size;
}

/* THE PHONE ONLY (2026-09-17, Maxim: "remove the green glow that appears when
   voice talking to dossier on web — that should only appear on the mobile
   interface").

   This treatment was designed for ARM'S LENGTH. Frank's brief was a phone on
   the desk or at his side, where a 12px label beside a microphone icon is
   unreadable and only a device-wide signal carries. On a desktop none of that
   holds: the member is eighteen inches from a large screen with the voice pill
   and its moving bars already in view, so the full-viewport frame carries no
   information the pill has not already given — and it washes the accent over
   the answer at exactly the moment they are trying to read it.

   A media query rather than a gate in ListeningGlow.jsx, deliberately: a
   window dragged across the breakpoint, or a phone rotated, resolves with no
   re-render, and a JS gate would duplicate a breakpoint that already lives in
   this file. The component still mounts and still holds its state; above 700px
   it simply draws nothing.

   700px is this repo's phone line — Header.jsx's useViewportNarrow(700) and
   every other breakpoint here. Keep them together. */
@media (min-width: 701px) {
  .cc-listen-glow {
    display: none;
  }
}

.cc-listen-glow::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 2px;
  box-shadow:
    inset 0 0 0 3px var(--cc-listen-glow, rgba(198, 160, 74, 0.9)),
    inset 0 0 34px 6px var(--cc-listen-glow-soft, rgba(198, 160, 74, 0.46)),
    inset 0 0 90px 16px var(--cc-listen-glow-faint, rgba(198, 160, 74, 0.2));
  animation: cc-listen-breathe 2.4s ease-in-out infinite;
}

@keyframes cc-listen-breathe {
  0%, 100% { opacity: 0.6; }
  50%      { opacity: 1; }
}

/* THE ORBITING LIGHT (round two, 2026-09-10: "the glow needs more movement
   like an actual moving rotating glow").

   Round one had four pools, one per side, brightening in turn. It read as
   blinking, not as motion. Now two comets chase each other round the edge of
   the screen, half a lap apart, clockwise. Each comet is a head and two
   trailing glows; each glow is a soft disc whose CENTRE runs along the
   screen's perimeter. The glow container clips the outer half, so what shows is
   a pool of light pressed against the edge, sliding along it and round the
   corners.

   Transform-only. Each disc is its own small layer (190px at most, ~1 MB at a
   phone's 3x density) that the compositor moves every frame; nothing repaints.
   A rotating conic gradient would look similar and cost far more: to reach the
   corners it has to be a square the size of the screen's diagonal, ~30 MB at
   3x, redrawn or re-composited every frame.

   THE PATH is keyframed corner to corner. With linear timing a disc's speed is
   (edge length ÷ that edge's share of the cycle), so the corner times are set
   to each edge's share of the perimeter: a portrait phone's top and bottom are
   390 of a 2468px perimeter, 15.8% each. Landscape gets its own set below.
   Every stop is written twice — vw/vh, then cqw/cqh — so a browser without
   container units keeps the first and still has an orbit.

   TRAILS lag the head by 0.12s each. A trailing disc is the same animation
   started LATER, i.e. a larger delay. Every delay is negative so all six discs
   are already mid-orbit on the first frame, with no dark beat while the mic
   opens. Comet B is comet A shifted by half the 4s cycle. */
.cc-listen-comet {
  position: absolute;
  left: 0;
  top: 0;
  width: 190px;
  height: 190px;
  margin: -95px 0 0 -95px;
  border-radius: 50%;
  background: radial-gradient(circle closest-side,
    var(--cc-listen-pool, rgba(var(--cc-gold-rgb, 198, 160, 74), 0.8)) 0%,
    var(--cc-listen-pool-soft, rgba(var(--cc-gold-rgb, 198, 160, 74), 0.34)) 48%,
    transparent 100%);
  will-change: transform;
  animation: cc-listen-orbit 4s linear infinite;
}

.cc-listen-comet[data-part="trail-1"] {
  width: 150px;
  height: 150px;
  margin: -75px 0 0 -75px;
  opacity: 0.62;
}

.cc-listen-comet[data-part="trail-2"] {
  width: 116px;
  height: 116px;
  margin: -58px 0 0 -58px;
  opacity: 0.36;
}

.cc-listen-comet[data-comet="a"][data-part="head"]    { animation-delay: -0.24s; }
.cc-listen-comet[data-comet="a"][data-part="trail-1"] { animation-delay: -0.12s; }
.cc-listen-comet[data-comet="a"][data-part="trail-2"] { animation-delay: 0s; }
.cc-listen-comet[data-comet="b"][data-part="head"]    { animation-delay: -2.24s; }
.cc-listen-comet[data-comet="b"][data-part="trail-1"] { animation-delay: -2.12s; }
.cc-listen-comet[data-comet="b"][data-part="trail-2"] { animation-delay: -2s; }

@keyframes cc-listen-orbit {
  0%, 100% { transform: translate(0, 0); }
  15.8%    { transform: translate(100vw, 0);     transform: translate(100cqw, 0); }
  50%      { transform: translate(100vw, 100vh); transform: translate(100cqw, 100cqh); }
  65.8%    { transform: translate(0, 100vh);     transform: translate(0, 100cqh); }
}

/* Landscape — a laptop, or a phone turned sideways — flips the proportions:
   top and bottom are now the long edges, ~32% of the perimeter each. */
@media (orientation: landscape) {
  @keyframes cc-listen-orbit {
    0%, 100% { transform: translate(0, 0); }
    32%      { transform: translate(100vw, 0);     transform: translate(100cqw, 0); }
    50%      { transform: translate(100vw, 100vh); transform: translate(100cqw, 100cqh); }
    82%      { transform: translate(0, 100vh);     transform: translate(0, 100cqh); }
  }
}

/* Take the client's OWN accent where the browser can mix it, and fall back to
   the literal gold above where it cannot. Guarded by @supports rather than set
   from JS on purpose: an unsupported color-mix assigned to a custom property
   is invalid at computed-value time, which would take the whole box-shadow
   down with it and leave a hands-free member with no listening indicator at
   all. Inside @supports, an unsupported browser simply never sees the rule. */
@supports (color: color-mix(in srgb, red 50%, transparent)) {
  .cc-listen-glow {
    --cc-listen-glow:       color-mix(in srgb, var(--cc-gold-bold) 90%, transparent);
    --cc-listen-glow-soft:  color-mix(in srgb, var(--cc-gold-bold) 46%, transparent);
    --cc-listen-glow-faint: color-mix(in srgb, var(--cc-gold-bold) 20%, transparent);
    /* The comets use the LIGHTER accent, --cc-accent-hi, so they read as light;
       the frame's darker accent against a bright page reads as shadow. */
    --cc-listen-pool:       color-mix(in srgb, var(--cc-accent-hi, var(--cc-gold-bold)) 82%, transparent);
    --cc-listen-pool-soft:  color-mix(in srgb, var(--cc-accent-hi, var(--cc-gold-bold)) 34%, transparent);
  }
}

/* A device that is SPEAKING is not a device that is listening, and the two
   must not look the same — otherwise you talk over it. Speaking holds a
   steady, dimmer frame, and the travelling light stops: movement means "go
   ahead", stillness means "wait". THINKING is a wait too, so it gets the same
   still frame — anything that is not listening. */
.cc-listen-glow:not([data-mode="listening"])::before {
  animation: none;
  opacity: 0.6;
}

.cc-listen-glow:not([data-mode="listening"]) .cc-listen-comet {
  display: none;
}

/* Reduced motion keeps the frame — it is the STATE indicator, and removing it
   would leave a hands-free member with no way to tell the microphone is open.
   The orbit goes entirely: a light that sits still in one corner would read as
   a rendering fault, not as "listening". The frame holds, bright and still. */
@media (prefers-reduced-motion: reduce) {
  .cc-listen-glow::before {
    animation: none;
    opacity: 0.95;
  }

  .cc-listen-comet {
    display: none;
  }
}

/* ── THE VOICE PILL'S MOTION ─────────────────────────────────────────────
   VoiceStatus.jsx carries its own layout inline; only what inline styles
   cannot do lives here. Transform and opacity only, so nothing repaints.

   The listening bars are the one moving thing in the pill, and they move for
   the same reason the glow does: at arm's length, motion reads as "live"
   before any word does. Five bars on staggered, unequal cycles so they never
   line up into a visible loop. */
.cc-voice-bars {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 20px;
}

.cc-voice-bars > span {
  display: block;
  width: 3.5px;
  height: 20px;
  border-radius: 2px;
  background: currentColor;
  transform-origin: 50% 50%;
  animation: cc-voice-bar 1.1s ease-in-out infinite;
}

.cc-voice-bars > span:nth-child(1) { animation-duration: 0.9s;  animation-delay: -0.2s; }
.cc-voice-bars > span:nth-child(2) { animation-duration: 1.2s;  animation-delay: -0.6s; }
.cc-voice-bars > span:nth-child(3) { animation-duration: 1s;    animation-delay: -0.1s; }
.cc-voice-bars > span:nth-child(4) { animation-duration: 1.3s;  animation-delay: -0.9s; }
.cc-voice-bars > span:nth-child(5) { animation-duration: 0.95s; animation-delay: -0.45s; }

@keyframes cc-voice-bar {
  0%, 100% { transform: scaleY(0.3); }
  50%      { transform: scaleY(1); }
}

/* The LISTENING pill's halo (round two: "show the listening more obviously").
   A ring of the accent that swells out of the pill and fades, like a pulse
   radiating from a live microphone. It is a box-shadow spread, not a scaled
   ring: scaling a 160x48 pill by one factor would swell it ~20px sideways and
   only ~6px up and down, and a lopsided ring reads as a glitch. The shadow
   repaints, but on a 48px pill that is nothing. */
.cc-voice-pill[data-state="listening"]::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  animation: cc-voice-halo 1.7s ease-out infinite;
}

@keyframes cc-voice-halo {
  0%   { box-shadow: 0 0 0 0 rgba(var(--cc-gold-rgb, 198, 160, 74), 0.5); }
  100% { box-shadow: 0 0 0 14px rgba(var(--cc-gold-rgb, 198, 160, 74), 0); }
}

/* Thinking: three dots taking turns. */
.cc-voice-dots {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.cc-voice-dots > span {
  display: block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  animation: cc-voice-dot 1.2s ease-in-out infinite;
}

.cc-voice-dots > span:nth-child(2) { animation-delay: 0.2s; }
.cc-voice-dots > span:nth-child(3) { animation-delay: 0.4s; }

@keyframes cc-voice-dot {
  0%, 60%, 100% { opacity: 0.3; }
  30%           { opacity: 1; }
}

/* Reduced motion: the bars hold a still, uneven skyline and the dots sit at
   full strength. The pill's WORDS still say the state; only the motion goes. */
@media (prefers-reduced-motion: reduce) {
  .cc-voice-bars > span,
  .cc-voice-dots > span,
  .cc-voice-pill[data-state="listening"]::after {
    animation: none;
  }

  .cc-voice-bars > span:nth-child(odd)  { transform: scaleY(0.55); }
  .cc-voice-bars > span:nth-child(even) { transform: scaleY(0.9); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE 2026-09-16 PHONE ROUND.

   Five changes, all on the phone, all asked for on the same day. The first two
   are one bug wearing two faces and are the reason the 2026-09-10 attempt
   (d04b9de, reverted in 1b14d5a) missed: that pass put its rules on html/body,
   and ON A PHONE THE DOCUMENT IS NOT WHAT SCROLLS. The shell pins a fixed
   100dvh frame and scrolls a column inside it, so html/body never overflow and
   a measurement of document.scrollWidth reads a clean 390 while the thing the
   member is actually dragging slides underneath it.

   Measured on production 2026-09-16 at 390x844, signed in, BEFORE this change:

     html            scrollW=390  clientW=390   <- clean, and useless
     mobile-overview-view  scrollW=394  clientW=390  overflow-x:auto   <- HERE
     div.at-actions  left=-4  right=394  width=398

   .at-actions is the hero's action ribbon. It is DELIBERATELY full-bleed
   (atelier.css: `margin: 0 calc(-1 * clamp(14px,3vw,44px))`) so the pills run
   to the screen edges, and it is deliberately its own horizontal scroller. What
   was never intended is that its 4px right-hand bleed makes its PARENT
   scrollable too — so the whole home screen could be dragged 4px sideways.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. NO SIDEWAYS SLIDE, AND THE DRAWER SWIPE WORKS AGAIN ──────────────────
   The 4px cost more than a wobble: it was also eating the swipe-right gesture
   that opens the menu. Header.jsx's `insideHorizontalScroller` walks up from
   wherever a touch lands and bails out of the drawer gesture if ANY ancestor
   has `scrollWidth > clientWidth + 1` and an auto/scroll overflow-x — because
   normally that means the member is scrolling a chip rail, not asking for the
   menu. mobile-overview-view matched on both counts and it covers the entire
   home content area, so on the home screen every swipe was being read as a
   ribbon scroll and the drawer never opened. Verified on production by running
   that helper's own logic against the element under a touch at (20,300): it
   returned true, blocked by mobile-overview-view.

   Clipping the parent fixes the slide and the swipe in one move, and leaves
   .at-actions' own scroller untouched — a swipe that starts ON the pill ribbon
   still scrolls the ribbon, which is correct. */
@media (max-width: 700px) {
  [data-testid="shell-main"] {
    /* Inline MAIN_STYLE sets `overflow: auto` — the shorthand, i.e. BOTH axes —
       so this needs !important to reach it. Vertical is untouched: the y axis
       keeps its auto and main stays the scroll column. */
    overflow-x: hidden !important;
  }
}

/* ── 2. THE "POWERED BY" FOOTER STOPS BEING PARKED ON SCREEN ─────────────────
   Asked for as "it should not be locked and always visible on the home screen,
   it should just be at the very bottom", and it is the same architecture again.

   The footer is NOT fixed or sticky — reading the DOM alone says it is in
   normal flow and innocent. What makes it permanent is the SIBLING ABOVE IT:
   mobile-overview-view is a fixed-height scrollport (measured top=72 bottom=717,
   height 645, with 1623px of content scrolling INSIDE it), so the home page's
   content never pushes anything downwards. main is 716px tall and holds
   645 + footer, which fits — so main itself never scrolls and the footer just
   sits there at top=730, on screen, permanently, at every scroll position.

   The fix is to stop the home column being its own scrollport and let main be
   the single scroll column it already declares itself to be. Then the content
   is 1623px inside a 716px window, the member scrolls, and the footer arrives
   at the end of the page the way a footer should.

   The tab bar is NOT inside main (measured: main ends at 788, the bar occupies
   788-844), so the footer cannot end up hidden behind it and needs no spacer.

   Why `overflow: visible` and not `clip` on the column: with the column's
   height released, nothing needs clipping here any more — the 4px is caught one
   level up by rule 1. It also matters that this element not remain a scroll
   container of any kind, because CSS coerces a lone `visible` back to `auto`
   the moment the other axis scrolls, which would silently rebuild the very
   scrollport this rule exists to remove.

   IT TAKES BOTH RULES BELOW, and the second is the one that is easy to miss.
   Releasing the overview alone moved nothing: the footer stayed parked at
   top=728. Between the overview and main sits an unnamed PAGE WRAPPER that is
   itself a fixed 714px, so the freed column simply overflowed IT instead and
   the footer went on being laid out against that wrapper's bottom edge. The
   lock was two deep. With the wrapper released as well the footer measures
   top=1695 at rest — off screen, where it belongs — and lands at the bottom of
   the page when the member scrolls there.

   `min-height: 100%` on the wrapper keeps a SHORT page honest: without it a
   page with little content would leave the footer floating in the middle of the
   screen instead of sitting at the bottom of it. */
@media (max-width: 700px) {
  [data-testid="shell-main"] > div {
    height: auto !important;
    min-height: 100% !important;
  }

  [data-testid="mobile-overview-view"] {
    flex: none !important;
    height: auto !important;
    min-height: 0 !important;
    overflow: visible !important;
  }
}

/* ── 3. THE CLIENT'S NAME, BIGGER ────────────────────────────────────────────
   "make the title of the header on the main page where it says Frank Benton to
   be larger text". 11px -> 15px on the phone bar.

   The name is the whole point of a white-labelled product and it was the
   smallest type in the masthead. 15px clears the 15px floor RMB-TASK-576 sets
   for this Command Center, and it still fits: the word measured 119px at 11px,
   so ~162px at 15px, inside the ~310px the bar leaves once the 44px hamburger
   and the 36px right-hand slot are taken out.

   Scoped under .at-mbar so it is unambiguously the PHONE bar, and specific
   enough (0,2,0) that it wins regardless of which stylesheet the bundle emits
   last. The desktop wordmark keeps its own 16px. */
@media (max-width: 700px) {
  .at-mbar .at-mbar-word {
    font-size: 15px !important;
  }
}

/* ── 4. NO CIRCLE ROUND THE HAMBURGER ────────────────────────────────────────
   "remove the circle around the hamburger menu button".

   Scoped to the phone toggle by its test id, NOT to .at-iconbtn, which is also
   worn by two DESKTOP header buttons (AtelierHeader.jsx:173 and :214) that were
   not part of this request and keep their circles.

   The 44x44 box stays exactly as it is — only the ring and the fill go. That
   size is the touch target the app-wide 44px floor in tokens.css guarantees,
   and shrinking a control to match the ink it happens to draw would be a
   usability regression on the one screen this round is trying to make easier. */
@media (max-width: 700px) {
  [data-testid="mobile-nav-toggle"].at-iconbtn {
    border: none !important;
    background: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
  }
}

/* ── 5. NO OPERATOR MARK IN THE TOP-RIGHT CORNER ─────────────────────────────
   "remove the BB logo on the top right of the page".

   The mark is hidden; its 36px SLOT is deliberately kept. That slot exists to
   mirror the 44px hamburger so the name in the middle stays optically centred,
   and collapsing it would drag the client's name off-centre — fixing one thing
   by breaking another. This is not a workaround: it is exactly what the shell
   itself renders for a Command Center with no operator mark configured, an
   invisible 36px spacer (AtelierMobileHeader.jsx:121).

   The mark on the Dossier page and the one in the footer are untouched — this
   is the corner of the masthead only.

   !important because the wrapper carries `display: inline-flex` inline
   (AtelierMobileHeader.jsx:110), which outranks a plain author rule. */
@media (max-width: 700px) {
  [data-testid="header-operator-mark"] > * {
    display: none !important;
  }
}
/* The report sheet, in the template Frank chose.
 *
 * PORTED FROM THE MASTER, NOT REDESIGNED. Every size, colour and rule below is
 * the stylesheet of Sample Reports/_build/build-master.mjs — the HTML that was
 * printed to "MASTER - Bronco Pursuits Report.pdf" — carried across under a
 * `.mr` scope. Maxim, 2026-09-17: reports "must look identical aside from the
 * fact that the contents of the reports will all be different." So a change
 * here is a change to the template and belongs in all three renderers
 * (this sheet, report-master-docx.js, report-master-pdf.js), never here alone.
 *
 * ── THREE THINGS THAT ARE NOT LITERAL COPIES, AND WHY ──────────────────
 *
 * 1. NO <table>, NO <h1>. The Atelier skin restyles every `main table th/td`
 *    and `main h1` with !important (atelier.css, the interior idiom layer),
 *    and this sheet renders inside <main>. A table here would silently take
 *    the Command Center's data-table padding and caps and stop looking like the
 *    paper. So rows are CSS grid with ARIA table roles, and the title is a div
 *    with role="heading".
 *
 * 2. THE SHEET NEVER THEMES. It is a piece of paper: white, dark ink, the
 *    template's own colours, in dark mode too — the same as the old report
 *    canvas and the same as the PDF on a dark desktop.
 *
 * 3. PHONE WIDTH. The master is an A4 page. Under 700px the page padding
 *    tightens, the two bar charts stack, the scoreline wraps to three across,
 *    and the wide tables scroll sideways inside their own box — never the page,
 *    because a document that pushes the whole Command Center sideways is the
 *    exact phone bug fixed on 2026-09-16.
 */

.mr-ground {
  background: #eceae5;
  padding: 18px 0;
  border-radius: 2px;
}

.mr {
  --mr-serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --mr-sans: "Segoe UI", Helvetica, Arial, sans-serif;
  box-sizing: border-box;
  max-width: 8.27in;
  margin: 0 auto;
  background: #fff;
  color: #1a1a18;
  font-family: var(--mr-serif);
  font-size: 10.6pt;
  line-height: 1.5;
  padding: 0.7in 0.72in 0.8in;
  text-align: left;
  color-scheme: light;
}
.mr *, .mr *::before, .mr *::after { box-sizing: border-box; }
/* Zero specificity, like the master's bare `h1,h2,p{margin:0}`: a class-level
   reset here would out-rank every margin below and collapse the page. */
:where(.mr) :where(p, div) { margin: 0; }

/* ── editable text ──────────────────────────────────────────────────── */
.mr-t[data-editable="true"] { cursor: text; border-radius: 2px; }
.mr-t[data-editable="true"]:hover { background: rgba(176, 122, 36, 0.07); }
.mr-edit {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  outline: none;
  resize: none;
  overflow: hidden;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  line-height: inherit;
  background: rgba(176, 122, 36, 0.09) !important;
  box-shadow: inset 0 0 0 1px rgba(176, 122, 36, 0.35);
  border-radius: 2px;
}
.mr-empty { color: #b9b3a6; font-style: italic; }

/* ── masthead ───────────────────────────────────────────────────────── */
.mr-mast { text-align: center; margin-bottom: 20px; }
.mr-rule { height: 2px; background: #1a1a18; }
.mr-client {
  font-size: 8pt; letter-spacing: .22em; text-transform: uppercase; color: #7c7669;
  margin: 13px 0 4px; font-family: var(--mr-sans); font-weight: 600;
}
.mr-title { font-size: 26pt; letter-spacing: -.01em; margin-bottom: 4px; font-weight: 700; }
.mr-period { font-style: italic; color: #5d574c; font-size: 10.5pt; margin-bottom: 10px; }
.mr-by { border-top: 1px solid #d8d3c8; padding: 8px 0 10px; font-family: var(--mr-sans); }
.mr-by-label { font-size: 7.6pt; letter-spacing: .19em; text-transform: uppercase; color: #8b8578; }
.mr-by-name { font-size: 9.6pt; letter-spacing: .05em; font-weight: 700; }

/* ── contents ───────────────────────────────────────────────────────── */
.mr-toc { background: #f6f4ef; border: 1px solid #ddd8cd; padding: 12px 16px; margin-bottom: 22px; }
.mr-toch, .mr-h4 {
  font-family: var(--mr-sans); font-size: 8pt; letter-spacing: .19em; text-transform: uppercase;
  color: #8b8578; font-weight: 700; margin-bottom: 7px;
}
.mr-toc ol {
  margin: 0; padding: 0; list-style: none; columns: 2; column-gap: 26px;
  font-family: var(--mr-sans); font-size: 9.4pt;
}
.mr-toc li { margin-bottom: 3px; break-inside: avoid; }
.mr-toc a { text-decoration: none; color: #2b2822; cursor: pointer; }
.mr-toc a:hover { text-decoration: underline; }
.mr-tn { display: inline-block; width: 1.5em; color: #a09a8c; font-weight: 700; }
.mr-key {
  margin-top: 10px; padding-top: 9px; border-top: 1px solid #e4dfd4; font-size: 8.4pt; color: #5d574c;
  font-family: var(--mr-sans);
}
.mr-key-item { white-space: nowrap; margin-right: 10px; }
.mr-sw { display: inline-block; width: 9px; height: 9px; margin-right: 5px; vertical-align: -1px; border-radius: 1px; }

/* ── section heads ──────────────────────────────────────────────────── */
.mr-h2 {
  font-size: 13pt; margin: 26px 0 9px; padding-bottom: 5px; border-bottom: 2px solid #1a1a18;
  font-family: var(--mr-sans); letter-spacing: .02em; font-weight: 700;
  scroll-margin-top: 90px;
}
.mr-sn {
  display: inline-block; background: #1a1a18; color: #fff; font-size: 8pt; padding: 2px 6px; margin-right: 9px;
  vertical-align: 2px; border-radius: 2px;
}
.mr-h3 {
  font-size: 11pt; font-weight: 600; margin: 18px 0 6px; padding-bottom: 3px; border-bottom: 1px solid #ddd8cd;
}
.mr-h4 { margin-top: 14px; }
.mr-lead, .mr-stands { font-size: 9.8pt; color: #3d382f; margin-bottom: 8px; }
.mr-stands { background: #f6f4ef; border: 1px solid #e4dfd4; padding: 8px 10px; }

/* ── the scoreline ──────────────────────────────────────────────────── */
.mr-score { display: grid; grid-template-columns: repeat(var(--mr-cols, 6), 1fr); margin-bottom: 6px; }
.mr-score > div {
  text-align: center; border: 1px solid #ddd8cd; padding: 8px 4px; margin: 0 -1px -1px 0;
}
.mr-score b { display: block; font-size: 19pt; line-height: 1; }
.mr-score span {
  display: block; margin-top: 4px;
  font-size: 7.4pt; letter-spacing: .1em; text-transform: uppercase; color: #8b8578;
  font-family: var(--mr-sans); font-weight: 700;
}

/* ── grids that stand in for tables ─────────────────────────────────── */
.mr-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: 6px; }
.mr-grid { display: grid; }
.mr-grid > [role="row"] { display: contents; }
/* break-word, not anywhere: `anywhere` also shrinks a column's min-content
   width, which is what split "Outstanding" into "Outstandin g". The columns
   are minmax(min-content, …) instead, the way the master's auto-layout table
   widened a column to fit its longest word. */
.mr-cell { padding: 5px 8px; border-bottom: 1px solid #eeebe4; min-width: 0; overflow-wrap: break-word; }

.mr-moved { font-size: 9.6pt; grid-template-columns: 30% 1fr; margin-bottom: 6px; }
.mr-moved .mr-mp { font-weight: 600; padding-left: 8px; }

.mr-dec { border-left: 3px solid #9e2b25; padding: 5px 0 5px 10px; margin-bottom: 8px; font-size: 9.8pt; }
.mr-dt { font-weight: 600; }

.mr-cal { font-size: 9.5pt; grid-template-columns: 13% 1fr; margin-bottom: 6px; }
.mr-cal .mr-cd { font-weight: 700; font-family: var(--mr-sans); font-size: 8.6pt; white-space: nowrap; }

.mr-rows { font-size: 9.2pt; }
.mr-rows.mr-tracker { font-size: 8.8pt; }
.mr-rows .mr-th {
  font-size: 7.6pt; letter-spacing: .12em; text-transform: uppercase; color: #8b8578;
  border-bottom: 1.5px solid #1a1a18; padding: 0 7px 4px; font-family: var(--mr-sans); font-weight: 700;
  align-self: end; overflow-wrap: normal;
}
.mr-rows .mr-cell:not(.mr-th) { padding: 6px 7px; }
.mr-rows .mr-nm { font-weight: 600; padding-left: 8px !important; }
.mr-rows .mr-wh { color: #6f695d; }
.mr-rows .mr-nx { white-space: nowrap; font-family: var(--mr-sans); font-size: 8.4pt; overflow-wrap: normal; }

/* ── bars ───────────────────────────────────────────────────────────── */
.mr-cols2 { display: flex; gap: 26px; }
.mr-cols2 > div { flex: 1; min-width: 0; }
.mr-bars { display: grid; grid-template-columns: 44% 46% 10%; font-size: 8.6pt; font-family: var(--mr-sans); }
.mr-bars .mr-bl, .mr-bars .mr-bt, .mr-bars .mr-bn { padding: 1.5px 0; min-width: 0; }
.mr-bars .mr-bl { text-align: right; padding-right: 8px; color: #4a453c; }
.mr-bars .mr-bt { align-self: center; }
.mr-bars .mr-bf { display: block; height: 11px; }
.mr-bars .mr-bn { text-align: right; color: #6f695d; padding-left: 6px; }

.mr-ckey { font-size: 9.4pt; grid-template-columns: 1.4em 1fr auto 4em; margin-bottom: 6px; }
.mr-ckey > [role="row"] > div { padding: 3px 6px; border-bottom: 1px solid #f0ede6; }
.mr-ckey .mr-nx { font-family: var(--mr-sans); font-size: 8.4pt; white-space: nowrap; }

.mr-cap { font-size: 8.2pt; color: #8b8578; margin: 2px 0 14px; font-family: var(--mr-sans); }

/* ── pursuits ───────────────────────────────────────────────────────── */
.mr-pursuit { border-left: 4px solid #ddd; padding: 2px 0 2px 12px; margin: 14px 0 0; }
.mr-pursuit-name { font-size: 11.4pt; margin: 0 0 2px; font-weight: 700; }
.mr-meta { font-size: 8.4pt; color: #6f695d; margin-bottom: 5px; font-family: var(--mr-sans); }
.mr-meta-sep { padding: 0 6px; }
.mr-status { font-weight: 600; font-size: 10pt; margin-bottom: 6px; }
.mr-facts { display: grid; grid-template-columns: 14% 1fr; margin-bottom: 7px; font-size: 9.4pt; }
.mr-facts .mr-fk {
  font-family: var(--mr-sans); font-size: 7.6pt; letter-spacing: .11em; text-transform: uppercase; color: #8b8578;
  padding: 2px 8px 2px 0; font-weight: 700;
}
.mr-facts .mr-fv { padding: 2px 0; min-width: 0; overflow-wrap: break-word; }
.mr-alert { background: #fdf2f2; border-left: 3px solid #9e2b25; padding: 6px 9px; margin: 6px 0; font-size: 9.6pt; }
.mr-ph {
  font-family: var(--mr-sans); font-size: 7.8pt; letter-spacing: .12em; text-transform: uppercase; color: #8b8578;
  font-weight: 700; margin: 7px 0 1px;
}
.mr-pb { font-size: 9.8pt; white-space: pre-line; }
/* The master's `.pursuit p{font-size:9.8pt}` out-ranks its own .ph, .alert and
   .contacts rules, so inside a card those print at 9.8pt, not their stated
   sizes. That IS the look he picked, so it is reproduced rather than "fixed". */
.mr-pursuit .mr-ph, .mr-pursuit .mr-alert, .mr-pursuit .mr-contacts { font-size: 9.8pt; }
.mr-contacts { font-size: 9pt; color: #4a453c; }
.mr-para { font-size: 10pt; margin-bottom: 6px; white-space: pre-line; }
.mr-para.mr-bullet { padding-left: 14px; text-indent: -10px; }

@media (max-width: 700px) {
  .mr { padding: 26px 18px 30px; font-size: 10.2pt; }
  .mr-ground { padding: 0; background: transparent; }
  .mr-title { font-size: 22pt; }
  .mr-toc ol { columns: 1; }
  .mr-score { grid-template-columns: repeat(3, 1fr); }
  .mr-cols2 { flex-direction: column; gap: 6px; }
  .mr-moved { grid-template-columns: 38% 1fr; }
  .mr-cal { grid-template-columns: 22% 1fr; }
  .mr-facts { grid-template-columns: 26% 1fr; }
  .mr-rows { min-width: 560px; }
  .mr-rows.mr-tracker { min-width: 640px; }
}
/* Command Center — interaction layer.
 *
 * DESIGN SAMPLE 3 — "The Study" (executive briefing-room dark theme).
 * Hover/motion retuned to the dark charcoal + brass palette; structure and
 * class names unchanged.
 *
 * Scoped TIGHTLY to what inline styles cannot express: :hover states,
 * transitions, and @keyframes. Imported once from src/main.jsx.
 */

/* --------------------------------------------------------------------------
 * Keyframes — live status dots
 * ------------------------------------------------------------------------ */
@keyframes cc-pulse-dot {
  0%, 100% { box-shadow: 0 0 0 3px rgba(95, 158, 125, 0.22); }
  50%      { box-shadow: 0 0 0 5px rgba(95, 158, 125, 0.1); }
}

.cc-live-dot {
  animation: cc-pulse-dot 2s ease-in-out infinite;
}
.cc-live-pulse {
  animation: cc-pulse-dot 1.8s ease-in-out infinite;
}

/* --------------------------------------------------------------------------
 * Masthead nav links + roster medallions
 * ------------------------------------------------------------------------ */
.cc-masthead-link {
  transition: color 0.15s, border-color 0.15s;
}
.cc-masthead-link:hover {
  color: var(--cc-accent-hi);
}

.cc-medallion {
  transition: transform 0.18s, filter 0.18s;
}
.cc-medallion:hover {
  transform: translateY(-3px);
  filter: drop-shadow(0 6px 14px rgba(var(--cc-accent-tint-rgb), 0.25));
}
.cc-medallion:hover span:first-of-type {
  color: var(--cc-accent-hi);
}

/* --------------------------------------------------------------------------
 * Top bar buttons + member pill
 * ------------------------------------------------------------------------ */
.cc-top-btn,
.cc-member-pill {
  transition: background 0.15s, border-color 0.15s;
}
.cc-top-btn:hover,
.cc-member-pill:hover {
  border-color: var(--cc-accent-line);
  background: rgba(var(--cc-accent-tint-rgb), 0.14);
}

/* Sticky agent ribbon removed 2026-07-23 (it leaked across page
   navigations). Its classes (.cc-sticky-ribbon / .cc-ribbon-*) are
   intentionally gone; the roster grid is the sole agent-nav surface. */

/* --------------------------------------------------------------------------
 * Agents grid — tile hover lift + brass top-border scaleX reveal
 * ------------------------------------------------------------------------ */
.cc-agent-tile {
  transition: border-color 0.18s, transform 0.18s, box-shadow 0.18s, color 0.18s;
}
.cc-agent-tile::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--cc-accent-line);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.18s;
}
.cc-agent-item:hover .cc-agent-tile {
  border-color: var(--cc-accent-line-2);
  transform: translateY(-2px);
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.5);
  color: var(--cc-accent-hi);
}
.cc-agent-item:hover .cc-agent-tile::before {
  transform: scaleX(1);
}

/* --------------------------------------------------------------------------
 * Quick Actions — primary + secondary button hovers
 * ------------------------------------------------------------------------ */
.cc-qa-primary {
  transition: background 0.15s, border-color 0.15s;
}
.cc-qa-primary:hover {
  background: #33466a;
  border-color: var(--cc-accent-line);
}
.cc-qa-btn {
  transition: background 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
.cc-qa-btn:hover {
  background: #33466a;
  border-color: var(--cc-accent-line);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
}
.cc-qa-arrow {
  transition: transform 0.15s, color 0.15s;
}
.cc-qa-btn:hover .cc-qa-arrow {
  color: var(--cc-accent-hi);
  transform: translateX(2px);
}


/* --------------------------------------------------------------------------
 * Sign-offs — approve / reject buttons
 * ------------------------------------------------------------------------ */
.cc-signoff-btn {
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.cc-signoff-btn-approve:hover { background: #4c8467; }
.cc-signoff-btn-reject:hover  { border-color: #b0413e; color: #cd6a63; }

/* --------------------------------------------------------------------------
 * Needs Attention — item row hover
 * ------------------------------------------------------------------------ */
.cc-attn-item {
  transition: transform 0.15s, box-shadow 0.15s, border-color 0.15s;
}
.cc-attn-item:hover {
  transform: translateX(2px);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
  border-color: var(--cc-accent-line-2);
}

/* --------------------------------------------------------------------------
 * Live Activity — event row hover
 * ------------------------------------------------------------------------ */
.cc-activity-row {
  transition: background 0.12s;
}
.cc-activity-row:hover {
  background: rgba(var(--cc-accent-tint-rgb), 0.06);
}

/* Messages panel search — placeholder + clear button on the dark title bar. */
[data-testid="messages-search"]::placeholder {
  color: rgba(255, 255, 255, 0.5);
}
[data-testid="messages-search"]::-webkit-search-cancel-button {
  filter: invert(1);
  opacity: 0.5;
  cursor: pointer;
}

/* --------------------------------------------------------------------------
 * Week Calendar — day cell hover (today cell keeps its slate fill)
 * ------------------------------------------------------------------------ */
.cc-week-day {
  transition: border-color 0.15s, background 0.15s;
}
.cc-week-day:hover {
  border-color: var(--cc-accent-line);
}
/* Today's cell is a soft gold wash set inline per cell (2026-07-23), no longer
   a navy fill; this only carries its gold hover border. */
.cc-week-day.is-today:hover {
  border-color: var(--cc-gold, var(--cc-accent-line));
}

/* --------------------------------------------------------------------------
 * Generic agent-tile / cost-row / signoff-item — subtle shared hovers
 * ------------------------------------------------------------------------ */
.cc-hoverable {
  transition: background 0.15s, border-color 0.15s;
}

/* --------------------------------------------------------------------------
 * Masthead BB monogram — the asset is a black-on-transparent PNG, invisible on
 * the dark masthead. In dark mode recolor it to white (brightness(0) forces the
 * silhouette solid black preserving alpha, invert(1) flips black -> white).
 * Light mode leaves the original black lockup on the cream masthead untouched.
 *
 * ⚠ EXCLUDES THE CLIENT LOGO (1.13.0). This rule was written when the mark was
 * a PNG; the mark became TYPE in 1.2.0 and the selector has matched nothing
 * since. Adding the client-logo <img> in 1.13.0 silently reactivated it, and
 * the result was a brand mark recoloured to a white silhouette in dark mode —
 * every colour in the client's logo destroyed, and, combined with the white
 * plate behind it, white-on-white and completely invisible. Caught by a
 * screenshot; no test would have seen it, because the bug is a stylesheet
 * meeting a component that did not exist when it was written.
 *
 * A client's logo keeps its own colours. Legibility in dark mode is the
 * plate's job (BrandMark.jsx) or a supplied `branding.logo.dark`, and both
 * preserve the artwork instead of flattening it to a silhouette.
 * ------------------------------------------------------------------------ */
:root[data-theme="dark"] [data-testid="header-home-logo"] img:not([data-testid="brand-logo"]) {
  filter: brightness(0) invert(1);
}

/* --------------------------------------------------------------------------
 * Header focus rings — dark surfaces take a brass ring
 * ------------------------------------------------------------------------ */
[data-testid="header-home-logo"]:focus-visible,
[data-testid="header-home-title"]:focus-visible,
[data-testid="feedback-button"]:focus-visible,
[data-testid="header-notif-btn"]:focus-visible,
[data-testid="mobile-nav-toggle"]:focus-visible,
[data-testid="member-switcher"]:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: 2px;
}

/* --------------------------------------------------------------------------
 * Stat band — clickable figure cells (tickets → Feedback, tasks → Tasks,
 * spend → Costs). Subtle tint + focus ring; the repo cell is static.
 * ------------------------------------------------------------------------ */
.cc-stat-cell {
  transition: background 0.15s;
}
.cc-stat-cell:hover {
  background: rgba(var(--cc-gold-rgb), 0.07);
}
.cc-stat-cell:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: -2px;
}

/* --------------------------------------------------------------------------
 * Mobile masthead / drawer BB mark — same black-on-transparent PNG as the
 * desktop lockup, so recolor it to white in dark mode.
 *
 * ⚠ The filter sits on the WRAPPER, not the image, so it cannot be undone from
 * the inside — an ancestor filter has already rasterised by the time an inner
 * rule is considered. Header.jsx therefore stops applying `cc-mobile-mark`
 * when the mark is an image (see markIsType()), which is the only place the
 * distinction can be made. Same 1.13.0 reasoning as the desktop rule above.
 * ------------------------------------------------------------------------ */
:root[data-theme="dark"] .cc-mobile-mark {
  filter: brightness(0) invert(1);
}

/* --------------------------------------------------------------------------
 * Mobile nav drawer — scrim fade + panel slide-in
 * ------------------------------------------------------------------------ */
@keyframes cc-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes cc-drawer-in {
  from { transform: translateX(-100%); }
  to   { transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  [data-testid="mobile-nav-drawer"],
  [data-testid="mobile-nav-scrim"] {
    animation: none !important;
  }
}

/* --------------------------------------------------------------------------
 * Skip-link + surface focus rings
 * ------------------------------------------------------------------------ */
.cc-skip-link {
  position: absolute;
  top: -40px;
  left: 8px;
  padding: 8px 16px;
  background: var(--cc-navy, #2a3a58);
  color: #ece7dc;
  border-radius: 4px;
  z-index: 10000;
  text-decoration: none;
  font-family: var(--cc-font-sans, system-ui);
  font-size: 13px;
}
.cc-skip-link:focus,
.cc-skip-link:focus-visible {
  top: 8px;
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: 2px;
}

[data-testid^="goal-row-"]:focus-visible,
[data-testid^="feedback-row-"]:focus-visible,
[data-testid^="feedback-bucket-header-"]:focus-visible,
[role="menuitem"]:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: 2px;
}

/* Dashboard month calendar — day cells are only interactive when a bespoke
   `calendar` page exists to receive the click (CalendarPanel renders a <div>
   otherwise, which these rules never match). The hover is a tint rather than a
   border so the grid's rules stay unbroken as the cursor crosses it. */
.cc-cal-day {
  transition: background 0.12s;
}
.cc-cal-day:hover {
  background: rgba(var(--cc-accent-tint-rgb), 0.14);
}
.cc-cal-day:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: -2px;
}

/* --------------------------------------------------------------------------
 * Settings — the interaction layer for the /settings register.
 *
 * SettingsPage.jsx styles itself inline (the house convention), which cannot
 * express :focus-visible, a hover gated on pointer type, or reduced motion.
 * Those three live here and nowhere else. Every colour is a --cc-* token, so
 * this block reskins with each client's generated palette like the rest.
 * ------------------------------------------------------------------------ */

/* Hover is an enhancement, never a carrier of information — and a :hover style
   that survives on a touch device sticks after a tap. Gate it on a real mouse. */
@media (hover: hover) and (pointer: fine) {
  .cc-set-btn:hover:not(:disabled) {
    background: rgba(var(--cc-gold-rgb), 0.08);
  }
  .cc-set-rail-link:hover {
    color: var(--cc-ink);
    border-left-color: var(--cc-gold);
  }
  .cc-set-switch:hover:not(:disabled) > span {
    filter: brightness(0.96);
  }
}

/* Every control on the page takes the same ring. outline-offset keeps it clear
   of the switch track and the sheet's own border rather than sitting on top of
   either. */
.cc-set-btn:focus-visible,
.cc-set-switch:focus-visible,
.cc-set-input:focus-visible,
.cc-set-rail-link:focus-visible,
[data-testid^="settings-brand-"]:focus-visible {
  outline: 2px solid var(--cc-gold-bold, var(--cc-accent-line));
  outline-offset: 2px;
}

/* A focused text field also reads as focused without the ring — the border is
   what someone tracks while typing. */
.cc-set-input:focus {
  border-color: var(--cc-gold);
}

.cc-set-btn,
.cc-set-rail-link {
  transition: background 150ms cubic-bezier(0.2, 0, 0, 1),
              color 150ms cubic-bezier(0.2, 0, 0, 1),
              border-color 150ms cubic-bezier(0.2, 0, 0, 1);
}

/* Reduced motion means less movement, not less information: the switch still
   changes fill and the knob is still in the other place — it just gets there
   without travelling, and the rail jump stops animating. */
@media (prefers-reduced-motion: reduce) {
  .cc-set-btn,
  .cc-set-rail-link,
  .cc-set-switch > span,
  .cc-set-switch > span > span {
    transition-duration: 1ms !important;
  }
  [data-testid="settings-page"] {
    scroll-behavior: auto !important;
  }
}
/*$vite$:1*/