/* =============================================================================================
   designboom newsroom: hub.css
   Plain-CSS port of the DAAily hub's design system v1 (daaily-hr-hub/web/src/design/ui.ts and
   web/src/styles/index.css), for an app with no build step. Class names mirror ui.ts so a rule
   here and a class set there mean the same thing. Rules:
     - every color is rgb(var(--token)) from /assets/hub/tokens.css, never a literal
     - every size is rem or a token; no px font sizes
     - md = 48rem (768px) is the one breakpoint the shell uses (Tailwind's `md`)
   Read docs/hub-migration/README.md before adding to this file.
   ============================================================================================= */

/* ---- Fonts: Inter Variable, self-hosted (SIL OFL 1.1, @fontsource-variable/inter 5.3.0) ---- */
@font-face { font-family: "Inter Variable"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("/assets/fonts/inter-latin-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Inter Variable"; font-style: italic; font-weight: 100 900; font-display: swap;
  src: url("/assets/fonts/inter-latin-wght-italic.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Inter Variable"; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url("/assets/fonts/inter-latin-ext-wght-normal.woff2") format("woff2-variations");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: "Inter Variable"; font-style: italic; font-weight: 100 900; font-display: swap;
  src: url("/assets/fonts/inter-latin-ext-wght-italic.woff2") format("woff2-variations");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }

:root {
  --font-sans: "Inter Variable", Inter, "Helvetica Neue", Helvetica, Arial, system-ui, sans-serif;
  /* Decision B: Forma DJR Deck on h1 and h2 only. Nothing else. */
  --font-display: "Forma DJR Deck", "Inter Variable", Inter, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* ---- Base ------------------------------------------------------------------------------- */
html { scroll-padding-top: calc(var(--header-h) + env(safe-area-inset-top, 0px) + 0.5rem); }   /* G16, 2.4.11 */
body { font-feature-settings: "cv11", "ss01", "ss03"; }
:where(h1, h2) { font-family: var(--font-display); }
/* Focus: one ring, everywhere, keyboard only (design system). No halo. */
*:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: 2px; }
/* G14: reduced motion, globally. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}
/* G13: the skip link is the first focusable thing on the page. */
.skip-link { position: absolute; left: -999px; top: 0.5rem; z-index: var(--z-tooltip); padding: 0.5rem 0.75rem;
  background: rgb(var(--primary)); color: rgb(var(--primary-fg)); border-radius: var(--radius-md);
  font: 500 0.875rem/1.25rem var(--font-sans); text-decoration: none; }
.skip-link:focus { left: 0.75rem; }
/* Figures line up in every table. */
table, td, th, .tabular { font-variant-numeric: tabular-nums; }
/* G12: touch targets and no iOS zoom below md. Carve-outs are the small close and grip marks that
   are sized to the thing they sit on (same list as the pointer:coarse floor in index.html). */
@media (max-width: 47.99rem) {
  button:not(.cd-x, .sd-x, .pl-x, .pt-att-x, .sd-dr-close, .ed-close, .dw-close, .ins-close, .al-tb, .pb-ico, .grip,
             .fold-btn, .crumb-step, .theme-seg button, .ws-seg button, .hub-theme-switch button, .hub-modal-x, .hub-toast-x),
  select, textarea,
  input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [type="hidden"]),
  .side-nav .nb, .hub-nav-row { min-height: 2.75rem; }
  input, select, textarea, input.field, select.field, textarea.field { font-size: 1rem; }   /* .field carries its own font shorthand, so it is outranked here too */
}

/* ---- Type roles (ui.ts) ------------------------------------------------------------------ */
.section-title { font: 600 1.125rem/1.75rem var(--font-display); letter-spacing: -0.02em; color: rgb(var(--fg)); }
/* Decision C: overlines and table headers are 12px (text-xs), uppercase, fg-faint. */
.overline { font: 600 0.75rem/1rem var(--font-sans); letter-spacing: 0.04em; text-transform: uppercase; color: rgb(var(--fg-faint)); }
/* Decision B: KPI figures in Inter semibold, tabular. :where() keeps this at zero specificity so
   the legacy .kpi-value rules in index.html (Deck, clamp) still win on unmigrated tiles until
   their section migrates and deletes them. */
:where(.kpi-value) { font: 600 1.5rem/2rem var(--font-sans); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; color: rgb(var(--fg)); }
/* Decision D: reading surfaces only (Article Lab, case-study text, proposal intake, Hindsight). */
.prose { font-size: 1rem; line-height: 1.5; max-width: var(--prose-max); }
.text-muted { color: rgb(var(--fg-muted)); }
.text-faint { color: rgb(var(--fg-faint)); }

/* ---- Buttons (btnBase + variants) -------------------------------------------------------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.375rem; height: 2rem; padding: 0 0.75rem;
  border: 1px solid transparent; border-radius: var(--radius-md); font: 500 0.875rem/1.25rem var(--font-sans); letter-spacing: normal;
  color: rgb(var(--fg)); background: transparent; cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background-color var(--duration-fast), border-color var(--duration-fast), color var(--duration-fast); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
.btn svg { width: 1rem; height: 1rem; flex: none; }
/* One primary per view. */
.btn-primary { background: rgb(var(--primary)); color: rgb(var(--primary-fg)); border-color: rgb(var(--primary)); }
/* The legacy stylesheet in index.html gives .btn-primary a 12px top margin, and it loads first,
   so every hub primary button (dialog footers included) sat low. Same specificity as that rule and
   later in the cascade, so it wins over it and loses to any more specific rule. Delete with Step 5. */
:where(.btn).btn-primary { margin-top: 0; }
.btn-primary:hover:not(:disabled) { background: rgb(var(--primary-hover)); border-color: rgb(var(--primary-hover)); }
/* The default for most actions. */
.btn-secondary { background: rgb(var(--surface)); color: rgb(var(--fg)); border-color: rgb(var(--line-strong)); }
.btn-secondary:hover:not(:disabled) { background: rgb(var(--surface-2)); }
/* Toolbars and row actions. */
.btn-ghost { color: rgb(var(--fg-muted)); }
.btn-ghost:hover:not(:disabled) { background: rgb(var(--surface-2)); color: rgb(var(--fg)); }
/* Delete, reject, revoke: solid only inside a confirmation. */
.btn-danger { color: rgb(var(--danger)); border-color: rgb(var(--danger) / 0.3); }
.btn-danger:hover:not(:disabled) { background: rgb(var(--danger-subtle)); }
.btn-danger.is-solid { background: rgb(var(--danger)); color: rgb(var(--primary-fg)); border-color: rgb(var(--danger)); }
/* Icon-only button: square. */
.btn-icon { width: 2rem; padding: 0; }
.btn-sm-h { height: 1.75rem; padding: 0 0.625rem; }

/* ---- Fields (selectCls, index.css inputs) ------------------------------------------------ */
.field { display: block; width: 100%; height: 2rem; padding: 0 0.625rem; border: 1px solid rgb(var(--line-strong)); border-radius: var(--radius-md);
  background: rgb(var(--surface)); color: rgb(var(--fg)); font: 400 0.875rem/1.25rem var(--font-sans);
  transition: border-color var(--duration-fast); }
.field::placeholder { color: rgb(var(--fg-faint)); }
.field:focus { outline: none; border-color: rgb(var(--ring)); }
.field:focus-visible { outline: none; border-color: rgb(var(--ring)); box-shadow: 0 0 0 1px rgb(var(--ring)); }
.field:disabled { opacity: 0.5; cursor: not-allowed; }
select.field { padding-right: 2rem; appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B6862' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 0.5rem center; background-size: 1rem; }
textarea.field { height: auto; min-height: 5rem; padding: 0.5rem 0.625rem; resize: vertical; }
.field-label { display: block; margin-bottom: 0.375rem; font: 500 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg)); }
.field-help { margin-top: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: rgb(var(--fg-muted)); }
.field-error { margin-top: 0.375rem; font-size: 0.75rem; line-height: 1rem; color: rgb(var(--danger)); }
.field.is-invalid { border-color: rgb(var(--danger)); }

/* ---- Segmented control (segGroup / segItem / segItemOn): neutral, never brand ------------- */
.seg { display: inline-flex; max-width: 100%; overflow-x: auto; gap: 0.125rem; padding: 0.125rem; border-radius: var(--radius-lg);
  background: rgb(var(--surface-2)); scrollbar-width: none; }
.seg::-webkit-scrollbar { display: none; }
.seg-item { display: inline-flex; align-items: center; gap: 0.375rem; height: 1.75rem; padding: 0 0.75rem; flex: none; white-space: nowrap;
  border: 0; border-radius: var(--radius-md); background: transparent; font: 400 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg-muted));
  cursor: pointer; transition: color var(--duration-fast), background-color var(--duration-fast); }
.seg-item:hover { color: rgb(var(--fg)); }
.seg-on, .seg-item[aria-selected="true"], .seg-item[aria-pressed="true"], .seg-item[aria-checked="true"] {
  background: rgb(var(--surface-3)); color: rgb(var(--fg)); font-weight: 500; box-shadow: var(--shadow-xs); }

/* ---- Cards (card / cardLink) ------------------------------------------------------------- */
.card { border: 1px solid rgb(var(--line)); border-radius: var(--radius-lg); background: rgb(var(--surface)); color: rgb(var(--fg)); }
.card-link { transition: border-color var(--duration-fast), background-color var(--duration-fast); cursor: pointer; text-decoration: none; }
.card-link:hover { border-color: rgb(var(--line-strong)); background: rgb(var(--surface-2)); }
.card-p4 { padding: var(--space-4); }
.card-p6 { padding: var(--space-6); }

/* ---- Page frame (pageFrame / formFrame): left-aligned to the sidebar, never centered ------- */
.page, .page-form { width: 100%; margin: 0; padding: 1.5rem 1rem 2.5rem; box-sizing: border-box; }
.page { max-width: var(--page-max); }
.page-form { max-width: var(--form-max); }
.content-max { max-width: var(--content-max); }
@media (min-width: 48rem) { .page, .page-form { padding-left: 2rem; padding-right: 2rem; } }

/* ---- Stat grid (statGrid) ---------------------------------------------------------------- */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); column-gap: var(--space-6); row-gap: var(--space-3); }
.stat-grid > * { min-width: 0; }
.stat-label { font-size: 0.75rem; line-height: 1rem; color: rgb(var(--fg-faint)); }
.stat-delta { font-size: 0.75rem; line-height: 1rem; font-variant-numeric: tabular-nums; }
.stat-delta.is-up { color: rgb(var(--success)); }
.stat-delta.is-down { color: rgb(var(--danger)); }

/* ---- Pills (index.css .pill-*) ----------------------------------------------------------- */
.pill { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.125rem 0.625rem; border-radius: var(--radius-md);
  font: 500 0.75rem/1rem var(--font-sans); letter-spacing: -0.01em; white-space: nowrap; }
