/* ═══════════════════════════════════════════════════════════════════════════
   csa-shell.css — rev_1186
   THE VISUAL CHANGE. Applies the approved material shell across the apps.

   WHAT THIS IS
   ────────────
   The approved mock (cassandra-material-design-audit.html) defines one page
   shape for every app:

       topbar  →  subhead (title + subtitle + actions)  →  tabs  →  card grid

   rev_1159 defined the primitives for that (.csa-tabs/.csa-tab with an accent
   underline, .csa-card, .csa-sec, .csa-pill) and rev_1161 adopted them in People
   as the reference app. But NO OTHER APP adopted them — which is exactly why
   Vincent said "so far I doid not see much redesign except the header". The
   tokens changed; the appearance largely did not.

   Rewriting sixteen apps' markup to use .csa-tab is weeks of risk. This file does
   the same job by MAPPING each app's existing tab/header/card classes onto the
   approved treatment. Same DOM, same behaviour, new appearance.

   WHAT CHANGES, DELIBERATELY
   ──────────────────────────
   Tabs stop being pills/boxes and become MATERIAL UNDERLINE tabs: muted label,
   accent label + 2px accent underline when active, count badge in a soft chip.
   That is the single most recognisable difference between old and new Cassandra,
   and it is layout-safe — nothing moves, the box just reads differently.

   Headers gain the subhead treatment: larger title, muted subtitle beside it, a
   hairline beneath, consistent breathing room.

   Cards gain one radius, one border, one hover elevation.

   THE RULE I AM HOLDING TO
   ────────────────────────
   Type, colour, weight, radius, border, shadow and the active-state treatment are
   fair game — that is the redesign. Anything that moves or resizes a layout BOX
   (width, flex-basis, grid-template, position, overflow) is NOT, because that is
   how a restyle silently breaks a dense screen. Tab padding is the one exception
   and is kept close to the old values.

   Loaded AFTER each app's stylesheet and BEFORE csa-normalize.css, so app rules
   are overridden here while normalize keeps the last word on controls.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Tab rows ──────────────────────────────────────────────────────────────── */
/* One flex row, hairline underneath, wrapping rather than scrolling — a hidden
   horizontal scroll means tabs the user cannot see (the rev_1181 lesson). */
.ld-tabs, .mk-tabs, .pe-tabs, .usr-tabs, .ep-tabs{
  display:flex;
  flex-wrap:wrap;
  gap:2px;
  border-bottom:1px solid var(--csa-line);
  padding:0;
}

/* ── Tabs themselves ──────────────────────────────────────────────────────── */
.ld-tab, .mk-tab, .pe-tab, .usr-tab, .ep-tab,
.pr-topic{
  position:relative;
  background:transparent;
  border:0;
  border-bottom:2px solid transparent;
  border-radius:0;
  padding:9px 14px;
  font-family:inherit;
  font-size:var(--csa-f-md);
  font-weight:500;
  line-height:1.2;
  color:var(--csa-muted);
  cursor:pointer;
  white-space:nowrap;
  transition:color var(--csa-t-fast) var(--csa-ease),
             border-color var(--csa-t-fast) var(--csa-ease);
}
.ld-tab:hover, .mk-tab:hover, .pe-tab:hover, .usr-tab:hover, .ep-tab:hover,
.pr-topic:hover{
  color:var(--csa-text);
  background:transparent;              /* kill the old hover fill */
}

/* Active: accent label + accent underline. `.on` everywhere except equipment,
   which uses `.active` — both listed rather than normalised, because renaming a
   state class means touching JS in every app for no visual gain. */
.ld-tab.on, .mk-tab.on, .pe-tab.on, .usr-tab.on, .ep-tab.active,
.pr-topic.on{
  color:var(--csa-accent-text);
  border-bottom-color:var(--csa-accent);
  background:transparent;
  font-weight:600;
}

/* Sub-tabs stay pills: they are a second level, and making them underlines too
   would leave two identical rows with no hierarchy between them. */
.pr-subtab{
  border-radius:var(--csa-r-full);
  font-size:var(--csa-f-sm);
  color:var(--csa-muted);
  border:1px solid var(--csa-line);
  background:transparent;
  transition:color var(--csa-t-fast) var(--csa-ease),
             border-color var(--csa-t-fast) var(--csa-ease);
}
.pr-subtab:hover{ color:var(--csa-text); border-color:var(--csa-line-2); }
.pr-subtab.on{
  color:var(--csa-accent-text);
  border-color:var(--csa-accent);
  background:var(--csa-accent-soft);
}

/* ── Counts on tabs ───────────────────────────────────────────────────────── */
/* Soft chip, tabular figures so a count changing 9 -> 10 does not shift the tab. */
.ld-tab-badge, .pr-topic-hint, .csa-tab__count{
  display:inline-block;
  margin-left:6px;
  padding:1px 6px;
  border-radius:var(--csa-r-full);
  background:var(--csa-surface-2);
  color:var(--csa-muted);
  font-size:var(--csa-f-2xs);
  font-weight:600;
  font-variant-numeric:tabular-nums;
  vertical-align:baseline;
}
.ld-tab.on .ld-tab-badge,
.pr-topic.on .pr-topic-hint{
  background:var(--csa-accent-bg);
  color:var(--csa-accent-text);
}