.pill-neutral { background: rgb(var(--surface-2)); color: rgb(var(--fg-muted)); }
.pill-info { background: rgb(var(--info-subtle)); color: rgb(var(--info)); }
.pill-success { background: rgb(var(--success-subtle)); color: rgb(var(--success)); }
.pill-warning { background: rgb(var(--warning-subtle)); color: rgb(var(--warning)); }
.pill-danger { background: rgb(var(--danger-subtle)); color: rgb(var(--danger)); }
/* Brand tag (G17): text in fg, the brand as a swatch, never yellow text. */
.pill-designboom { background: rgb(var(--designboom-subtle)); color: rgb(var(--fg)); }
.pill-designboom::before { content: ""; width: 0.5rem; height: 0.5rem; border-radius: var(--radius-full);
  background: rgb(var(--designboom-solid)); box-shadow: inset 0 0 0 1px rgb(var(--line-strong)); }

/* ---- Tables (index.css data tables, Decision C headers; G3 in Step 3) ---------------------
   min-width: 0 on purpose: index.html still carries `table { min-width: 600px }` from the old
   dashboards, and a 600px floor is a horizontal scroll on every phone. The header sticks under the
   top bar in page flow, and at 0 inside a scrolling wrapper or an overlay body. Rows are 2.75rem
   (44px): one line of text sits in the middle, a two-line cell grows the row. */
.hub-table { width: 100%; min-width: 0; border-collapse: collapse; font-family: var(--font-sans); font-size: 0.875rem; line-height: 1.25rem; color: rgb(var(--fg)); }
.hub-table thead th { position: sticky; top: calc(var(--header-h) + env(safe-area-inset-top, 0px)); z-index: var(--z-sticky); text-align: left; padding: 0.625rem 1rem;
  background: rgb(var(--surface-2)); border-bottom: 1px solid rgb(var(--line-strong)); vertical-align: bottom; box-shadow: none;
  font: 600 0.75rem/1rem var(--font-sans); letter-spacing: 0.04em; text-transform: uppercase; color: rgb(var(--fg-faint)); }
.table-wrap .hub-table thead th, .hub-ov-body .hub-table thead th, .hub-table.is-flat thead th { top: 0; }
/* index.html's generic sortable-header affordance (a ↕ after every th, and its delegated sorter) does
   not apply here: a hub table sorts through Hub.table.sortable on th[data-sort] only. */
.hub-table thead th:not([data-gs-dir])::after,
.hub-table thead th:not([data-sk]):not([data-k]):not([data-oi]):not([onclick]):not(:empty):not([data-gs-dir])::after,
.hub-table thead th[aria-sort="none"]::after { content: none; }   /* the second selector outranks index.html's six-:not() rule; a data-gs-dir column (the generic sorter's ▲ or ▼, index.html) is left to it in both directions */
.hub-table thead th:not(.is-sortable) { cursor: default; user-select: text; }
.hub-collection.has-bulk .hub-table thead th { top: calc(var(--header-h) + env(safe-area-inset-top, 0px) + 3.75rem); }
.hub-table tbody td { height: 2.75rem; padding: 0.5rem 1rem; border-bottom: 1px solid rgb(var(--line)); vertical-align: middle; color: rgb(var(--fg)); }
.hub-table tbody tr:last-child td { border-bottom: 0; }
.hub-table tbody tr:hover td { background: rgb(var(--surface-2)); }
.hub-table tbody tr[aria-selected="true"] td, .hub-table tbody tr.is-selected td { background: rgb(var(--surface-3)); }
.hub-table tbody tr.is-click { cursor: pointer; }
/* The row's opener: the primary cell's text is a button, so the keyboard reaches the record without a focusable tr. */
.hub-table .hub-row-open, .hub-cards .hub-card-open { display: inline; padding: 0; border: 0; min-height: 0; background: none; font: inherit; color: inherit; text-align: left; cursor: pointer; }
.hub-table .hub-row-open:hover, .hub-cards .hub-card-open:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.hub-table tbody tr.is-click a, .hub-table tbody tr.is-click button, .hub-table tbody tr.is-click label, .hub-table tbody tr.is-click input { cursor: pointer; }
.hub-table tbody tr:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: -2px; }
.hub-table th.is-num, .hub-table td.is-num { text-align: right; font-variant-numeric: tabular-nums; }
/* One line per row: an .is-ellipsis cell truncates (max-width: 0 lets a table cell shrink), .is-nowrap never wraps. Both relax in the card mode below md. */
.hub-table td.is-ellipsis { max-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-table td.is-nowrap { white-space: nowrap; }
.hub-table td .text-faint, .hub-table td .text-muted { font-size: 0.75rem; line-height: 1rem; }
/* Sortable column: the whole header cell is the button; aria-sort on the th says the direction. */
.hub-table th.is-sortable { padding: 0; }
.hub-sort { display: inline-flex; align-items: center; gap: 0.25rem; width: 100%; min-height: 2.5rem; padding: 0.625rem 1rem; border: 0; background: transparent;
  font: inherit; letter-spacing: inherit; text-transform: inherit; color: inherit; text-align: left; cursor: pointer; }
.hub-table th.is-num .hub-sort { justify-content: flex-end; }
.hub-sort:hover { color: rgb(var(--fg)); }
.hub-sort:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: -2px; }
.hub-sort-mark { width: 0.75rem; height: 0.75rem; flex: none; opacity: 0.45; transition: transform var(--duration-fast), opacity var(--duration-fast); }
.hub-table th[aria-sort] .hub-sort { color: rgb(var(--fg)); }
.hub-table th[aria-sort] .hub-sort-mark { opacity: 1; }
.hub-table th[aria-sort="descending"] .hub-sort-mark { transform: rotate(180deg); }
/* Leading checkbox column. */
.hub-table .hub-check { width: 2.75rem; padding-right: 0; }
.hub-table thead th.hub-check { padding: 0.625rem 0 0.625rem 1rem; }
.hub-table .hub-check input, .hub-check-box { width: 1rem; height: 1rem; margin: 0; vertical-align: middle; accent-color: rgb(var(--primary)); cursor: pointer; }
/* Below md the same rows render as stacked cards (ResponsiveTable): the header goes, each row is a
   card, each cell a label / value line from data-label, the primary cell the card's title, and a
   cell marked .is-card-hidden is left out. Never a horizontal scroll. */
@media (max-width: 47.99rem) {
  .hub-table.is-responsive, .hub-table.is-responsive tbody, .hub-table.is-responsive tr, .hub-table.is-responsive td { display: block; }
  .hub-table.is-responsive thead { display: none; }
  .hub-table.is-responsive tbody tr { position: relative; margin: 0 0 0.75rem; padding: 0.75rem 1rem; border: 1px solid rgb(var(--line)); border-radius: var(--radius-lg);
    background: rgb(var(--surface)); transition: background-color var(--duration-fast), border-color var(--duration-fast); }
  .hub-table.is-responsive tbody tr:last-child { margin-bottom: 0; }
  .hub-table.is-responsive tbody tr.is-click:hover { background: rgb(var(--surface-2)); }
  .hub-table.is-responsive tbody tr[aria-selected="true"], .hub-table.is-responsive tbody tr.is-selected { background: rgb(var(--surface-3)); border-color: rgb(var(--line-strong)); }
  .hub-table.is-responsive tbody tr:hover td, .hub-table.is-responsive tbody tr[aria-selected="true"] td, .hub-table.is-responsive tbody tr.is-selected td { background: transparent; }
  .hub-table.is-responsive tbody td { display: flex; justify-content: space-between; gap: 0.75rem; height: auto; min-height: 0; padding: 0.1875rem 0; border: 0; text-align: right; }
  .hub-table.is-responsive tbody td::before { content: attr(data-label); flex: none; color: rgb(var(--fg-faint)); text-align: left; }
  .hub-table.is-responsive tbody td:not([data-label])::before { display: none; }
  .hub-table.is-responsive tbody td.is-primary { display: block; padding: 0 2rem 0.375rem 0; font-weight: 500; text-align: left; }
  .hub-table.is-responsive tbody td.is-primary::before, .hub-table.is-responsive tbody td.hub-check::before { display: none; }
  .hub-table.is-responsive tbody td.is-card-hidden { display: none; }
  .hub-table.is-responsive tbody td.is-ellipsis, .hub-table.is-responsive tbody td.is-nowrap { max-width: none; white-space: normal; overflow: visible; }
  .hub-table.is-responsive tbody td.is-card-full { display: block; text-align: left; }
  .hub-table.is-responsive tbody td.is-card-full::before { display: block; margin-bottom: 0.125rem; }
  .hub-table.is-responsive tbody td.hub-check { position: absolute; top: 0.625rem; right: 0.625rem; width: auto; padding: 0.25rem; }
  .hub-table.is-responsive tbody td.hub-check input { width: 1.25rem; height: 1.25rem; }
}

/* =============================================================================================
   THE SHELL. The markup is the newsroom's own (<aside class="sidebar"> stays the source of truth
   for gating, ⌘K, crumbs and cards); these rules give it the hub's geometry. .hub-shell is on
   the .app wrapper; the shell layer at the end of index.html adds the classes named here.
   ============================================================================================= */
/* No font-family on the wrapper: unmigrated pages keep Forma DJR until their own step. The shell parts set Inter themselves. */
.hub-shell { display: flex; align-items: stretch; min-height: 100vh; background: rgb(var(--bg)); color: rgb(var(--fg)); }
.hub-shell > .main-col { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

/* ---- Sidebar: 240px, collapsible to 56px (html.nav-rail), hidden below md ---------------- */
.hub-shell > .sidebar { position: sticky; top: 0; height: 100vh; height: 100dvh; flex: 0 0 var(--sidebar-w); width: var(--sidebar-w);
  display: flex; flex-direction: column; gap: 0; padding: 0; overflow: visible;
  background: rgb(var(--bg-sidebar)); color: rgb(var(--fg)); border-right: 1px solid rgb(var(--line));
  z-index: var(--z-sidebar); font-family: var(--font-sans); transition: width var(--duration-base), flex-basis var(--duration-base); transform: none; box-shadow: none; }
html.nav-rail .hub-shell > .sidebar { flex-basis: var(--sidebar-w-collapsed); width: var(--sidebar-w-collapsed); padding: 0; gap: 0; }
/* Lockup row: the designboom wordmark as its own badge (black on yellow, the mark as designboom
   draws it, and it reads in both themes) plus the room descriptor, and the collapse toggle. */
.hub-shell .side-brand { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.5rem; padding: 0.75rem 0.75rem 0.25rem; }
.hub-shell .brand-lockup { display: flex; flex-direction: column; gap: 0.375rem; padding: 0.25rem 0.5rem; min-width: 0; font: inherit; }
.hub-shell .brand-word, .hub-shell .brand-glyph { display: block; height: 0.875rem; width: auto; padding: 0.375rem 0.5rem; box-sizing: content-box;
  border-radius: var(--radius-sm); background: rgb(var(--designboom-solid)); color: rgb(var(--designboom-on)); }
.hub-shell .brand-glyph { display: none; height: 1rem; padding: 0.375rem; }
.hub-shell .brand-sub { margin: 0; font: 600 0.75rem/1rem var(--font-sans); letter-spacing: 0.04em; text-transform: uppercase; color: rgb(var(--fg-faint)); }
html.nav-rail .hub-shell .side-brand { flex-direction: column; align-items: center; padding: 0.75rem 0.5rem 0.25rem; }
html.nav-rail .hub-shell .brand-lockup { padding: 0; align-items: center; }
html.nav-rail .hub-shell .brand-word, html.nav-rail .hub-shell .brand-sub { display: none; }
html.nav-rail .hub-shell .brand-glyph { display: block; }
/* The collapse toggle (#railToggle) sits beside the lockup, icon only. */
.hub-shell .rail-toggle { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 2rem; height: 2rem; margin: 0; padding: 0;
  border: 0; border-radius: var(--radius-md); background: transparent; color: rgb(var(--fg-faint)); cursor: pointer; font: inherit;
  transition: color var(--duration-fast), background-color var(--duration-fast); }
.hub-shell .rail-toggle:hover { color: rgb(var(--fg)); background: rgb(var(--surface-2)); }
.hub-shell .rail-toggle span { display: none; }
.hub-shell .rail-toggle .nb-ico { transition: transform var(--duration-fast); }
html.nav-rail .hub-shell .rail-toggle .nb-ico { transform: rotate(180deg); }
/* Workspace switcher at the top of the sidebar: a segmented control. */
.hub-shell > .sidebar .ws-seg { margin: 0.25rem 0.75rem 0.5rem; padding: 0.125rem; gap: 0.125rem; border: 0; border-radius: var(--radius-lg); background: rgb(var(--surface-2)); }
.hub-shell > .sidebar .ws-seg button { height: 1.75rem; padding: 0 0.75rem; border-radius: var(--radius-md); font: 400 0.8125rem/1.25rem var(--font-sans); letter-spacing: normal; color: rgb(var(--fg-muted)); box-shadow: none; }
.hub-shell > .sidebar .ws-seg button[aria-pressed="true"] { background: rgb(var(--surface-3)); color: rgb(var(--fg)); font-weight: 500; box-shadow: var(--shadow-xs); }
.hub-shell > .sidebar .ws-seg button:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: 2px; box-shadow: none; }
html.nav-rail .hub-shell > .sidebar .ws-seg { display: none; }
/* The nav scrolls; the sidebar itself does not, so the user menu popover at its foot can escape. */
.hub-shell .side-nav { position: static; z-index: auto; border: 0; flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: 0.25rem 0.75rem 1rem; gap: 0.125rem; scrollbar-width: thin; }
html.nav-rail .hub-shell .side-nav { padding-left: 0.5rem; padding-right: 0.5rem; }
/* Nav row: h-8 px-2.5 rounded-md text-sm. */
.hub-shell .side-nav .nb { position: relative; display: flex; align-items: center; gap: 0.625rem; width: 100%; min-height: 2rem; padding: 0.25rem 0.625rem;
  border: 0; border-radius: var(--radius-md); background: transparent; box-shadow: none; text-align: left;
  font: 400 0.875rem/1.25rem var(--font-sans); letter-spacing: normal; color: rgb(var(--fg-muted)); cursor: pointer; text-decoration: none;
  transition: color var(--duration-fast), background-color var(--duration-fast); }
.hub-shell .side-nav .nb > span:not(.nb-count):not(.beta-tag):not(.nb-ext) { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-shell .side-nav .nb:hover { color: rgb(var(--fg)); background: rgb(var(--surface-2)); }
.hub-shell .side-nav .nb .nb-ico { flex: none; width: 1rem; height: 1rem; color: rgb(var(--fg-faint)); }
.hub-shell .side-nav .nb:hover .nb-ico, .hub-shell .side-nav .nb.active .nb-ico { color: rgb(var(--fg)); }
.hub-shell .side-nav .nb-child { padding-top: 0.25rem; padding-bottom: 0.25rem; font-size: 0.875rem; }
/* Decision A (revised 2026-09-30): "you are here" is the designboom wash with the label in fg
   and a 2px yellow bar on the sidebar's edge. Never yellow text. */
.hub-shell .side-nav .nb.active { color: rgb(var(--fg)); background: rgb(var(--designboom-subtle)); font-weight: 500; box-shadow: none; }
.hub-shell .side-nav .nb.active::before { content: ""; position: absolute; left: -0.75rem; top: 0.375rem; bottom: 0.375rem; width: 2px;
  border-radius: var(--radius-full); background: rgb(var(--designboom-solid)); }
html.nav-rail .hub-shell .side-nav .nb.active::before { left: -0.5rem; }
/* Group header: an overline that folds its group. */
.hub-shell .nav-label { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; width: 100%; padding: 1rem 0.625rem 0.25rem;
  border: 0; background: transparent; text-align: left; cursor: pointer;
  font: 600 0.75rem/1rem var(--font-sans); letter-spacing: 0.04em; text-transform: uppercase; color: rgb(var(--fg-faint)); box-shadow: none; }
.hub-shell .nav-label:hover { color: rgb(var(--fg-muted)); }
.hub-shell .nav-label:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: 2px; box-shadow: none; border-radius: var(--radius-sm); }
.hub-shell .nav-label .nb-chev { color: rgb(var(--fg-faint)); }
.hub-shell .nav-children { gap: 0.125rem; margin: 0 0 0.25rem; }
/* The pinned pages (Feedback, Guide) under the last group: a hairline like the Graveyard's, drawn outside the row so
   the hover wash never sits on it. A bare margin here read as a missing row (Timo, 2026-10-01: "strange gap"). */
.hub-shell .side-nav .nav-group + .nb { margin-top: 0.75rem; padding-top: 0.25rem; border-top: 0; }
.hub-shell .side-nav .nav-group + .nb::after { content: ""; position: absolute; left: 0; right: 0; top: -0.375rem; border-top: 1px solid rgb(var(--line)); pointer-events: none; }
html.nav-rail .hub-shell .side-nav .nav-group + .nb::after { left: 0.25rem; right: 0.25rem; }
.hub-shell .side-nav #grp-graveyard { margin-top: 0.5rem; padding-top: 0.25rem; border-top: 1px solid rgb(var(--line)); }
.hub-shell .side-nav #grp-graveyard > .nav-label, .hub-shell .side-nav #grp-graveyard .nb-child { color: rgb(var(--fg-faint)); }
.hub-shell .side-nav #grp-graveyard .nb-child:hover, .hub-shell .side-nav #grp-graveyard .nb-child.active { color: rgb(var(--fg)); }
.hub-shell .side-nav .nb-ext { color: rgb(var(--fg-faint)); }
/* Count badges: yellow fill, near-black text (Decision A). */
.hub-shell .nb-count, .hub-shell .nb-badge, .crumb-menu .nb-count {
  display: inline-flex; align-items: center; justify-content: center; min-width: 1.25rem; height: 1.25rem; padding: 0 0.375rem; margin-left: auto;
  border-radius: var(--radius-full); background: rgb(var(--designboom-solid)); color: rgb(var(--designboom-on));
  font: 600 0.75rem/1 var(--font-sans); font-variant-numeric: tabular-nums; letter-spacing: normal; }
.hub-shell .nb-count[hidden], .hub-shell .nb-badge[hidden] { display: none; }
.hub-shell .beta-tag { font-family: var(--font-sans); font-size: 0.6875rem; letter-spacing: 0.02em; padding: 0.0625rem 0.3125rem; border-radius: var(--radius-sm);
  background: rgb(var(--surface-2)); color: rgb(var(--fg-faint)); border: 1px solid rgb(var(--line)); }
/* Collapsed rail: icons only, group labels become hairlines, counts become dots. */
html.nav-rail .hub-shell .nav-label { height: 0; padding: 0; margin: 0.5rem 0.25rem; border-top: 1px solid rgb(var(--line)); overflow: hidden; color: transparent; }
html.nav-rail .hub-shell .nav-label > * { display: none; }
html.nav-rail .hub-shell .side-nav .nav-group:not(.tabbed) > .nav-children { display: flex; }
html.nav-rail .hub-shell .side-nav .nb { justify-content: center; padding-left: 0; padding-right: 0; }
html.nav-rail .hub-shell .side-nav .nb > span:not(.nb-count), html.nav-rail .hub-shell .side-nav .nb .beta-tag, html.nav-rail .hub-shell .side-nav .nb .nb-ext { display: none; }
html.nav-rail .hub-shell .side-nav .nb .nb-count { position: absolute; top: 0.125rem; right: 0.125rem; min-width: 0.5rem; height: 0.5rem; padding: 0; margin: 0; font-size: 0; }
html.nav-rail .hub-shell .side-nav .nb .nb-count[hidden] { display: none; }
/* User row at the foot of the sidebar: avatar, name, and the menu it discloses (#umWrap moves in
   here on desktop; the shell layer does the moving). */
.hub-shell .hub-sidebar-user { flex: none; padding: 0.5rem 0.75rem; border-top: 1px solid rgb(var(--line)); }
html.nav-rail .hub-shell .hub-sidebar-user { padding-left: 0.375rem; padding-right: 0.375rem; }
.hub-shell .hub-sidebar-user .um-wrap { position: relative; display: block; }
.hub-shell .hub-sidebar-user .um-btn { display: flex; align-items: center; gap: 0.625rem; width: 100%; height: 2.5rem; padding: 0.25rem 0.5rem;
  border: 0; border-radius: var(--radius-md); background: transparent; color: rgb(var(--fg)); cursor: pointer; text-align: left; }
.hub-shell .hub-sidebar-user .um-btn:hover, .hub-shell .hub-sidebar-user .um-btn[aria-expanded="true"] { background: rgb(var(--surface-2)); }
.hub-shell .hub-sidebar-user .um-btn .side-user-av { position: static; width: 1.75rem; height: 1.75rem; flex: none; }
.hub-shell .hub-sidebar-user .um-btn .um-fallback { position: static; width: 1.75rem; height: 1.75rem; flex: none; padding: 0.25rem; border-radius: var(--radius-full); background: rgb(var(--surface-3)); color: rgb(var(--fg-muted)); }
.hub-shell .hub-sidebar-user .um-btn:has(.side-user-av[src]) .um-fallback { display: none; }
.hub-shell .um-btn .side-user-av:not([src]) { display: none; }   /* no photo yet: the fallback glyph alone */
.hub-shell .hub-sidebar-user .um-btn-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 500 0.875rem/1.25rem var(--font-sans); }
.hub-shell .hub-sidebar-user .um-btn-chev { flex: none; color: rgb(var(--fg-faint)); }
html.nav-rail .hub-shell .hub-sidebar-user .um-btn { justify-content: center; padding: 0.25rem; }
html.nav-rail .hub-shell .hub-sidebar-user .um-btn-name, html.nav-rail .hub-shell .hub-sidebar-user .um-btn-chev { display: none; }
.hub-shell .hub-sidebar-user .user-menu { position: absolute; left: 0; right: auto; bottom: calc(100% + 0.5rem); top: auto; width: 16rem; max-width: calc(100vw - 1.5rem);
  z-index: var(--z-dropdown); border-radius: var(--radius-lg); border: 1px solid rgb(var(--line)); background: rgb(var(--surface)); box-shadow: var(--shadow-md); padding: 0.25rem; }