/* ── Subheads ─────────────────────────────────────────────────────────────── */
/* The app's own title block. Padding/hairline only — the flex layout each app
   already has is left alone. */
.pr-head, .ib-head, .eq-subheader{
  border-bottom:1px solid var(--csa-line);
}
.pr-head-title, .ib-head-title-row h1, .ib-head-title-row h2{
  font-size:var(--csa-f-2xl);
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--csa-text);
}
/* Event name / client line reads as a subtitle, not a second title. */
.pr-head-event, .pr-head-clientline{
  font-size:var(--csa-f-sm);
  color:var(--csa-muted);
  font-weight:400;
}

/* Admin + Manager list heads: micro-label, which is what they actually are. */
.list-head{
  font-size:var(--csa-f-2xs);
  font-weight:700;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--csa-muted);
  border-bottom:1px solid var(--csa-line);
}

/* ── Cards ────────────────────────────────────────────────────────────────── */
/* One radius, one border, one hover lift. Backgrounds are NOT set here: several
   apps tint cards by state (overdue, unpaid, internal) and flattening those would
   destroy information. */
.ld-card, .mk-card, .eq-card, .res-card, .pr-card, .ib-card{
  border-radius:var(--csa-r-md);
  border:1px solid var(--csa-line);
  transition:border-color var(--csa-t-fast) var(--csa-ease),
             box-shadow var(--csa-t-fast) var(--csa-ease);
}
.ld-card:hover, .mk-card:hover, .eq-card:hover, .res-card:hover,
.pr-card:hover, .ib-card:hover{
  border-color:var(--csa-line-2);
  box-shadow:var(--csa-shadow-1);
}

/* ── Section headings ─────────────────────────────────────────────────────── */
/* Every app had its own idea of a section label. One micro-label treatment. */
.ld-sec-title, .mk-sec-title, .eq-sec-title, .pr-sec-title, .res-sec-title,
.bs-sec-hd{
  font-size:var(--csa-f-2xs);
  font-weight:700;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--csa-muted);
}

/* ── Reduced motion ───────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce){
  .ld-tab, .mk-tab, .pe-tab, .usr-tab, .ep-tab, .pr-topic, .pr-subtab,
  .ld-card, .mk-card, .eq-card, .res-card, .pr-card, .ib-card{
    transition:none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   rev_1188 — the three apps that had no mock until rev_1187.
   Built to the approved mock (cassandra-planner-equipment-scene-mocks.html),
   taking its defaults as the decision: Planner keeps both axes visible, Scene
   panels float, Equipment's Owned/Catalog stays a subhead toggle.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── PLANNER ───────────────────────────────────────────────────────────────
   Planner is TWO AXES, not a view list: scope (day/week/month/year/custom) x
   render (list/timeline/calendar) = 15 legal states, plus three group modes.
   Both axes stay visible — the mock's call — because collapsing one into a
   dropdown costs a click AND hides which state you are in.

   These are SEGMENTED controls, deliberately not the underline tabs used
   elsewhere: underline tabs mean "navigate to a different place", segments mean
   "same data, different shape". Using one treatment for both would flatten a
   real distinction. */
.pl-bar{
  border-bottom:1px solid var(--csa-line);
}
.pl-title{
  font-size:var(--csa-f-2xl);
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--csa-text);
}
.pl-views, .pl-scopes{
  border:1px solid var(--csa-line);
  border-radius:var(--csa-r-sm);
  overflow:hidden;
  background:transparent;
  padding:0;
  gap:0;
}
.pl-view, .pl-scopebtn{
  background:transparent;
  border:0;
  border-right:1px solid var(--csa-line);
  border-radius:0;
  color:var(--csa-muted);
  font-weight:500;
  transition:background var(--csa-t-fast) var(--csa-ease),
             color var(--csa-t-fast) var(--csa-ease);
}
.pl-view:last-child, .pl-scopebtn:last-child{ border-right:0; }
.pl-view:hover, .pl-scopebtn:hover{ color:var(--csa-text); background:var(--csa-hover); }
.pl-view.on, .pl-scopebtn.on{
  background:var(--csa-accent-soft);
  color:var(--csa-accent-text);
  font-weight:600;
}
/* Compare has its own tab strip inside its modal — that one IS navigation, so it
   gets the underline treatment to match the rest of Cassandra. */