html.nav-rail .hub-shell .hub-sidebar-user .user-menu { left: 0; }
/* The user menu (wherever it sits): hub geometry. */
.hub-shell .user-menu { border-radius: var(--radius-lg); border: 1px solid rgb(var(--line)); background: rgb(var(--surface)); box-shadow: var(--shadow-md); padding: 0.25rem; }
.hub-shell .um-head { padding: 0.5rem 0.625rem 0.625rem; border-bottom: 1px solid rgb(var(--line)); margin-bottom: 0.25rem; }
.hub-shell .um-name { font: 500 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg)); }
.hub-shell .um-mail { font: 400 0.75rem/1rem var(--font-sans); color: rgb(var(--fg-faint)); margin-top: 0.125rem; }
.hub-shell .um-row { display: block; padding: 0.375rem 0.625rem 0.5rem; font: 500 0.75rem/1rem var(--font-sans); color: rgb(var(--fg-faint)); text-transform: uppercase; letter-spacing: 0.04em; }
.hub-shell .um-row > span { display: block; margin-bottom: 0.375rem; }
.hub-shell .um-item { display: flex; align-items: center; gap: 0.625rem; width: 100%; min-height: 2rem; padding: 0.375rem 0.625rem; border: 0; border-radius: var(--radius-md);
  background: transparent; font: 400 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg-muted)); text-align: left; cursor: pointer; }
.hub-shell .um-item:hover { background: rgb(var(--surface-2)); color: rgb(var(--fg)); }
.hub-shell .um-item .nb-ico { color: rgb(var(--fg-faint)); }
.hub-shell .um-item:hover .nb-ico { color: rgb(var(--fg)); }
.hub-shell .um-sep { height: 1px; margin: 0.25rem 0.25rem; background: rgb(var(--line)); }
/* Three-way theme switch (Hub.theme.renderSwitch): a radiogroup on surface-2, the checked one on surface-3. */
.hub-theme-switch { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.125rem; padding: 0.125rem; border-radius: var(--radius-lg); background: rgb(var(--surface-2)); }
.hub-theme-switch button { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.125rem; height: 2.75rem; padding: 0.25rem 0.25rem;
  border: 0; border-radius: var(--radius-md); background: transparent; font: 400 0.75rem/1rem var(--font-sans); letter-spacing: normal; text-transform: none; color: rgb(var(--fg-muted)); cursor: pointer;
  transition: color var(--duration-fast), background-color var(--duration-fast); }
.hub-theme-switch button svg { width: 1rem; height: 1rem; }
.hub-theme-switch button:hover { color: rgb(var(--fg)); }
.hub-theme-switch button[aria-checked="true"] { background: rgb(var(--surface-3)); color: rgb(var(--fg)); font-weight: 500; box-shadow: var(--shadow-xs); }

/* ---- Top bar: 56px plus the safe area, translucent, one hairline --------------------------- */
.hub-shell header.hub-topbar { position: sticky; top: var(--viewas-h, 0px); z-index: var(--z-header);
  display: flex; flex-wrap: nowrap; align-items: center; justify-content: flex-start; gap: 0.75rem;
  height: calc(var(--header-h) + env(safe-area-inset-top, 0px)); padding: env(safe-area-inset-top, 0px) 1rem 0;
  background: rgb(var(--bg) / 0.8); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); border-bottom: 1px solid rgb(var(--line)); font-family: var(--font-sans); }
@media (min-width: 48rem) { .hub-shell header.hub-topbar { padding-left: 2rem; padding-right: 2rem; gap: 1rem; } }
.hub-shell header.hub-topbar .side-toggle { display: none; }   /* the More tab opens the sheet below md */
/* Mobile mark: the wordmark badge, the way home; the sidebar has it above md. */
.hub-shell header.hub-topbar .hdr-brand { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0; border: 0; background: none; cursor: pointer; color: rgb(var(--fg)); }
.hub-shell header.hub-topbar .hdr-brand > svg { display: block; height: 0.75rem; width: auto; padding: 0.375rem 0.5rem; box-sizing: content-box;
  border-radius: var(--radius-sm); background: rgb(var(--designboom-solid)); color: rgb(var(--designboom-on)); fill: currentColor; }
.hub-shell header.hub-topbar .hdr-brand .brand-sub { display: none; }
.hub-shell header.hub-topbar .hdr-brand:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: 2px; border-radius: var(--radius-sm); }
@media (min-width: 48rem) { .hub-shell header.hub-topbar .hdr-brand { display: none; } }
.hub-shell header.hub-topbar > .ws-seg { display: none; }     /* the sidebar (and the sheet) hold the original */
.hub-shell header.hub-topbar .header-end { display: flex; flex: 1 1 auto; align-items: center; justify-content: flex-end; gap: 0.5rem; min-width: 0; grid-column: auto; order: 0; flex-basis: auto; }
/* The ⌘K search button (SearchButton): h-8 w-56 field look with a kbd; icon only below md. */
.hub-shell .header-search { position: relative; display: flex; align-items: center; flex: 0 0 auto; width: 14rem; max-width: 14rem; min-width: 0; order: 0; }
.hub-shell .header-ask { width: 100%; height: 2rem; padding: 0 3rem 0 2rem; border: 1px solid rgb(var(--line)); border-radius: var(--radius-md);
  background: rgb(var(--surface)); color: rgb(var(--fg-faint)); font: 400 0.875rem/1.25rem var(--font-sans); cursor: pointer; box-sizing: border-box;
  transition: border-color var(--duration-fast); }
.hub-shell .header-ask::placeholder { color: rgb(var(--fg-faint)); }
.hub-shell .header-ask:hover { border-color: rgb(var(--line-strong)); }
.hub-shell .header-ask:focus { outline: none; border-color: rgb(var(--ring)); background: rgb(var(--surface)); }
.hub-shell .header-search .hs-icon { left: 0.625rem; color: rgb(var(--fg-faint)); }
.hub-shell .header-search .kbd-hint { right: 0.375rem !important; padding: 0.125rem 0.375rem; border: 1px solid rgb(var(--line)); border-radius: var(--radius-sm);
  background: transparent; color: rgb(var(--fg-faint)); font: 500 0.6875rem/1rem var(--font-sans); letter-spacing: 0.02em; }
.hub-shell .header-search .kbd-hint:hover { color: rgb(var(--fg)); border-color: rgb(var(--line-strong)); }
@media (max-width: 47.99rem) {
  .hub-shell .header-search { width: 2rem; max-width: 2rem; }
  .hub-shell .header-ask { padding: 0; color: transparent; font-size: 1rem; }   /* 1rem: iOS zooms a smaller field on focus */
  .hub-shell .header-ask::placeholder { color: transparent; }
  .hub-shell .header-search .hs-icon { left: 50%; transform: translate(-50%, -50%); }
  .hub-shell .header-search .kbd-hint { display: none; }
}
/* Right cluster: bell, feedback, avatar (mobile only; on desktop the avatar is in the sidebar). */
.hub-shell .header-right { display: flex; align-items: center; gap: 0.25rem; flex: none; }
.hub-shell .header-right > #userChip { order: 1; margin: 0; padding: 0; border: 0; gap: 0.25rem; }
.hub-shell .header-right > #fbSlot { order: 2; display: inline-flex; align-items: center; }
.hub-shell .header-right > .um-wrap { order: 3; }
.hub-shell .header-right .side-user-out, .hub-shell .header-right .um-btn { width: 2rem; height: 2rem; padding: 0; border: 0; border-radius: var(--radius-md);
  display: inline-flex; align-items: center; justify-content: center; background: transparent; color: rgb(var(--fg-muted)); cursor: pointer; }
.hub-shell .header-right .side-user-out:hover, .hub-shell .header-right .um-btn:hover, .hub-shell .header-right .um-btn[aria-expanded="true"] { background: rgb(var(--surface-2)); color: rgb(var(--fg)); }
.hub-shell .header-right .um-btn .side-user-av { width: 1.75rem; height: 1.75rem; }
.hub-shell .header-right .um-btn .um-btn-name, .hub-shell .header-right .um-btn .um-btn-chev { display: none; }
.hub-shell .header-right .nb-badge { position: absolute; top: 0; right: 0; min-width: 1rem; height: 1rem; padding: 0 0.25rem; margin: 0; font-size: 0.6875rem;
  box-shadow: 0 0 0 2px rgb(var(--bg)); }
.hub-shell .header-right .user-menu { top: calc(100% + 0.5rem); right: 0; left: auto; bottom: auto; width: 16rem; z-index: var(--z-dropdown); }
.hub-shell .nb-panel { border-radius: var(--radius-lg); border: 1px solid rgb(var(--line)); background: rgb(var(--surface)); box-shadow: var(--shadow-md); }

/* ---- Sub-nav (the Performance tab strip): segmented above md, a chip row below ------------- */
.hub-shell .page-tabs { padding: 0.75rem 1rem 0; border-bottom: 0; background: transparent; }
@media (min-width: 48rem) { .hub-shell .page-tabs { padding: 1.5rem 2rem 0; max-width: var(--page-max); } }
.hub-shell .page-tabs[hidden] { display: none; }
.hub-shell .pt-row { position: static; top: auto; z-index: auto; border: 0; display: inline-flex; max-width: 100%; overflow-x: auto; gap: 0.125rem; padding: 0.125rem; border-radius: var(--radius-lg); background: rgb(var(--surface-2)); scrollbar-width: none; }
.hub-shell .pt-row::-webkit-scrollbar { display: none; }
.hub-shell .pt-tab { display: inline-flex; align-items: center; gap: 0.375rem; flex: none; height: 1.75rem; padding: 0 0.75rem; white-space: nowrap;
  border: 0; border-radius: var(--radius-md); background: transparent; font: 400 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg-muted)); cursor: pointer;
  transition: color var(--duration-fast), background-color var(--duration-fast); }
.hub-shell .pt-tab:hover { color: rgb(var(--fg)); }
.hub-shell .pt-tab.active { background: rgb(var(--surface-3)); color: rgb(var(--fg)); font-weight: 500; box-shadow: var(--shadow-xs); border-bottom-color: transparent; }
.hub-shell .pt-tab .nb-count { margin-left: 0; }
@media (max-width: 47.99rem) {
  .hub-shell .page-tabs { padding: 0; border-bottom: 1px solid rgb(var(--line)); background: rgb(var(--bg)); }
  .hub-shell .pt-row { display: flex; gap: 0.375rem; padding: 0.5rem 1rem; border-radius: 0; background: transparent; }
  .hub-shell .pt-tab { height: auto; padding: 0.375rem 0.75rem; border-radius: var(--radius-full); background: rgb(var(--surface-2)); }
  .hub-shell .pt-tab.active { background: rgb(var(--surface-3)); box-shadow: none; }
}
/* The old crumb row under the header is retired: the trail lives in the page header now. */
.hub-shell .sub-header { display: none !important; }

/* ---- Page header: breadcrumb line, h1, italic summary, actions right ----------------------- */
/* (#crumbs, .pt-row and the bottom tabs are <nav>s; index.html's old top-nav `nav {}` rule still gives every nav
   a sticky position, a 28px gutter and a hairline, so each resets those.) */
.hub-shell .hub-crumbs { position: static; top: auto; z-index: auto; padding: 0; border: 0; background: transparent; overflow: visible;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; margin: 0 0 0.75rem; min-width: 0;
  font: 400 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg-muted)); white-space: normal; }
.hub-shell .hub-crumbs:empty { display: none; }
.hub-shell .hub-crumbs .crumb-home, .hub-shell .hub-crumbs .crumb-grp-btn { display: inline-flex; align-items: center; gap: 0.1875rem; padding: 0; border: 0; background: none;
  font: inherit; color: rgb(var(--fg-muted)); cursor: pointer; }
.hub-shell .hub-crumbs .crumb-home:hover, .hub-shell .hub-crumbs .crumb-grp-btn:hover, .hub-shell .hub-crumbs .crumb-grp-btn[aria-expanded="true"] { color: rgb(var(--fg)); text-decoration: underline; text-underline-offset: 0.2em; }
.hub-shell .hub-crumbs .crumb-home:focus-visible, .hub-shell .hub-crumbs .crumb-grp-btn:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: 2px; border-radius: var(--radius-sm); }
.hub-shell .hub-crumbs .crumb-sep { font-size: 0; color: rgb(var(--fg-faint)); }
.hub-shell .hub-crumbs .crumb-sep::before { content: "/"; font-size: 0.875rem; }
.hub-shell .hub-crumbs .crumb-page { color: rgb(var(--fg)); font-weight: 500; }
.hub-shell .hub-crumbs .crumb-grp-btn .crumb-chev { width: 0.75rem; height: 0.75rem; color: rgb(var(--fg-faint)); }
/* ‹ › are keyboard shortcuts now ([ and ]); the buttons stay in the DOM for the handler to click. */
.hub-shell .hub-crumbs .crumb-nav { display: none; }
@media (max-width: 47.99rem) {
  /* Below md only "← Group" (or "← Home" for a page with no group). */
  .hub-shell .hub-crumbs .crumb-sep, .hub-shell .hub-crumbs .crumb-page, .hub-shell .hub-crumbs .crumb-grp-btn:not(.crumb-grp-last), .hub-shell .hub-crumbs .crumb-home { display: none; }
  .hub-shell .hub-crumbs .crumb-grp-btn.crumb-grp-last::before, .hub-shell .hub-crumbs:not(:has(.crumb-grp-btn)) .crumb-home::before { content: "\2190"; margin-right: 0.25rem; }
  .hub-shell .hub-crumbs:not(:has(.crumb-grp-btn)) .crumb-home { display: inline-flex; }
  .hub-shell .hub-crumbs .crumb-grp-btn.crumb-grp-last .crumb-chev { display: none; }
}
/* The existing .eyebrow (icon badge + h1 + right note) and .sec-lead, restyled to the hub header. */
.hub-shell .section > .eyebrow { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem 0.75rem; margin: 0 0 0.125rem; }
.hub-shell .section > .eyebrow .idx { display: none; }
.hub-shell .section > .eyebrow h1 { font: 700 1.5rem/2rem var(--font-display); letter-spacing: -0.02em; color: rgb(var(--fg)); text-wrap: balance; }
.hub-shell .section > .eyebrow .note { margin-left: auto; font: 400 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg-muted)); }
.hub-shell .section > .sec-lead { margin: 0 0 1.5rem; font: italic 400 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg-muted)); max-width: var(--prose-max); }
.hub-shell .section > .sec-lead strong { color: rgb(var(--fg)); font-weight: 500; }
.hub-shell .section > .sec-lead .ph-info > summary { font-style: normal; font-weight: 500; color: rgb(var(--fg)); border-bottom-color: rgb(var(--line-strong)); }
.hub-shell .section > .sec-lead .ph-body { font-style: normal; font-size: 0.875rem; line-height: 1.5; border-radius: var(--radius-lg); }
.hub-shell .section > .sec-lead .ph-body h4 { font: 600 0.75rem/1rem var(--font-sans); letter-spacing: 0.04em; text-transform: uppercase; color: rgb(var(--fg-faint)); }
/* The Home page header (greeting) keeps its own shape. */
.hub-shell #sec-home > .hub-crumbs { display: none; }

/* ---- Content column below md: room for the bottom tab bar ------------------------------- */
@media (max-width: 47.99rem) {
  .hub-shell > .main-col { padding-bottom: calc(4rem + env(safe-area-inset-bottom, 0px)); }
}
/* Footer: quiet, same gutter as the page. */
.hub-shell .app-foot { margin-top: auto; padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px)); border-top: 1px solid rgb(var(--line));
  font: 400 0.75rem/1rem var(--font-sans); color: rgb(var(--fg-faint)); background: transparent; }
@media (min-width: 48rem) { .hub-shell .app-foot { padding-left: 2rem; padding-right: 2rem; } }
.hub-shell .app-foot .foot-brand { font-weight: 500; color: rgb(var(--fg-muted)); }
.hub-shell .app-foot .brand-sub { font-family: var(--font-sans); letter-spacing: 0.04em; color: rgb(var(--fg-faint)); }
.hub-shell .app-foot .status-pill { font-family: var(--font-sans); font-size: 0.75rem; }

/* ---- Bottom tab bar (below md): Home, two most-opened tools, Feedback, More ------------- */
.hub-bottom-tabs { display: none; }
@media (max-width: 47.99rem) {
  .hub-shell > .sidebar { display: none; }
  .hub-bottom-tabs { position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: var(--z-header); display: grid; grid-template-columns: repeat(5, 1fr); overflow: visible;
    padding: 0 0 env(safe-area-inset-bottom, 0px); background: rgb(var(--bg-sidebar)); border: 0; border-top: 1px solid rgb(var(--line)); font-family: var(--font-sans); }
  .hub-bottom-tabs button { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.125rem; min-width: 0; min-height: 3.5rem;
    padding: 0.5rem 0.25rem; border: 0; background: transparent; font: 500 0.6875rem/1rem var(--font-sans); letter-spacing: normal; text-transform: none; color: rgb(var(--fg-muted)); cursor: pointer;
    transition: color var(--duration-fast), background-color var(--duration-fast); }
  .hub-bottom-tabs button svg { width: 1.25rem; height: 1.25rem; }
  .hub-bottom-tabs button span { max-width: 100%; padding: 0 0.125rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .hub-bottom-tabs button[aria-current="page"] { color: rgb(var(--fg)); font-weight: 600; background: rgb(var(--designboom-subtle)); }
  .hub-bottom-tabs button[aria-current="page"] svg { color: rgb(var(--fg)); }
  .hub-bottom-tabs .hub-tab-dot { position: absolute; top: 0.5rem; right: calc(50% - 0.875rem); width: 0.5rem; height: 0.5rem; border-radius: var(--radius-full); background: rgb(var(--designboom-solid)); box-shadow: 0 0 0 1px rgb(var(--line-strong)); }
  /* "More" opens the sidebar as a full-screen sheet with a scrim; Escape closes it. */
  .hub-shell > .sidebar.open { display: flex; position: fixed; left: 0; right: 0; bottom: 0; top: max(3rem, 8dvh); width: auto; height: auto; max-height: none; flex-basis: auto; z-index: var(--z-modal);
    border-right: 0; border-top: 1px solid rgb(var(--line)); border-radius: var(--radius-xl) var(--radius-xl) 0 0; transform: none; box-shadow: var(--shadow-lg);
    padding-bottom: env(safe-area-inset-bottom, 0px); animation: hub-sheet-in var(--duration-base) ease-out; }
  .hub-shell > .sidebar.open::before { content: ""; display: block; flex: none; width: 2.25rem; height: 0.25rem; margin: 0.5rem auto 0; border-radius: var(--radius-full); background: rgb(var(--line-strong)); }
  .hub-shell > .sidebar.open .side-brand { align-items: center; }
  .hub-shell > .sidebar.open .rail-toggle { display: none; }
  .hub-shell > .sidebar.open .hub-sheet-close { display: inline-flex; }
  .hub-shell > .sidebar.open .side-nav .nb.active { background: rgb(var(--designboom-subtle)); }
  .hub-shell > .sidebar.open .side-nav .nb.active::before { left: -0.5rem; }
  .hub-shell > .sidebar.open .side-nav .nb { min-height: 2.75rem; }
}
.hub-sheet-close { display: none; align-items: center; justify-content: center; flex: none; width: 2.75rem; height: 2.75rem; border: 0; border-radius: var(--radius-md);
  background: transparent; color: rgb(var(--fg-muted)); cursor: pointer; }
.hub-sheet-close:hover { background: rgb(var(--surface-2)); color: rgb(var(--fg)); }

/* =============================================================================================
   OVERLAYS: modal, drawer, sheet, toast. Modal and drawer render as a bottom sheet below md.
   Structure (JS builds it, or write it by hand):
     <div class="hub-modal" role="dialog" aria-modal="true" aria-labelledby="...">
       <div class="hub-modal-panel">
         <div class="hub-ov-head"><h2 class="hub-ov-title">Title</h2><button class="hub-modal-x" aria-label="Close">x</button></div>
         <div class="hub-ov-body">...</div>
         <div class="hub-ov-foot"><button class="btn btn-secondary">Cancel</button><button class="btn btn-primary">Save</button></div>
   Footer: secondary left, primary right (the primary carries margin-left:auto).
   ============================================================================================= */
@keyframes hub-sheet-in { from { transform: translateY(1rem); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes hub-fade-in { from { opacity: 0; } to { opacity: 1; } }
.hub-scrim, .hub-modal, .hub-drawer { position: fixed; inset: 0; z-index: var(--z-overlay); background: rgb(var(--overlay) / var(--overlay-alpha));
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px); animation: hub-fade-in var(--duration-fast) ease-out; }
.hub-scrim[hidden], .hub-modal[hidden], .hub-drawer[hidden], .hub-sheet[hidden] { display: none; }
.hub-modal, .hub-drawer { z-index: var(--z-modal); }
.hub-modal { display: flex; align-items: center; justify-content: center; padding: 1rem; }
.hub-modal-panel { width: 100%; max-width: 32rem; max-height: 90vh; max-height: 90dvh; overflow: auto; display: flex; flex-direction: column;
  border: 1px solid rgb(var(--line)); border-radius: var(--radius-xl); background: rgb(var(--surface)); color: rgb(var(--fg)); box-shadow: var(--shadow-lg); outline: none; }
.hub-modal-panel.is-sm { max-width: 28rem; }
.hub-modal-panel.is-lg { max-width: 42rem; }
.hub-drawer-panel { position: absolute; top: 0; right: 0; bottom: 0; width: 100%; max-width: 36rem; display: flex; flex-direction: column; overflow: hidden;
  border-left: 1px solid rgb(var(--line)); background: rgb(var(--surface)); color: rgb(var(--fg)); box-shadow: var(--shadow-lg); outline: none;
  animation: hub-drawer-in var(--duration-base) ease-out; }
@keyframes hub-drawer-in { from { transform: translateX(1rem); opacity: 0; } to { transform: none; opacity: 1; } }
.hub-ov-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex: none; padding: 1.25rem 1.5rem; border-bottom: 1px solid rgb(var(--line)); }
.hub-ov-title { margin: 0; font: 600 1.125rem/1.75rem var(--font-sans); letter-spacing: -0.01em; color: rgb(var(--fg)); }
.hub-ov-sub { margin: 0.125rem 0 0; font: italic 400 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg-muted)); }
.hub-modal-x { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 2rem; height: 2rem; margin-right: -0.5rem; border: 0; border-radius: var(--radius-md);
  background: transparent; color: rgb(var(--fg-faint)); cursor: pointer; font-size: 1rem; line-height: 1; }