.pl-cmp-tabs{
  display:flex; flex-wrap:wrap; gap:2px;
  border-bottom:1px solid var(--csa-line);
}
.pl-cmp-tab{
  background:transparent; border:0; border-bottom:2px solid transparent; border-radius:0;
  padding:9px 14px; font:500 var(--csa-f-md)/1.2 inherit; color:var(--csa-muted); cursor:pointer;
}
.pl-cmp-tab:hover{ color:var(--csa-text); }
.pl-cmp-tab.on{
  color:var(--csa-accent-text); border-bottom-color:var(--csa-accent); font-weight:600;
}
/* Lane and phase headers were six different label styles. One micro-label. */
.pl-lane-head, .pl-lane-nm, .pl-list-dayhead, .pl-aggrp-hd, .pl-ressec-head{
  font-size:var(--csa-f-2xs);
  font-weight:700;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--csa-muted);
}

/* ── EQUIPMENT ─────────────────────────────────────────────────────────────
   Owned / Catalog is one shell over two datasets, so it stays a toggle in the
   subhead rather than becoming tabs — tabs would imply two places. */
.eq-subheader{ border-bottom:1px solid var(--csa-line); }
/* Brand groupings in the rail are labels, not rows. */
.eq-list-brand-header{
  font-size:var(--csa-f-2xs);
  font-weight:700;
  letter-spacing:.09em;
  text-transform:uppercase;
  color:var(--csa-muted);
  background:var(--csa-surface-2);
  border-bottom:1px solid var(--csa-line);
}
.eq-list-item{
  border-bottom:1px solid var(--csa-line);
  border-left:2px solid transparent;
  transition:background var(--csa-t-fast) var(--csa-ease),
             border-color var(--csa-t-fast) var(--csa-ease);
}
.eq-list-item:hover{ background:var(--csa-hover); }
/* Selected reads as accent-on-the-edge, matching the list-row treatment
   csa-normalize already uses elsewhere, so selection means one thing app-wide. */
.eq-list-item.on, .eq-list-item.active, .eq-list-item.selected{
  background:var(--csa-accent-soft);
  border-left-color:var(--csa-accent);
}
.eq-list-name{ font-size:var(--csa-f-md); color:var(--csa-text); }
.eq-device-name{ font-size:var(--csa-f-md); font-weight:600; }
.eq-device-sub{ font-size:var(--csa-f-xs); color:var(--csa-hint); }

/* ── SCENE BUILDER ─────────────────────────────────────────────────────────
   Deliberately NO tabs. It is a canvas tool with a map, live collaborators, a
   floor-plan overlay and calibration — applying the tab pattern here would be
   pattern for its own sake. The chrome becomes floating accordion panels so the
   canvas keeps the screen, which is the mock's call.

   Note scene.html loads the legacy theme.css vocabulary; these rules land after
   it, so the panels pick up Cassandra surfaces without touching that file. */
.acc{
  background:var(--csa-surface-1);
  border:1px solid var(--csa-line);
  border-radius:var(--csa-r-md);
  box-shadow:var(--csa-shadow-2);
  overflow:hidden;
}
.acc-hd{
  border-bottom:1px solid var(--csa-line);
  background:transparent;
}
.acc-title{
  font-size:var(--csa-f-2xs);
  font-weight:700;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--csa-muted);
}
.acc-chevron{ color:var(--csa-hint); }
.acc.open > .acc-hd .acc-title{ color:var(--csa-text); }
/* Readouts are numbers you compare — tabular figures stop them jittering. */
.bstat-val, .bstat-label{ font-variant-numeric:tabular-nums; }
.bstat-label{ font-size:var(--csa-f-2xs); color:var(--csa-hint); letter-spacing:.06em; text-transform:uppercase; }