.hub-modal-x:hover { background: rgb(var(--surface-2)); color: rgb(var(--fg)); }
.hub-ov-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 1.5rem; font-size: 0.875rem; line-height: 1.25rem; scroll-padding-top: 1rem; }
.hub-ov-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; flex: none; padding: 1rem 1.5rem 1.5rem; }
.hub-ov-foot > .btn-primary, .hub-ov-foot > .hub-foot-end { margin-left: auto; }
.hub-ov-foot.has-line { border-top: 1px solid rgb(var(--line)); padding-top: 1rem; }
/* Standalone sheet (filters, More): bottom anchored below md; a centered modal panel above it. */
.hub-sheet { position: fixed; inset: 0; z-index: var(--z-modal); display: flex; align-items: center; justify-content: center; padding: 1rem;
  background: rgb(var(--overlay) / var(--overlay-alpha)); animation: hub-fade-in var(--duration-fast) ease-out; }
.hub-sheet-panel { width: 100%; max-width: 32rem; max-height: 90dvh; display: flex; flex-direction: column; overflow: hidden;
  border: 1px solid rgb(var(--line)); border-radius: var(--radius-xl); background: rgb(var(--surface)); color: rgb(var(--fg)); box-shadow: var(--shadow-lg); outline: none; }
@media (max-width: 47.99rem) {
  .hub-modal, .hub-sheet { align-items: flex-end; padding: 0; }
  .hub-modal-panel, .hub-drawer-panel, .hub-sheet-panel { position: fixed; left: 0; right: 0; bottom: 0; top: auto; width: auto; max-width: none; max-height: 92dvh;
    border: 0; border-top: 1px solid rgb(var(--line)); border-radius: var(--radius-xl) var(--radius-xl) 0 0; box-shadow: var(--shadow-lg);
    padding-bottom: env(safe-area-inset-bottom, 0px); animation: hub-sheet-in var(--duration-base) ease-out; }
  .hub-modal-panel::before, .hub-drawer-panel::before, .hub-sheet-panel::before { content: ""; display: block; flex: none; width: 2.25rem; height: 0.25rem; margin: 0.5rem auto 0;
    border-radius: var(--radius-full); background: rgb(var(--line-strong)); }
  .hub-ov-head { padding: 0.75rem 1rem; }
  .hub-modal-x { width: 2.75rem; height: 2.75rem; margin-right: -0.75rem; }   /* a 44px close on a phone; the head has the room */
  .hub-ov-body { padding: 1rem; }
  .hub-ov-foot { padding: 0.75rem 1rem 1rem; }
  .hub-ov-foot .btn { min-height: 2.75rem; }
}

/* ---- Toasts (G7): one region, four tones, live ------------------------------------------- */
.hub-toast-region { position: fixed; right: 1rem; bottom: 1rem; z-index: var(--z-toast); display: flex; flex-direction: column; align-items: flex-end; gap: 0.5rem;
  width: min(24rem, calc(100vw - 2rem)); pointer-events: none; }
@media (max-width: 47.99rem) { .hub-toast-region { left: 50%; right: auto; transform: translateX(-50%); bottom: calc(6rem + env(safe-area-inset-bottom, 0px)); align-items: stretch; } }
/* While a drawer is open the bottom-right corner is its footer (the primary action lives there), so the
   toasts move out of its way: bottom-left above md, under the top bar below it. */
/* Above md the toasts stay in the drawer's own column, above its footer; below md the drawer is a
   full-height sheet, so the toasts sit under its header. hub.js measures the open drawer's footer
   height and header bottom into --hub-drawer-foot-h and --hub-drawer-head-b (whatever the title
   wraps to, whichever footer is showing), so nothing sits over a footer button at any width. */
@media (min-width: 48rem) { body:has(.hub-drawer:not([hidden])) .hub-toast-region { bottom: calc(var(--hub-drawer-foot-h, 4.75rem) + 0.75rem); width: min(24rem, 36rem - 2rem); } }
@media (max-width: 47.99rem) {
  body:has(.hub-drawer:not([hidden])) .hub-toast-region { left: 50%; right: auto; top: calc(var(--hub-drawer-head-b, calc(max(3rem, 8dvh) + 5.75rem)) + 0.5rem); bottom: auto; align-items: stretch; }
  /* A bulk bar sits above the tab bar on phones; the toasts stack above it rather than on it. */
  body:has(.hub-bulkbar:not([hidden])) .hub-toast-region { bottom: calc(10rem + env(safe-area-inset-bottom, 0px)); }
}
.hub-toast { pointer-events: auto; display: flex; align-items: flex-start; gap: 0.625rem; width: 100%; padding: 0.75rem 0.75rem 0.75rem 1rem;
  border: 1px solid rgb(var(--line)); border-left-width: 3px; border-radius: var(--radius-xl); background: rgb(var(--surface)); color: rgb(var(--fg)); box-shadow: var(--shadow-lg);
  font: 400 0.875rem/1.25rem var(--font-sans); animation: hub-sheet-in var(--duration-base) ease-out; }
.hub-toast.is-leaving { opacity: 0; transform: translateY(0.25rem); transition: opacity var(--duration-base), transform var(--duration-base); }
.hub-toast-msg { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.hub-toast-x { flex: none; width: 1.5rem; height: 1.5rem; margin: -0.125rem -0.125rem 0 0; border: 0; border-radius: var(--radius-sm); background: transparent; color: rgb(var(--fg-faint)); cursor: pointer; font-size: 0.875rem; line-height: 1; }
.hub-toast-x:hover { color: rgb(var(--fg)); background: rgb(var(--surface-2)); }
.hub-toast-action { flex: none; align-self: center; }
.hub-toast-info { border-left-color: rgb(var(--info)); }
.hub-toast-success { border-left-color: rgb(var(--success)); }
.hub-toast-warning { border-left-color: rgb(var(--warning)); }
.hub-toast-danger { border-left-color: rgb(var(--danger)); }
.hub-toast-neutral { border-left-color: rgb(var(--fg)); }

/* ---- Empty, error and loading states (G8) ------------------------------------------------- */
.hub-empty { display: flex; flex-direction: column; align-items: center; gap: 0.375rem; padding: 2.5rem 1.5rem; text-align: center;
  border: 1px solid rgb(var(--line)); border-radius: var(--radius-lg); background: rgb(var(--surface)); grid-column: 1 / -1; }
.hub-empty-mark { display: flex; align-items: center; justify-content: center; width: 2rem; height: 2rem; margin-bottom: 0.25rem; border-radius: var(--radius-full);
  background: rgb(var(--surface-2)); color: rgb(var(--fg-faint)); font: 500 1rem/1 var(--font-sans); }
.hub-empty-title { margin: 0; font: 500 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg)); }
.hub-empty-body { margin: 0; max-width: 46ch; font: 400 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg-muted)); }
.hub-empty .btn { margin-top: 0.5rem; }
.hub-empty.is-error { border-color: rgb(var(--danger) / 0.3); background: rgb(var(--danger-subtle)); }
.hub-empty.is-error .hub-empty-mark { background: rgb(var(--surface)); color: rgb(var(--danger)); }
@keyframes hub-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
.hub-skeleton { display: block; border-radius: var(--radius-md); background: rgb(var(--surface-2)); animation: hub-pulse 1.4s ease-in-out infinite; }
.hub-skeleton.is-row { height: 2.5rem; }
.hub-skeleton.is-card { height: 7rem; border-radius: var(--radius-lg); }
@media (prefers-reduced-motion: reduce) { .hub-skeleton { animation: none; } }

/* ---- Framed external preview (section 5.3): the one place designboom's page styles live inside
   the tool. The inner scope pins the light theme whatever the app is in. Not applied yet. ---- */
.ext-frame { display: flex; flex-direction: column; overflow: hidden; border: 1px solid rgb(var(--line)); border-radius: var(--radius-lg); background: rgb(var(--surface)); }
.ext-frame-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.5rem 0.75rem; border-bottom: 1px solid rgb(var(--line)); background: rgb(var(--surface-2)); }
.ext-frame-head .overline::before { content: "Client preview \00b7 designboom"; }
.ext-frame-body { flex: 1 1 auto; min-height: 0; color-scheme: light; background: rgb(var(--bg)); color: rgb(var(--fg)); }
.ext-frame-body > iframe { display: block; width: 100%; border: 0; background: rgb(var(--surface)); }

/* =============================================================================================
   COLLECTIONS (Step 3, audit G1 G2 G3 G8 G10 G11): the search field, the filter bar with its
   chips and its phone sheet, the card grid, the bulk bar, the confirm dialog and the state
   blocks. hub.js mounts the behavior (Hub.search, Hub.filterbar, Hub.table, Hub.view, Hub.bulk,
   Hub.overlay.confirm, Hub.state). docs/hub-migration/README.md section 12 is the reference.
   ============================================================================================= */

/* ---- Search field (G1): icon left, clear right, 2.75rem and 1rem type below md ------------- */
.hub-search { position: relative; display: flex; align-items: center; flex: 1 1 16rem; min-width: 0; max-width: 28rem; }
.hub-search > .hub-search-icon { position: absolute; left: 0.625rem; width: 1rem; height: 1rem; color: rgb(var(--fg-faint)); pointer-events: none; }
.hub-search > .field { padding-left: 2rem; padding-right: 2.25rem; }
.hub-search > .field::-webkit-search-cancel-button, .hub-search > .field::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.hub-search-clear { position: absolute; right: 0.25rem; display: inline-flex; align-items: center; justify-content: center; width: 1.5rem; height: 1.5rem; min-height: 0; padding: 0;
  border: 0; border-radius: var(--radius-sm); background: transparent; color: rgb(var(--fg-faint)); cursor: pointer; }
.hub-search-clear:hover { color: rgb(var(--fg)); background: rgb(var(--surface-2)); }
.hub-search-clear[hidden] { display: none; }
.hub-search-clear svg { width: 0.875rem; height: 0.875rem; }
.hub-search-count { font: 400 0.75rem/1rem var(--font-sans); color: rgb(var(--fg-muted)); }
.hub-kbd { display: inline-flex; align-items: center; height: 1.125rem; padding: 0 0.3125rem; border: 1px solid rgb(var(--line)); border-radius: var(--radius-sm); background: rgb(var(--surface-2));
  font: 500 0.6875rem/1 var(--font-sans); letter-spacing: 0.02em; color: rgb(var(--fg-muted)); cursor: default; }
button.hub-kbd { cursor: pointer; min-height: 0; }
button.hub-kbd:hover { color: rgb(var(--fg)); border-color: rgb(var(--line-strong)); }
@media (max-width: 47.99rem) {
  .hub-search { flex-basis: 100%; max-width: none; }
  .hub-search-clear { width: 2.25rem; height: 2.25rem; right: 0.25rem; }
}

/* ---- Filter bar (G2): [search][filters][sort][view], chips beneath, a Filters sheet below md - */
.hub-filterbar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0 0 0.75rem; font-family: var(--font-sans); }
.hub-filterbar > .field, .hub-filterbar-filters > .field, .hub-filterbar-end > .field { width: auto; min-width: 0; max-width: 100%; }
.hub-filterbar-filters { display: contents; }
.hub-filterbar-toggle { display: none; }
.hub-filterbar-end { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; }
.hub-filterbar-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 1.25rem; height: 1.25rem; padding: 0 0.375rem; border-radius: var(--radius-full);
  background: rgb(var(--primary)); color: rgb(var(--primary-fg)); font: 600 0.75rem/1 var(--font-sans); font-variant-numeric: tabular-nums; }
.hub-filterbar-badge[hidden] { display: none; }
.hub-filterbar-help { flex-basis: 100%; margin: -0.25rem 0 0; font: 400 0.75rem/1rem var(--font-sans); color: rgb(var(--fg-faint)); }
@media (max-width: 47.99rem) {
  .hub-filterbar-filters { display: none; }
  .hub-filterbar-toggle { display: inline-flex; }
  .hub-filterbar-end { flex: 1 1 auto; flex-wrap: wrap; margin-left: 0; justify-content: flex-end; min-width: 0; }
  .hub-filterbar-end > .field { flex: 1 1 10rem; min-width: 0; }   /* a select's intrinsic width may not fit beside the toggle at 360; it shrinks or the toggle wraps */
  .hub-filterbar-end > .seg { flex: none; max-width: 100%; }
}
/* The same controls inside the sheet: stacked, full width, labeled by their aria-label. */
.hub-filter-sheet .hub-filterbar-filters { display: flex; flex-direction: column; gap: 0.75rem; }
.hub-filter-sheet .hub-filterbar-filters > * { width: 100%; max-width: none; }
.hub-filter-sheet .hub-filter-lab { display: block; margin-bottom: 0.375rem; font: 500 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg)); }

/* ---- Chips: an active filter (removable, a button) or a static tag (a span) ---------------- */
.hub-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; margin: 0 0 0.75rem; font-family: var(--font-sans); }
.hub-chips:empty, .hub-chips[hidden] { display: none; }
.hub-chip { display: inline-flex; align-items: center; gap: 0.25rem; max-width: 100%; height: 1.75rem; min-height: 0; padding: 0 0.625rem; border: 1px solid transparent; border-radius: var(--radius-full);
  background: rgb(var(--surface-2)); color: rgb(var(--fg)); font: 500 0.75rem/1rem var(--font-sans); letter-spacing: normal; text-transform: none; text-decoration: none; cursor: default;
  transition: background-color var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast); }
.hub-chip > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hub-chip .hub-chip-k { color: rgb(var(--fg-muted)); font-weight: 400; }
.hub-chip .hub-chip-k::after { content: ":"; }
.hub-chip-x { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 1.25rem; height: 1.25rem; margin-right: -0.375rem; border-radius: var(--radius-full); color: rgb(var(--fg-muted)); }
.hub-chip-x svg { width: 0.75rem; height: 0.75rem; }
button.hub-chip, a.hub-chip { cursor: pointer; }
button.hub-chip:hover, a.hub-chip:hover { background: rgb(var(--surface-3)); }
button.hub-chip:hover .hub-chip-x { color: rgb(var(--fg)); }
button.hub-chip:disabled { opacity: 0.5; cursor: not-allowed; }
/* A toggle chip (aria-pressed) reads as the ink button when on. */
.hub-chip[aria-pressed="true"] { background: rgb(var(--primary)); color: rgb(var(--primary-fg)); }
.hub-chip[aria-pressed="true"] .hub-chip-k { color: inherit; }
.hub-chip.is-outline { background: transparent; border-color: rgb(var(--line)); color: rgb(var(--fg-muted)); }
.hub-chip.is-dashed { background: transparent; border: 1px dashed rgb(var(--line-strong)); color: rgb(var(--fg-muted)); }
.hub-chips-clear { margin-left: 0.25rem; }
@media (max-width: 47.99rem) {
  .hub-chip { height: 2.75rem; min-height: 2.75rem; padding: 0 0.875rem; font-size: 0.875rem; }
  .hub-chip-x { width: 2.25rem; height: 2.25rem; margin-right: -0.75rem; }
  .hub-chip-x svg { width: 1rem; height: 1rem; }
}

/* ---- Card grid (the card view of a collection) ------------------------------------------- */
.hub-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); gap: 1rem; font-family: var(--font-sans); }
.hub-cards > * { min-width: 0; }
.hub-cards > .card[role="button"], .hub-cards > .card.is-click { cursor: pointer; }
.hub-cards > .card[role="button"]:hover, .hub-cards > .card.is-click:hover { border-color: rgb(var(--line-strong)); background: rgb(var(--surface-2)); }
.hub-cards > .card[aria-selected="true"], .hub-cards > .card.is-selected { background: rgb(var(--surface-3)); border-color: rgb(var(--line-strong)); }
.hub-cards > .card a, .hub-cards > .card button, .hub-cards > .card label, .hub-cards > .card input { cursor: pointer; }
@media (max-width: 47.99rem) { .hub-cards { grid-template-columns: minmax(0, 1fr); gap: 0.75rem; } }
/* A whole-card control gets the ring like any other focusable. */
.card:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: 2px; }

/* ---- Bulk bar (G3): appears above the collection with the count and the actions ----------- */
.hub-bulkbar { position: sticky; top: calc(var(--header-h) + env(safe-area-inset-top, 0px) + 0.5rem); z-index: calc(var(--z-sticky) + 1); display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  margin: 0 0 0.75rem; padding: 0.5rem 0.75rem; border: 1px solid rgb(var(--line-strong)); border-radius: var(--radius-lg); background: rgb(var(--surface)); box-shadow: var(--shadow-md);
  font: 500 0.875rem/1.25rem var(--font-sans); color: rgb(var(--fg)); animation: hub-sheet-in var(--duration-base) ease-out; }
.hub-bulkbar[hidden] { display: none; }
.hub-bulkbar .hub-bulk-n { margin-right: auto; font-variant-numeric: tabular-nums; }
@media (max-width: 47.99rem) {
  .hub-bulkbar { position: fixed; top: auto; left: 0.75rem; right: 0.75rem; bottom: calc(4.25rem + env(safe-area-inset-bottom, 0px)); margin: 0; z-index: var(--z-dropdown); }
  .hub-bulkbar .btn { min-height: 2.75rem; }
}

/* ---- Overlay additions (G10, G11) --------------------------------------------------------- */
/* A drawer is a full-height sheet below md, so a footer stays at the foot while the body changes state. */
@media (max-width: 47.99rem) {
  .hub-drawer-panel { top: max(3rem, 8dvh); max-height: none; }
}
.hub-ov-head > .hub-ov-heading { min-width: 0; flex: 1 1 auto; }
.hub-ov-head .hub-ov-title { overflow-wrap: anywhere; }
.hub-ov-foot .btn { flex: none; }
.hub-modal-x svg { width: 1rem; height: 1rem; }
/* The confirm / alert / prompt dialog (Hub.overlay.confirm): the modal panel at 28rem, no divider,
   title and body only, the buttons on the right, the confirm solid danger when tone is danger. */
.hub-modal-panel.hub-dialog { max-width: 28rem; }
.hub-dialog .hub-ov-head { padding: 1.25rem 1.5rem 0; border-bottom: 0; align-items: flex-start; }
.hub-dialog .hub-ov-title { font-size: 1rem; line-height: 1.5rem; }
.hub-dialog .hub-ov-body { padding: 0.5rem 1.5rem 0; color: rgb(var(--fg-muted)); white-space: pre-wrap; }
.hub-dialog .hub-ov-body:empty { display: none; }
.hub-dialog textarea.field { margin-top: 0.75rem; min-height: 4.5rem; color: rgb(var(--fg)); }
.hub-dialog .hub-ov-foot { justify-content: flex-end; padding: 1.25rem 1.5rem 1.5rem; }
.hub-dialog .hub-ov-foot > .btn-primary, .hub-dialog .hub-ov-foot > .btn-danger { margin-left: 0; }

/* ---- States (G8): additions to .hub-empty and .hub-skeleton --------------------------------- */
.hub-empty { font-family: var(--font-sans); }
.hub-empty-mark svg { width: 1rem; height: 1rem; }
.hub-empty .btn { margin-top: 0.5rem; }
.hub-empty.is-plain, .tcard > .hub-empty, .pl-col > .hub-empty, .cd-boot.is-plain > .hub-empty { border: 0; background: none; }
/* A framed empty or error block with something under it keeps the page rhythm: a state block standing in for a list
   used to sit flush on the next card (House Banners' "No house banners yet" on Settings, 2026-10-01). */
.hub-empty:not(:last-child):not(.is-plain) { margin-bottom: 1rem; }
.hub-empty[role="alert"] { text-align: center; }
.hub-skeletons { display: grid; gap: 0.5rem; }
.hub-skeletons.is-cards { grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); gap: 1rem; }
.hub-skeletons.is-cards .hub-skeleton { height: 11rem; }
@media (max-width: 47.99rem) { .hub-skeletons.is-cards { grid-template-columns: minmax(0, 1fr); gap: 0.75rem; } }
.hub-skeleton.is-line { height: 1rem; width: 60%; }
.hub-skeleton.is-line.is-short { width: 35%; }
.hub-skeleton.is-block { height: 5rem; }
[aria-busy="true"] > .hub-skeletons { pointer-events: none; }

/* =============================================================================================
   POLISH ROUND, 2026-09-30 (Timo's list after the migration). Shared rules only; each module's own
   fixes stay in its style block.
   ============================================================================================= */

/* ---- The page grows with the screen: no 1440px cap, a 1920px ceiling so a line of prose or a
   table never runs the width of a 27-inch display. The sidebar and gutters take the rest. ------- */
.hub-shell .page { max-width: 120rem; width: 100%; box-sizing: border-box; }
@media (min-width: 48rem) { .hub-shell .page-tabs { max-width: 120rem; } }

/* ---- "designboom hub" as type (the brand-lockup span; the yellow SVG badge is retired) --------- */
.hub-shell .brand-word { display: none; }
.hub-shell .brand-text { font: 600 0.9375rem/1.25rem var(--font-sans); letter-spacing: -0.01em; color: rgb(var(--fg)); white-space: nowrap; }
.hub-shell .brand-text .brand-hub { font-weight: 400; color: rgb(var(--fg-muted)); }
.hub-shell header.hub-topbar .hdr-brand { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0.375rem; margin-left: -0.375rem; border-radius: var(--radius-md); }
.hub-shell header.hub-topbar .hdr-brand:hover { background: rgb(var(--surface-2)); }
.hub-shell header.hub-topbar .hdr-brand > svg { display: none; }