@media (prefers-reduced-motion: reduce){
  .pl-view, .pl-scopebtn, .eq-list-item{ transition:none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   rev_1189 — the pages the shell had not reached.
   Vincent: "so do the untouched pages to!"

   These are SCOPED with [data-page="…"] rather than styled by class name, and
   that is the whole point. The classes these pages use — .card, .btn, .field,
   .sub, .hint, .brand, .done — are shared with 5 to 26 other pages each,
   including apps already styled. Restyling .card bare would fire a shotgun
   across the product. A per-page hook on <body> keeps every rule below exactly
   as wide as intended.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── The auth family: login, forgot / reset / change password, set credential ──
   The first screen anyone sees, and until now the least considered. One card
   treatment across all of them so the entry to Cassandra matches the inside. */
[data-page="login"] .card,
[data-page="forgot-password"] .card,
[data-page="reset-password"] .card,
[data-page="change-password"] .card,
[data-page="set-credential"] .sc-card,
[data-page="pin-login"] .pl-card{
  background:var(--csa-surface-1);
  border:1px solid var(--csa-line);
  border-radius:var(--csa-r-lg);
  box-shadow:var(--csa-shadow-2);
}
[data-page="login"] .logo-text,
[data-page="forgot-password"] .logo-text,
[data-page="reset-password"] .logo-text,
[data-page="change-password"] .logo-text{
  font-size:var(--csa-f-xl);
  font-weight:650;
  letter-spacing:-.01em;
  color:var(--csa-text);
}
[data-page="login"] .sub, [data-page="forgot-password"] .hint,
[data-page="reset-password"] .hint, [data-page="change-password"] .sub,
[data-page="set-credential"] .sc-sub, [data-page="pin-login"] .pl-sub{
  color:var(--csa-muted); font-size:var(--csa-f-sm);
}
/* Errors read as danger, not as body text — on a login screen that matters. */
[data-page="login"] .err, [data-page="forgot-password"] .err,
[data-page="reset-password"] .err, [data-page="change-password"] .err,
[data-page="set-credential"] .sc-msg.err, [data-page="pin-login"] .pl-msg.err{
  color:var(--csa-danger-text); font-size:var(--csa-f-sm);
}
[data-page="login"] .forgot, [data-page="forgot-password"] .back,
[data-page="reset-password"] .back, [data-page="pin-login"] .pl-link{
  color:var(--csa-accent-text); text-decoration:none;
}
[data-page="login"] .forgot:hover, [data-page="forgot-password"] .back:hover,
[data-page="reset-password"] .back:hover, [data-page="pin-login"] .pl-link:hover{
  text-decoration:underline;
}
/* PIN keypad: tabular figures and one radius. A keypad with drifting digit
   widths feels cheap, and this is the screen crew use on site. */
[data-page="pin-login"] .pl-key{
  border-radius:var(--csa-r-md);
  border:1px solid var(--csa-line);
  background:var(--csa-surface-1);
  font-variant-numeric:tabular-nums;
  font-size:var(--csa-f-xl);
  color:var(--csa-text);
}
[data-page="pin-login"] .pl-key:hover{ border-color:var(--csa-accent); background:var(--csa-accent-soft); }
[data-page="pin-login"] .pl-dot{ border-color:var(--csa-line-2); }
[data-page="pin-login"] .pl-lbl{
  font-size:var(--csa-f-2xs); letter-spacing:.08em; text-transform:uppercase; color:var(--csa-muted);
}

/* ── Launcher: the front door ──────────────────────────────────────────────── */
[data-page="launcher"] .tile-name{
  font-size:var(--csa-f-md); font-weight:600; color:var(--csa-text); letter-spacing:-.005em;
}
[data-page="launcher"] .tile-desc{ font-size:var(--csa-f-xs); color:var(--csa-hint); }
[data-page="launcher"] .tile-tag{
  font-size:var(--csa-f-2xs); font-weight:700; letter-spacing:.07em; text-transform:uppercase;
  color:var(--csa-muted); background:var(--csa-surface-2);
  border-radius:var(--csa-r-full); padding:1px 7px;
}
[data-page="launcher"] .tile-tag-feature{
  background:var(--csa-accent-bg); color:var(--csa-accent-text);
}

/* ── Wiki ─────────────────────────────────────────────────────────────────── */
[data-page="wiki"] .wk-btn{
  border-radius:var(--csa-r-sm); border:1px solid var(--csa-line-2);
  background:transparent; color:var(--csa-text); font-weight:500;
}
[data-page="wiki"] .wk-btn:hover{ background:var(--csa-hover); }
[data-page="wiki"] .wk-btn.primary{
  background:var(--csa-accent); border-color:var(--csa-accent); color:var(--csa-on-accent);
}

/* ── Items catalog ────────────────────────────────────────────────────────── */
[data-page="items"] .csa-sidebar{ border-right:1px solid var(--csa-line); }
[data-page="items"] .field-row{ gap:var(--csa-s-3); }

/* ── Sales: a retirement notice, so make it read as one ───────────────────── */
[data-page="sales"] .retired-card{
  background:var(--csa-surface-1); border:1px solid var(--csa-line);
  border-radius:var(--csa-r-lg);
}
[data-page="sales"] .retired-card-title{
  font-size:var(--csa-f-lg); font-weight:600; color:var(--csa-text);
}
[data-page="sales"] .retired-card-text, [data-page="sales"] .retired-note{
  color:var(--csa-muted); font-size:var(--csa-f-sm);
}
[data-page="sales"] .retired-icon{ color:var(--csa-hint); }

/* ── Client-facing pages: portal, public form, closeout ────────────────────
   A client sees these and nothing else of Cassandra, so they carry the brand
   alone. Same surfaces and hairlines as the inside of the product. */
[data-page="portal"] .po-brand{
  font-size:var(--csa-f-lg); font-weight:650; letter-spacing:-.01em; color:var(--csa-text);
}
/* public-form and closeout-public deliberately do NOT load cassandra-theme.css.
   They declare their own standalone :root (--bg/--text/--border/--accent/--card)
   so a client-facing page cannot break when the app theme changes — a good call,
   so it is respected rather than overridden. These rules therefore use THEIR
   token names, and only the scale tokens from csa-tokens.css (--csa-f-*,
   --csa-r-*), which those pages DO load. Using --csa-text here would resolve to
   nothing and the rule would silently do less than it appears to. */
[data-page="public-form"] .brand, [data-page="closeout-public"] .brand{
  font-size:var(--csa-f-lg); font-weight:650; letter-spacing:-.01em; color:var(--text);
}
[data-page="portal"] .po-page-title{
  font-size:var(--csa-f-2xl); font-weight:650; letter-spacing:-.01em;
}
[data-page="portal"] .po-row{ border-bottom:1px solid var(--csa-line); }
[data-page="portal"] .po-muted{ color:var(--csa-muted); font-size:var(--csa-f-sm); }
[data-page="public-form"] .field-lbl{ color:var(--muted); font-size:var(--csa-f-sm); }
[data-page="public-form"] .card{
  background:var(--accent-bg); border:1px solid var(--border); border-radius:var(--csa-r-lg);
}
[data-page="closeout-public"] .card{
  background:var(--card); border:1px solid var(--border); border-radius:var(--csa-r-lg);
}
/* public-form has no warning token of its own; --danger is its only alert colour,
   so the alert uses that rather than inventing a hue this page does not define. */
[data-page="public-form"] .alert{
  border:1px solid var(--danger); color:var(--danger);
  border-radius:var(--csa-r-sm); font-size:var(--csa-f-sm);
}
[data-page="public-form"] .done-icon, [data-page="closeout-public"] .done{
  color:var(--accent);
}

/* ── Export ───────────────────────────────────────────────────────────────── */
[data-page="export"] .xp-app{
  border:1px solid var(--csa-line); border-radius:var(--csa-r-md); background:var(--csa-surface-1);
}
[data-page="export"] .xp-empty{ color:var(--csa-hint); font-size:var(--csa-f-sm); }
[data-page="export"] .xp-btn-sm{
  border-radius:var(--csa-r-sm); border:1px solid var(--csa-line-2);
  background:transparent; color:var(--csa-text);
}

/* ── rev_1190: Admin → Workflows (workflow cycles editor) ─────────────────── */
.wf-card{
  background:var(--csa-surface-1); border:1px solid var(--csa-line);
  border-radius:var(--csa-r-md); padding:var(--csa-s-3) var(--csa-s-4);
  margin-bottom:var(--csa-s-3);
}
.wf-card-hd{ display:flex; align-items:center; gap:var(--csa-s-2); flex-wrap:wrap; margin-bottom:var(--csa-s-2); }
.wf-flex{ flex:1; }
.wf-name{
  font-size:var(--csa-f-lg); font-weight:650; letter-spacing:-.01em;
  background:transparent; border:1px solid transparent; border-radius:var(--csa-r-sm);
  color:var(--csa-text); padding:3px 6px; min-width:9rem;
}
.wf-name:hover, .wf-name:focus{ border-color:var(--csa-line); background:var(--csa-bg3); }
.wf-key{
  font-size:var(--csa-f-2xs); letter-spacing:.08em; text-transform:uppercase;
  color:var(--csa-hint); font-variant-numeric:tabular-nums;
}
.wf-inline{ display:inline-flex; align-items:center; gap:6px; font-size:var(--csa-f-sm); color:var(--csa-muted); }
.wf-inline input[type=text], .wf-focus{ width:8rem; }
.wf-notes{
  font-size:var(--csa-f-sm); color:var(--csa-muted);
  border-left:2px solid var(--csa-line); padding-left:10px; margin-bottom:var(--csa-s-2);
}
/* One row per participating app. Fixed columns so the app / role / param / map
   values line up down the list and can be compared at a glance. */
.wf-approw{
  display:grid; grid-template-columns:11rem 7rem 8rem 1fr 2rem;
  gap:var(--csa-s-2); align-items:center; padding:4px 0;
}
.wf-map{ font-family:var(--csa-mono, ui-monospace, monospace); font-size:var(--csa-f-sm); }
.wf-msg{ font-size:var(--csa-f-sm); min-height:1.2em; margin-bottom:var(--csa-s-2); }
.wf-msg.ok{ color:var(--csa-accent-text); }
.wf-msg.err{ color:var(--csa-danger-text); }
@media (max-width: 900px){
  .wf-approw{ grid-template-columns:1fr 1fr; }
}

/* ── rev_1190: workflow-cycle app row in the topbar ───────────────────────── */
/* rev_1198: this lives in the topbar's CENTRED, absolutely-positioned slot, so it
   must NOT wrap — a second line would grow upward out of a 64px bar and overlap
   the brand and the app name. Scroll instead, and keep it on one line. */
.csa-tb-cycle{
  display:flex; align-items:center; gap:var(--csa-s-1);
  flex-wrap:nowrap; min-width:0; max-width:100%;
  overflow-x:auto; overflow-y:hidden;
  scrollbar-width:none;
}
.csa-tb-cycle::-webkit-scrollbar{ display:none; }
/* rev_1196: now a link back to workspace switching, since the pills are hidden
   while a cycle row is showing. */
.csa-tb-cycle-lab{
  font-size:var(--csa-f-2xs); font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--csa-hint);
  padding-right:var(--csa-s-2); margin-right:var(--csa-s-1);
  border-right:1px solid var(--csa-line); white-space:nowrap;
  text-decoration:none;
}
.csa-tb-cycle-lab:hover{ color:var(--csa-accent-text); }
.csa-tb-cyapp{
  padding:3px 9px; border-radius:var(--csa-r-full);
  font-size:var(--csa-f-sm); color:var(--csa-muted);
  text-decoration:none; white-space:nowrap;
  border:1px solid transparent;
  transition:color var(--csa-t-fast) var(--csa-ease),
             border-color var(--csa-t-fast) var(--csa-ease);
}
.csa-tb-cyapp:hover{ color:var(--csa-text); border-color:var(--csa-line); }
.csa-tb-cyapp.on{
  color:var(--csa-accent-text); border-color:var(--csa-accent);
  background:var(--csa-accent-soft);
}
/* Dim = reachable, but context is dropped when you go there. Deliberately still a
   real link with a tooltip explaining why, rather than disabled: "you may go, it
   just will not carry your project" is information, not a blocked door. */
.csa-tb-cyapp.dim{ color:var(--csa-hint); opacity:.62; }
.csa-tb-cyapp.dim:hover{ color:var(--csa-muted); opacity:1; }
/* The centre slot is a fixed-width overlay between the brand and the right-hand
   controls, so cap it rather than let it run under either. */
/* Class rather than :has() — a layout cap this load-bearing should not depend on
   selector support, and the renderer knows when it applies. */
.csa-topbar-new #csa-topbar-mid.csa-tb-has-cycle{ max-width:min(62vw, 780px); }
/* First thing to go on a narrow screen — the app name matters more than the aid. */
/* rev_1205: `@media (max-width:1100px){ .csa-tb-cycle{display:none} }` REMOVED.
   1100 was invented, and Vincent's stated floor is 1024 — so on exactly the screen
   he named, the workspace app row was hidden and there was no way to reach the
   workspace's apps. The row is already overflow-x:auto, so it degrades by
   scrolling; what it actually needed was a max-width so it stops overlapping the
   brand and the user pill. topbar.js:_csaSizeCentreSlot() measures that from the
   real geometry, which is right at every width instead of one. */

/* rev_1196: workspace default-app picker in the workspace editor. */
.mgr-ws-default{
  display:flex; align-items:center; gap:var(--csa-s-2);
  flex-wrap:wrap; margin-bottom:var(--csa-s-3);
}
.mgr-ws-default label{
  font-size:var(--csa-f-2xs); letter-spacing:.08em; text-transform:uppercase;
  color:var(--csa-muted);
}
.mgr-ws-hint{ font-size:var(--csa-f-xs); color:var(--csa-hint); }

/* ═══════════════════════════════════════════════════════════════════════════
   rev_1201 — the approved FORM, as components. Emitted by csa-shell.js.

   This is the part rev_1186 could not deliver. A mapping layer restyles what
   exists; the mock's title + subtitle + actions block did not exist in ten apps,
   so there was nothing to restyle. These are the real classes those apps now emit.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Subhead ──────────────────────────────────────────────────────────────── */
.csa-subhead{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:var(--csa-s-4); flex-wrap:wrap;
  padding:var(--csa-s-4) var(--csa-gutter) var(--csa-s-3);
  border-bottom:1px solid var(--csa-line);
}
/* rev_1235 (Vincent: "also the name breaks off" — the Projects header showed "Deventer Op
   Stelten - Font" instead of the full name). min-width:0 was here so the title could SHRINK
   rather than push the actions off the row. Growing was never enabled: with no flex property a
   child of this flex container defaults to `flex: 0 1 auto` and sizes to its CONTENT.

   For a text title that is invisible — the text is as wide as it is. Projects puts an <input>
   there (the title is rename-in-place), and an input's intrinsic width is about 20 characters
   regardless of its value. So the box was ~26 characters wide with the rest of the row empty
   beside it, and an <input> CLIPS rather than ellipsising, which is why it looked like a hard
   cut with no "…" to explain it.

   flex:1 lets the title block claim the free space. Actions are unaffected — they were already
   pushed right by justify-content:space-between — and nothing inside the title block is
   centred or stretched, so a text title lands in exactly the same place. */
.csa-subhead__titles{ flex:1 1 auto; min-width:0; }
.csa-subhead__title{
  font-size:var(--csa-f-2xl); font-weight:650; letter-spacing:-.01em;
  color:var(--csa-text); line-height:1.15;
  display:flex; align-items:baseline; gap:var(--csa-s-2); min-width:0;
}
.csa-subhead__sub{
  font-size:var(--csa-f-sm); color:var(--csa-muted); margin-top:3px;
  display:flex; align-items:center; gap:var(--csa-s-2); flex-wrap:wrap;
}
/* Backstage keeps its back button. The subhead is a flex row, so a third child
   would sit beside the titles and steal the row; giving it a full-width basis and
   order:-1 puts it back on its own line above the title, which is where it has
   always been and where the "go up one level" gesture belongs. */
[data-page="backstage"] .csa-subhead > .bs-back{
  order:-1; flex-basis:100%; margin-bottom:var(--csa-s-2);
}
/* Backstage's own padding/border predate the token layer and disagreed with every
   other app's subhead by 8px. One source now. */
[data-page="backstage"] .bs-page-hd.csa-subhead{
  padding:var(--csa-s-4) var(--csa-gutter) var(--csa-s-3);
  border-bottom:1px solid var(--csa-line);
}
[data-page="backstage"] .bs-page-title.csa-subhead__title{
  font-size:var(--csa-f-2xl); font-weight:650; letter-spacing:-.01em; margin-bottom:0;
}

/* Inbox: same story. Its .ib-head was the shape, under a different name. */
[data-page="inbox"] .ib-head.csa-subhead{ display:flex; }
[data-page="inbox"] .ib-head-title-row.csa-subhead__titles{ display:block; }
[data-page="inbox"] .ib-title.csa-subhead__title{
  font-size:var(--csa-f-2xl); font-weight:650; letter-spacing:-.01em;
}

/* rev_1204: floating variant for canvas apps (Scene Builder). Not a full-width
   band — it sits over the canvas so the drawing surface keeps the screen. */
.csa-subhead--float{
  position:absolute; z-index:420; top:var(--csa-s-3); left:var(--csa-s-3);
  max-width:min(46ch, calc(100% - 2 * var(--csa-s-3)));
  padding:var(--csa-s-3) var(--csa-s-4);
  background:var(--csa-bg2); border:.5px solid var(--csa-border);
  border-bottom:.5px solid var(--csa-border);
  border-radius:var(--csa-r-lg); box-shadow:0 8px 28px var(--csa-shadow,#0009);
  align-items:flex-start; gap:var(--csa-s-3);
}
.csa-subhead--float .csa-subhead__title{ font-size:var(--csa-f-lg); }
.csa-subhead--float .csa-subhead__sub{ font-size:var(--csa-f-xs); }
.csa-subhead__hide{
  background:none; border:0; color:var(--csa-muted); cursor:pointer;
  font-size:var(--csa-f-lg); line-height:1; padding:2px 4px; margin:-2px -4px 0 0; flex-shrink:0;
}
.csa-subhead__hide:hover{ color:var(--csa-text); }
/* A phone has no room for a floating panel over a map. */
@media (max-width:720px){ .csa-subhead--float{ display:none } }

.csa-subhead__actions{ display:flex; gap:var(--csa-s-2); flex-wrap:wrap; flex-shrink:0; }

/* Inline-editable titles. Projects renames a project in place, and replacing that
   with display text to match a mock would remove a real capability. So the input
   READS as a heading until you touch it, and only then looks like a field. */
.csa-subhead__title input,
.csa-subhead input.csa-subhead__titleinput{
  font:inherit; font-size:inherit; font-weight:inherit; letter-spacing:inherit;
  color:inherit; background:transparent;
  border:1px solid transparent; border-radius:var(--csa-r-sm);
  padding:1px 6px; margin:-1px -6px; min-width:4ch; max-width:100%;
}
.csa-subhead__title input:hover{ border-color:var(--csa-line); }
.csa-subhead__title input:focus{
  border-color:var(--csa-accent); background:var(--csa-input-bg); outline:none;
}
.csa-subhead__sub input{
  font:inherit; color:var(--csa-muted); background:transparent;
  border:1px solid transparent; border-radius:var(--csa-r-sm); padding:1px 5px; margin:-1px -5px;
}
.csa-subhead__sub input:hover{ border-color:var(--csa-line); }
.csa-subhead__sub input:focus{
  border-color:var(--csa-accent); background:var(--csa-input-bg); color:var(--csa-text); outline:none;
}
.csa-subhead__sub input::placeholder{ color:var(--csa-hint); font-style:italic; }

/* ── Card grid ────────────────────────────────────────────────────────────── */
/* auto-fit with a floor, so it is 1 column at 1024 and fills a 4K screen without
   a hardcoded count. Vincent's range is 1024 → 3840. */
.csa-cards{
  display:grid; gap:var(--csa-s-3);
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  padding:var(--csa-s-4) var(--csa-gutter);
  align-items:start;
}
.csa-cards--dense{ gap:var(--csa-s-2); }
/* A wall of 13 columns on a 4K monitor is not a design. Cap the grid, not the page:
   the page stays full-width (rev_1196) while the cards stay a readable measure. */
@media (min-width:1920px){
  .csa-cards{ grid-template-columns:repeat(auto-fit, minmax(360px, 1fr)); max-width:2000px; }
}
.csa-card__label{
  font-size:var(--csa-f-2xs); font-weight:700; letter-spacing:.08em;
  text-transform:uppercase; color:var(--csa-muted);
}
.csa-card__body{ font-size:var(--csa-f-sm); color:var(--csa-text); min-width:0; }
.csa-card--wide{ grid-column:1 / -1; }
.csa-card--interactive{ cursor:pointer; }
.csa-card--interactive:hover{ border-color:var(--csa-accent); }
.csa-card--interactive:focus-visible{
  outline:2px solid var(--csa-accent); outline-offset:2px;
}

/* Projects' rail already compiles six summary cards as .pr-ov-card. The Overview
   tab reuses that HTML rather than rebuilding the content — one source of truth —
   so those cards need to behave as grid children here. */
.csa-cards .pr-ov-card{
  margin:0; min-height:0;
  background:var(--csa-surface-1); border:1px solid var(--csa-line);
  border-radius:var(--csa-r-md);
}
.csa-cards .pr-ov-card:hover{ border-color:var(--csa-line-2); box-shadow:var(--csa-shadow-1); }

/* ── rev_1341: shared master-detail view (Vincent: "one view for more apps
   to reuse") — sortable table + detail pane. Was hand-copied across Leads
   (My desk Tasks/Deals) and Projects (Open items, My tasks) as the ld-me2-
   and pr-mt- families; the FOCUS PANE half (ld-focus/pr-focus) was already byte-for-
   byte identical between the two apps before this rev, just prefixed
   differently — a textbook duplicate. One definition now, in the shell
   file every app already loads, so a future 5th app gets this for free. */
.csa-md-split{display:flex;flex:1;min-height:0;overflow:hidden}
.csa-md-tablewrap{flex:1;min-width:0;overflow:auto;padding:16px 20px}
.csa-md-table{width:100%;border-collapse:collapse;font-size:var(--csa-f-sm)}
.csa-md-table th{position:sticky;top:0;background:var(--csa-bg);text-align:left;padding:8px 10px;font-size:var(--csa-f-xs);font-weight:600;color:var(--csa-hint);text-transform:uppercase;letter-spacing:.04em;border-bottom:1px solid var(--csa-border);cursor:pointer;user-select:none;white-space:nowrap}
.csa-md-table th:hover{color:var(--csa-text)}
.csa-md-table th .csa-md-arr{color:var(--csa-accent);margin-left:3px}
.csa-md-table td{padding:9px 10px;border-bottom:.5px solid var(--csa-border);color:var(--csa-text);vertical-align:middle}
.csa-md-table tbody tr{cursor:pointer}
.csa-md-table tbody tr:hover td{background:var(--csa-bg2)}
.csa-md-table tbody tr.sel td{background:var(--csa-accent-soft)}
.csa-md-link{color:var(--csa-accent);cursor:pointer}
.csa-md-link:hover{text-decoration:underline}
.csa-md-empty{padding:30px;text-align:center;color:var(--csa-hint);font-size:var(--csa-f-sm)}
/* detail pane — verbatim from the pre-existing identical .pr-focus/.ld-focus */
.csa-md-focus{flex:none;width:440px;border-left:.5px solid var(--csa-border);background:var(--csa-bg2);overflow:auto}
.csa-md-focus:empty{display:none}
/* rev_1351 (Vincent: "starting already in the right format … a preview pane"):
   inside a master-detail split, keep the preview pane reserved with nothing
   selected, showing a hint. Scoped to .csa-md-split — the Board's #ldFocus lives
   in .ld-pipe-split, not a split, so it still collapses when empty. */
.csa-md-split > .csa-md-focus:empty{display:block}
.csa-md-split > .csa-md-focus:empty::after{content:"Select a row to preview";display:block;padding:34px 18px;color:var(--csa-hint);font-size:var(--csa-f-sm);text-align:center}
.csa-md-focus-head{position:relative;padding:18px 18px 14px;border-bottom:.5px solid var(--csa-border)}
.csa-md-focus-x{position:absolute;top:14px;right:14px;width:26px;height:26px;border-radius:var(--csa-r-sm);border:1px solid var(--csa-border);background:var(--csa-bg3);color:var(--csa-muted);font-size:var(--csa-f-lg);cursor:pointer;line-height:1}
.csa-md-focus-x:hover{color:var(--csa-text)}
.csa-md-focus-title{font-size:var(--csa-f-lg);font-weight:600;padding-right:30px;line-height:1.3}
.csa-md-focus-sub{color:var(--csa-muted);font-size:var(--csa-f-sm);margin-top:6px}
.csa-md-focus-sub a{color:var(--csa-accent);text-decoration:none}
.csa-md-focus-sub a:hover{text-decoration:underline}
.csa-md-focus-sec{padding:15px 18px;border-bottom:.5px solid var(--csa-border)}
.csa-md-focus-kv{display:flex;justify-content:space-between;font-size:var(--csa-f-md);padding:5px 0}
.csa-md-focus-kv span{color:var(--csa-muted)}
.csa-md-focus-actions{display:flex;gap:8px;flex-wrap:wrap}