/* ---- The ClickUp top bar: full width over sidebar and page, three columns ----------------------
   left: sidebar toggle · designboom hub · Newsroom/Showroom   middle: search   right: Feedback · bell · avatar */
.hub-shell .hub-top-left { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.hub-shell header.hub-topbar .hub-top-left .ws-seg { display: none; }
.hub-shell .hub-sidebar-user { display: none; }
.hub-shell header.hub-topbar .rail-toggle { display: none; }
@media (min-width: 48rem) {
  .hub-shell { padding-top: calc(var(--header-h) + env(safe-area-inset-top, 0px)); }
  .hub-shell header.hub-topbar { position: fixed; top: var(--viewas-h, 0px); left: 0; right: 0;
    display: grid; grid-template-columns: 1fr minmax(12rem, 40rem) 1fr; gap: 1rem;
    padding-left: 0.75rem; padding-right: 1rem; background: rgb(var(--bg-sidebar)); -webkit-backdrop-filter: none; backdrop-filter: none; }
  .hub-shell header.hub-topbar .header-end { display: contents; }
  .hub-shell header.hub-topbar .hub-top-left { grid-column: 1; min-width: max-content; }
  .hub-shell header.hub-topbar .header-search { grid-column: 2; width: 100%; max-width: none; justify-self: stretch; }
  .hub-shell header.hub-topbar .header-right { grid-column: 3; justify-self: end; gap: 0.5rem; }
  .hub-shell header.hub-topbar .rail-toggle { display: inline-flex; }
  .hub-shell header.hub-topbar .hub-top-left .ws-seg { display: inline-flex; flex: none; margin: 0 0 0 0.25rem; padding: 0.125rem; gap: 0.125rem; border: 0;
    border-radius: var(--radius-lg); background: rgb(var(--surface-2)); }
  .hub-shell header.hub-topbar .hub-top-left .ws-seg[hidden] { display: none; }
  .hub-shell header.hub-topbar .hub-top-left .ws-seg button { height: 1.75rem; padding: 0 0.75rem; border: 0; border-radius: var(--radius-md); background: transparent;
    font: 400 0.8125rem/1.25rem var(--font-sans); letter-spacing: normal; text-transform: none; color: rgb(var(--fg-muted)); box-shadow: none; cursor: pointer; }
  .hub-shell header.hub-topbar .hub-top-left .ws-seg button:hover { color: rgb(var(--fg)); }
  .hub-shell header.hub-topbar .hub-top-left .ws-seg button[aria-pressed="true"] { background: rgb(var(--surface)); color: rgb(var(--fg)); font-weight: 500; box-shadow: var(--shadow-xs); }
  .hub-shell header.hub-topbar .hub-top-left .ws-seg button:focus-visible { outline: 2px solid rgb(var(--ring)); outline-offset: 2px; }
  /* The sidebar starts under the bar; its own brand row and switch are the top bar's now. */
  .hub-shell > .sidebar { top: calc(var(--header-h) + env(safe-area-inset-top, 0px) + var(--viewas-h, 0px));
    height: calc(100dvh - var(--header-h) - env(safe-area-inset-top, 0px) - var(--viewas-h, 0px)); }
  .hub-shell > .sidebar .side-brand, .hub-shell > .sidebar .ws-seg { display: none; }
  .hub-shell .side-nav { padding-top: 0.5rem; }
  /* The avatar, top right: a 2rem round button, the menu drops down from it. */
  .hub-shell header.hub-topbar .header-right .um-btn { width: 2rem; height: 2rem; padding: 0; border-radius: var(--radius-full); }
  .hub-shell header.hub-topbar .header-right .um-btn .um-fallback { width: 1.75rem; height: 1.75rem; padding: 0.25rem; border-radius: var(--radius-full); background: rgb(var(--surface-3)); color: rgb(var(--fg-muted)); }
  .hub-shell header.hub-topbar .header-right .um-btn:has(.side-user-av[src]) .um-fallback { display: none; }
}
/* Below 60rem the search narrows and the wordmark drops "hub" so the room switch keeps its place. */
@media (min-width: 48rem) and (max-width: 59.99rem) {
  /* The switch stays in the bar (the sidebar is the auto rail here and hides its own copy); the search gives way. */
  .hub-shell header.hub-topbar { grid-template-columns: auto minmax(8rem, 1fr) auto; }
  .hub-shell header.hub-topbar .brand-text .brand-hub { display: none; }
}
/* Search placeholder: the rotating "Try: …" line fits the wider field; keep it on one line. */
.hub-shell .header-ask { text-overflow: ellipsis; }

/* ---- ⌘K: the palette is the focus context, so its input carries no ring of its own (the blue
   frame read as a bug in both themes). The caret and the palette border say where you are. ------ */
.cmdk-input:focus, .cmdk-input:focus-visible { outline: none; box-shadow: none; }

/* ---- Stacked cards: charts.css's `.card + .card` is scoped to the data pages now. These six pages
   stack cards in plain flow and kept the same 1rem; grids of cards (Home, IRL, Comebacks) line up. */
:is(#sec-planner, #sec-articlelab, #sec-storydesk, #sec-clientdesk, #sec-team, #sec-users) .card + .card { margin-top: 1rem; }

/* ---- The Performance tab strip wraps above md instead of running off the right edge (it held
   fourteen tabs in one scrolling row with no cue, so half of them were simply invisible). ------ */
@media (min-width: 48rem) {
  .hub-shell .pt-row { display: flex; flex-wrap: wrap; width: fit-content; overflow: visible; row-gap: 0.125rem; }
}

/* ---- Who sees this: one marker for content only admins (or leaders) see, the same everywhere
   (2026-09-30, Timo: "make sure it's clear what only admins/leaders can see vs everyone"). ----- */
.hub-aud { display: inline-flex; align-items: center; gap: 0.25rem; margin-left: 0.5rem; padding: 0 0.4375rem; border: 1px dashed rgb(var(--line-strong)); border-radius: var(--radius-full);
  font: 500 0.6875rem/1.125rem var(--font-sans); letter-spacing: 0.01em; text-transform: none; color: rgb(var(--fg-muted)); background: transparent; white-space: nowrap; vertical-align: middle; }
.hub-aud::before { content: ""; width: 0.625rem; height: 0.625rem; flex: none; background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='11' width='16' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='4' y='11' width='16' height='10' rx='2'/%3E%3Cpath d='M8 11V7a4 4 0 0 1 8 0v4'/%3E%3C/svg%3E") center / contain no-repeat; }

/* ---- Chart tips (hub.js, 2026-09-30): the value under the pointer, at once, styled like Chart.js's tooltip. */
.hub-tip { position: fixed; z-index: var(--z-toast); pointer-events: none; max-width: 18rem; padding: 0.375rem 0.625rem; border: 1px solid rgb(var(--line));
  border-radius: var(--radius-md); background: rgb(var(--surface)); color: rgb(var(--fg)); box-shadow: var(--shadow-md);
  font: 500 0.75rem/1rem var(--font-sans); font-variant-numeric: tabular-nums; white-space: pre-line; }
.hub-tip[hidden] { display: none; }
.ch-bars > span:hover, .hub-tip-zone > div:hover > div, .hub-bar > div:hover { filter: brightness(1.15); }

/* ---- A drawer that holds a wide table asks for room (openDrawer({ wide:true }), 2026-09-30). -- */
@media (min-width: 48rem) { #drawer.is-wide .hub-drawer-panel { max-width: min(64rem, 92vw); } }
#drawer.is-wide .table-wrap { overflow-x: auto; }
#drawer.is-wide .table-wrap td:first-child { min-width: 14rem; }

/* ---- A table wider than its card shows it (2026-09-30, "cut off, no scroll horizontal available"): the
   classic scroll shadows, local backgrounds that cover the edge shadow until there is more to scroll to. */
.hub-scroll-x { overflow-x: auto;
  background:
    linear-gradient(to right, rgb(var(--surface)) 30%, rgb(var(--surface) / 0)) left center / 2.5rem 100% no-repeat local,
    linear-gradient(to left, rgb(var(--surface)) 30%, rgb(var(--surface) / 0)) right center / 2.5rem 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgb(var(--shadow-color) / 0.16), transparent) left center / 0.75rem 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgb(var(--shadow-color) / 0.16), transparent) right center / 0.75rem 100% no-repeat scroll; }
.hub-scroll-x table { background: transparent; }

/* ---- Full-screen views instead of right-side drawers (2026-09-30, Timo: "i really don't like these right side pop-ups.
   can we not just have a full screen pop up with a url that we could copy so that we can share this exact example?").
   Every .hub-drawer (and the shared #drawer) opens as a large centered view from md up; below md it stays the full-height
   sheet it already was. The markup, ids, focus trap and Escape are unchanged; only the geometry moved. A Copy link button
   joins the header whenever the address names the item (hub.js, Hub.shareLink). */
/* Scoped to the app (body:has(.app.hub-shell); the Image Tool and Lightbox are their own pages and keep their side drawer) and not the
   Article Lab rail, which is a tool beside the draft rather than a detail to open. Two ids of weight so a module's own
   panel max-width (.pb-dw 40rem, .oc-drawer 38rem, #vsDiff 56rem, and the drawers built in script) cannot turn the
   view back into a narrow column. Centered with margin-inline, not a transform, so a fixed child still positions
   against the viewport. */
@media (min-width: 48rem) {
  body:has(.app.hub-shell) .hub-drawer:not(#al-rail-host) .hub-drawer-panel {
    top: 1.5rem; bottom: 1.5rem; left: 0; right: 0; margin-inline: auto; width: min(72rem, calc(100vw - 3rem)); max-width: none !important;
    border: 1px solid rgb(var(--line)); border-radius: var(--radius-xl); animation: hub-view-in var(--duration-base) ease-out; }
  body:has(.app.hub-shell) .hub-drawer:not(#al-rail-host) .hub-ov-body { padding: 1.75rem 2rem; }
  body:has(.app.hub-shell) .hub-drawer:not(#al-rail-host) .hub-ov-head { padding: 1.25rem 2rem; }
  body:has(.app.hub-shell) .hub-drawer:not(#al-rail-host) .hub-ov-foot { padding-left: 2rem; padding-right: 2rem; }
  body:has(.app.hub-shell):has(.hub-drawer:not([hidden]):not(#al-rail-host)) .hub-toast-region { width: min(24rem, calc(100vw - 2rem)); bottom: calc(var(--hub-drawer-foot-h, 4.75rem) + 1.5rem + 0.75rem); }
}
@keyframes hub-view-in { from { opacity: 0; transform: translateY(0.5rem); } to { opacity: 1; transform: none; } }
.hub-ov-share { flex: none; margin-left: auto; }
.hub-ov-share[hidden] { display: none; }
