/* ContextBase UI - Notion + Airtable + Linear inspired. Layers: base, components, utilities. */
@layer base, components, utilities;

@layer base {
  :root {
    --font: ui-sans-serif, -apple-system, "Segoe UI", Inter, Roboto, sans-serif;
    --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --bg: #ffffff;
    --bg-side: #f7f7f5;
    --bg-2: #fbfbfa;
    --bg-code: #f7f6f3;
    --fg: rgb(55,53,47);
    --muted: rgba(55,53,47,.65);
    --faint: rgba(55,53,47,.45);
    --border: rgba(55,53,47,.09);
    --border-2: rgba(55,53,47,.16);
    --hover: rgba(55,53,47,.06);
    --hover-2: rgba(55,53,47,.1);
    --selected: rgba(35,131,226,.14); --range-fill: rgba(35,131,226,.09);
    /* Focus halo. --selected is a SELECTION tint (14% blue) and reads as almost nothing around a
       focused edge; the ring needs enough weight that the focused field is findable at a glance. */
    --ring: rgba(35,131,226,.3); --ring-danger: rgba(235,87,87,.26);
    --accent: #2383e2;
    --accent-fg: #fff;
    --danger: #eb5757;
    --danger-bg: rgba(235,87,87,.1);
    --ok: #0f7b6c;
    --ok-bg: #dbeddb;
    --warn-bg: #fdecc8;
    --info-bg: #d3e5ef;
    --info-fg: #183347;
    --r-1: 4px; --r-2: 6px; --r-3: 8px; --r-4: 12px;
    --shadow: 0 4px 12px rgba(0,0,0,.08), 0 0 0 1px rgba(0,0,0,.06);
    --shadow-lg: 0 12px 40px rgba(0,0,0,.16), 0 0 0 1px rgba(0,0,0,.06);
    --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 24px; --s-6: 32px;
    /* Layering, low to high. Everything inside a scroller (grid rows, calendar events) lives in
       1-9; sticky chrome that must cover that content is 20+; page chrome above that; then the
       app overlays. x-grid does NOT create a stacking context, so its descendants compete with
       x-topbar and x-ghead directly - that is why these have to share one ordered scale. */
    --z-content: 1; --z-sticky: 2; --z-active: 4; --z-drag: 7; --z-guide: 8;
    --z-stickychrome: 20; --z-stickyhead: 22; --z-topbar: 25;
    --z-side: 35; --z-peek: 40; --z-pal: 55; --z-pop: 60; --z-toast: 200;
    --sidebar-w: 240px; --rail-w: 52px; --bg-rail: #f1f1ef;
    /* density: Notion-calibrated (sidebar item 27px, controls 28px, table rows 32px, popover items 28px) */
    --row-h: 32px;
    --ctl-h: 28px;
    --side-item-h: 27px;
    --menu-item-h: 28px;
    --t: 120ms;
    --pc0-bg:#e3e2e0;--pc0-fg:#32302c;--pc1-bg:#eee0da;--pc1-fg:#442a1e;--pc2-bg:#fadec9;--pc2-fg:#49290e;--pc3-bg:#fdecc8;--pc3-fg:#402c1b;
    --pc4-bg:#dbeddb;--pc4-fg:#1c3829;--pc5-bg:#d3e5ef;--pc5-fg:#183347;--pc6-bg:#e8deee;--pc6-fg:#412454;--pc7-bg:#f5e0e9;--pc7-fg:#4c2337;--pc8-bg:#ffe2dd;--pc8-fg:#5d1715;
    color-scheme: light;
  }
  html[data-theme="dark"] { color-scheme: dark;
    --bg:#191919;--bg-side:#202020;--bg-rail:#171717;--bg-2:#1f1f1f;--bg-code:#252525;--fg:rgba(255,255,255,.81);--muted:rgba(255,255,255,.55);--faint:rgba(255,255,255,.38);
    --border:rgba(255,255,255,.094);--border-2:rgba(255,255,255,.16);--hover:rgba(255,255,255,.055);--hover-2:rgba(255,255,255,.1);--selected:rgba(35,131,226,.22);--range-fill:rgba(35,131,226,.14);--ring:rgba(35,131,226,.45);--ring-danger:rgba(235,87,87,.38);
    --shadow:0 4px 12px rgba(0,0,0,.4),0 0 0 1px rgba(255,255,255,.08);--shadow-lg:0 12px 40px rgba(0,0,0,.6),0 0 0 1px rgba(255,255,255,.08);
    --ok-bg:#1c3829;--warn-bg:#402c1b;--info-bg:#183347;--info-fg:#d3e5ef;--danger-bg:rgba(235,87,87,.18);
    --pc0-bg:#373737;--pc0-fg:#d4d4d4;--pc1-bg:#4a3228;--pc1-fg:#e0c9be;--pc2-bg:#5a3a1c;--pc2-fg:#f6d5b8;--pc3-bg:#5a4a1c;--pc3-fg:#f6e4b8;
    --pc4-bg:#1f3a2a;--pc4-fg:#c4e3c9;--pc5-bg:#1e3a4d;--pc5-fg:#c2dcec;--pc6-bg:#3a2a4a;--pc6-fg:#dcc9ea;--pc7-bg:#4a2a3a;--pc7-fg:#ecc9d9;--pc8-bg:#5a2a28;--pc8-fg:#f6c9c4;
  }
  @media (prefers-color-scheme: dark) {
    html:not([data-theme="light"]) { color-scheme: dark;
      --bg:#191919;--bg-side:#202020;--bg-rail:#171717;--bg-2:#1f1f1f;--bg-code:#252525;--fg:rgba(255,255,255,.81);--muted:rgba(255,255,255,.55);--faint:rgba(255,255,255,.38);
      --border:rgba(255,255,255,.094);--border-2:rgba(255,255,255,.16);--hover:rgba(255,255,255,.055);--hover-2:rgba(255,255,255,.1);--selected:rgba(35,131,226,.22);--range-fill:rgba(35,131,226,.14);--ring:rgba(35,131,226,.45);--ring-danger:rgba(235,87,87,.38);
      --shadow:0 4px 12px rgba(0,0,0,.4),0 0 0 1px rgba(255,255,255,.08);--shadow-lg:0 12px 40px rgba(0,0,0,.6),0 0 0 1px rgba(255,255,255,.08);
      --ok-bg:#1c3829;--warn-bg:#402c1b;--info-bg:#183347;--info-fg:#d3e5ef;--danger-bg:rgba(235,87,87,.18);
      --pc0-bg:#373737;--pc0-fg:#d4d4d4;--pc1-bg:#4a3228;--pc1-fg:#e0c9be;--pc2-bg:#5a3a1c;--pc2-fg:#f6d5b8;--pc3-bg:#5a4a1c;--pc3-fg:#f6e4b8;
      --pc4-bg:#1f3a2a;--pc4-fg:#c4e3c9;--pc5-bg:#1e3a4d;--pc5-fg:#c2dcec;--pc6-bg:#3a2a4a;--pc6-fg:#dcc9ea;--pc7-bg:#4a2a3a;--pc7-fg:#ecc9d9;--pc8-bg:#5a2a28;--pc8-fg:#f6c9c4;
    }
  }
  *, *::before, *::after { box-sizing: border-box; }
  html { height: 100%; -webkit-text-size-adjust: 100%; }
  /* App shell never scrolls: the rail and sidebar are fixed panes and <main> is the page's
     own scroll container (Notion/Linear model). Previously the whole page scrolled and the
     sidebar was only `position: sticky`, so it drifted with the body. */
  body {
    margin: 0; height: 100%; background: var(--bg); color: var(--fg);
    font: 14px/1.5 var(--font); -webkit-font-smoothing: antialiased;
    display: flex; overflow: hidden;
  }
  h1, h2, h3, h4, h5, h6 { margin: 0; font-weight: 600; line-height: 1.25; }
  h1 { font-size: 28px; font-weight: 700; letter-spacing: -.01em; }
  h2 { font-size: 20px; }
  h3 { font-size: 15px; }
  h6 { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--faint); font-weight: 600; }
  p { margin: 0; }
  a { color: inherit; text-decoration: none; }
  ul { margin: 0; padding: 0; list-style: none; }
  hr { border: 0; border-top: 1px solid var(--border); margin: var(--s-1) 0; }
  code { font: 12px/1.4 var(--mono); background: var(--hover); padding: 1px 4px; border-radius: 3px; }
  svg.ico { flex: 0 0 auto; display: inline-block; vertical-align: -3px; }
  svg.ico.faint { color: var(--faint); }
  button, input, select, textarea { font: inherit; color: inherit; }
  button { cursor: pointer; background: none; border: 0; padding: 0; transition: background var(--t), color var(--t), box-shadow var(--t); }
  input:not([type=checkbox]):not([type=radio]):not([type=file]), select, textarea {
    width: 100%; height: var(--ctl-h); padding: 0 8px; border: 1px solid var(--border-2); border-radius: var(--r-1);
    background: var(--bg); font-size: 13px; outline: none; transition: border-color var(--t), box-shadow var(--t); max-width: 100%;
  }
  input[type=file] { max-width: 100%; }
  textarea { height: auto; padding: 6px 8px; }
  /* A solid 2px accent perimeter (border + 1px INSET shadow): it carries contrast against both the
     field and the page, where a single translucent halo composites down to roughly 1.5:1 and fails.
     Focus never changes a field's box, visibly or in layout: no border width, padding or size on
     :focus, and no outer ring - a halo painted outside made a field in a tight row read as grown. */
  input:focus-visible, select:focus-visible, textarea:focus-visible {
    border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent);
  }
  /* Invalid is only worth showing once the user has had a go at the field. `:invalid` paints every
     empty required box red on first paint; `:user-invalid` waits for the interaction. aria-invalid
     covers what the app judges for itself (mismatched confirmation, a rejected value). */
  input:user-invalid, textarea:user-invalid, select:user-invalid,
  input[aria-invalid="true"], textarea[aria-invalid="true"], select[aria-invalid="true"] { border-color: var(--danger); }
  input:user-invalid:focus-visible, textarea:user-invalid:focus-visible, select:user-invalid:focus-visible,
  input[aria-invalid="true"]:focus-visible, textarea[aria-invalid="true"]:focus-visible, select[aria-invalid="true"]:focus-visible {
    border-color: var(--danger); box-shadow: inset 0 0 0 1px var(--danger);
  }
  /* Checkboxes and radios are drawn by the OS: accent-color only tints them, so the box shape,
     size, corner radius and check mark still differ between Chrome, Firefox and Safari on every
     platform. appearance:none removes the native widget entirely and we paint all of it. */
  input[type=checkbox], input[type=radio] {
    appearance: none; -webkit-appearance: none; flex: 0 0 auto; position: relative;
    width: 15px; height: 15px; margin: 0; padding: 0; cursor: pointer;
    border: 1.5px solid var(--border-3, var(--faint)); border-radius: var(--r-1); background: var(--bg);
    transition: background var(--t), border-color var(--t);
  }
  input[type=radio] { border-radius: 50%; }
  input[type=checkbox]:hover, input[type=radio]:hover { border-color: var(--accent); }
  input[type=checkbox]:checked, input[type=radio]:checked, input[type=checkbox]:indeterminate { background: var(--accent); border-color: var(--accent); }
  input[type=checkbox]:checked::after {
    content: ""; position: absolute; left: 4px; top: 1px; width: 3px; height: 7px;
    border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(43deg);
  }
  input[type=checkbox]:indeterminate::after { content: ""; position: absolute; left: 2.5px; right: 2.5px; top: 5.5px; height: 2px; border-radius: 1px; background: #fff; }
  input[type=radio]:checked::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: #fff; }
  input[type=checkbox]:disabled, input[type=radio]:disabled { opacity: .45; cursor: not-allowed; }
  input[type=checkbox]:focus-visible, input[type=radio]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

  /* No resize gripper: it is browser-drawn and sits in the corner of every textarea. */
  textarea { resize: none; line-height: 1.5; }

  /* Number spinners and the WebKit search clear button are painted by the browser too. */
  input[type=number] { appearance: textfield; -moz-appearance: textfield; }
  input[type=number]::-webkit-outer-spin-button, input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; appearance: none; margin: 0; }
  input[type=search]::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
  input[type=search]::-webkit-search-results-button, input[type=search]::-webkit-search-results-decoration { -webkit-appearance: none; appearance: none; display: none; }
  select { padding-right: 24px; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 16 16' fill='none' stroke='%23888' stroke-width='1.6' stroke-linecap='round'%3E%3Cpath d='m4 6 4 4 4-4'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 8px center; }
  label > span:first-child { display: block; font-size: 12px; color: var(--muted); margin-bottom: 4px; font-weight: 500; }
  label.check { display: flex; align-items: center; gap: 8px; min-height: 30px; padding: 0 6px; border-radius: var(--r-1); cursor: pointer; font-size: 13px; }
  label.check:hover { background: var(--hover); }
  label.check input { margin: 0; }
  [hidden] { display: none !important; }
  [x-cloak] { display: none !important; }
  small { font-size: 12px; }
  time { white-space: nowrap; }
  :focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
  input:focus-visible, select:focus-visible, textarea:focus-visible, x-cell:focus-visible { outline: none; }
  * { scrollbar-width: thin; scrollbar-color: var(--border-2) transparent; }   /* Firefox */
  ::-webkit-scrollbar { width: 10px; height: 10px; }
  ::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 6px; border: 2px solid transparent; background-clip: padding-box; }
  ::-webkit-scrollbar-thumb:hover { background: var(--faint); background-clip: padding-box; border: 2px solid transparent; }
  ::-webkit-scrollbar-track { background: transparent; }
  @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition: none !important; animation: none !important; } }
}

@layer components {
  /* ---------- buttons ---------- */
  .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: var(--ctl-h); padding: 0 12px; font-size: 13px; font-weight: 500;
    border: 1px solid var(--border-2); border-radius: var(--r-2); background: var(--bg); white-space: nowrap; color: var(--fg);
  }
  .btn:hover { background: var(--hover); }
  .btn.primary { background: var(--accent); color: var(--accent-fg); border-color: transparent; }
  .btn.primary:hover { filter: brightness(.94); background: var(--accent); }
  .btn.danger { background: var(--danger); color: #fff; border-color: transparent; }
  .btn.sm { height: 28px; padding: 0 10px; font-size: 12px; }
  .btn.block { width: 100%; height: 36px; }
  .btn:disabled { opacity: .5; cursor: default; }
  .ghost { display: inline-flex; align-items: center; gap: 6px; height: var(--ctl-h); padding: 0 8px; border-radius: var(--r-1); color: var(--muted); font-size: 13px; font-weight: 500; }
  .ghost:hover { background: var(--hover); color: var(--fg); }
  .ghost.sm { height: 26px; font-size: 12px; }
  .ghost.danger, .mi.danger { color: var(--danger); }
  .ghost.danger:hover, .mi.danger:hover { background: var(--danger-bg); color: var(--danger); }
  .icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--r-1); color: var(--muted); flex: 0 0 auto; }
  .icon-btn:hover { background: var(--hover); color: var(--fg); }
  .icon-btn[aria-pressed="true"], .icon-btn.on { color: var(--accent); background: var(--selected); }
  .icon-btn.sm { width: 22px; height: 22px; }

  /* ---------- pills / chips / avatars ---------- */
  .pill {
    display: inline-flex; align-items: center; height: 20px; padding: 0 7px; border-radius: 3px; font-size: 12px; line-height: 20px; font-weight: 500;
    white-space: nowrap; max-width: 100%; overflow: hidden; text-overflow: ellipsis; background: var(--pc0-bg); color: var(--pc0-fg);
  }
  .pill + .pill { margin-left: 4px; }
  .pill.c0 { background: var(--pc0-bg); color: var(--pc0-fg); }
  .pill.c1 { background: var(--pc1-bg); color: var(--pc1-fg); }
  .pill.c2 { background: var(--pc2-bg); color: var(--pc2-fg); }
  .pill.c3 { background: var(--pc3-bg); color: var(--pc3-fg); }
  .pill.c4 { background: var(--pc4-bg); color: var(--pc4-fg); }
  .pill.c5 { background: var(--pc5-bg); color: var(--pc5-fg); }
  .pill.c6 { background: var(--pc6-bg); color: var(--pc6-fg); }
  .pill.c7 { background: var(--pc7-bg); color: var(--pc7-fg); }
  .pill.c8 { background: var(--pc8-bg); color: var(--pc8-fg); }
  .pill.restricted { background: transparent; color: var(--faint); border: 1px dashed var(--border-2); }
  .pill.dot::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; margin-right: 5px; opacity: .8; }
  .chip { display: inline-flex; align-items: center; gap: 4px; height: 20px; padding: 0 6px; border-radius: 3px; font-size: 12px; color: var(--muted); background: var(--hover); white-space: nowrap; max-width: 100%; overflow: hidden; }
  .chip.who { background: none; padding-left: 0; color: var(--fg); }
  .chip.who .avatar { width: 18px; height: 18px; font-size: 10px; }
  .chk { display: inline-flex; width: 16px; height: 16px; border: 1px solid var(--border-2); border-radius: 3px; align-items: center; justify-content: center; color: #fff; background: var(--bg); transition: background var(--t); }
  .chk.on { background: var(--accent); border-color: var(--accent); }
  .avatar { display: inline-flex; width: 20px; height: 20px; border-radius: 50%; background: var(--pc5-bg); color: var(--pc5-fg); font: 600 10px/20px var(--font); font-style: normal; align-items: center; justify-content: center; margin-right: 6px; flex: 0 0 auto; text-transform: uppercase; }
  .avatar.lg { width: 32px; height: 32px; font-size: 13px; line-height: 32px; }
  .empty { color: var(--faint); font-size: 13px; }
  .muted { color: var(--muted); }
  .faint { color: var(--faint); }
  .lnk { color: var(--accent); text-decoration: underline; text-decoration-color: rgba(35,131,226,.35); }
  /* a formula's style(): Notion's b/i/u/s/c and colours, in the pill colours (macros/ui.html rich) */
  .fx-b { font-weight: 600; } .fx-i { font-style: italic; } .fx-u { text-decoration: underline; } .fx-s { text-decoration: line-through; }
  .fx-u.fx-s { text-decoration: underline line-through; }
  .fx-c { font: 12px/1.4 var(--mono); background: var(--hover); padding: 1px 4px; border-radius: 3px; }
  .fx-gray { color: var(--muted); } .fx-brown { color: var(--pc1-fg); } .fx-orange { color: var(--pc2-fg); } .fx-yellow { color: var(--pc3-fg); } .fx-green { color: var(--pc4-fg); }
  .fx-blue { color: var(--pc5-fg); } .fx-purple { color: var(--pc6-fg); } .fx-pink { color: var(--pc7-fg); } .fx-red { color: var(--pc8-fg); }
  :is(.fx-gray_background, .fx-brown_background, .fx-orange_background, .fx-yellow_background, .fx-green_background, .fx-blue_background, .fx-purple_background, .fx-pink_background, .fx-red_background) { padding: 1px 4px; border-radius: 3px; }
  .fx-gray_background { background: var(--pc0-bg); } .fx-brown_background { background: var(--pc1-bg); } .fx-orange_background { background: var(--pc2-bg); }
  .fx-yellow_background { background: var(--pc3-bg); } .fx-green_background { background: var(--pc4-bg); } .fx-blue_background { background: var(--pc5-bg); }
  .fx-purple_background { background: var(--pc6-bg); } .fx-pink_background { background: var(--pc7-bg); } .fx-red_background { background: var(--pc8-bg); }
  .note { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: var(--r-2); font-size: 13px; }
  .note.ok { background: var(--ok-bg); color: var(--pc4-fg); }
  /* warn is amber "careful"; err is red "that did not work" - a rejected sign-in is the second one */
  .note.err { background: var(--pc8-bg); color: var(--pc8-fg); align-items: flex-start; }
  .note.info { background: var(--info-bg); color: var(--info-fg); align-items: flex-start; }
  .note.key { flex-direction: column; align-items: flex-start; background: var(--warn-bg); color: var(--pc3-fg); margin-bottom: var(--s-3); }
  .note.key code { font-size: 13px; background: var(--bg); padding: 8px 10px; user-select: all; word-break: break-all; border-radius: var(--r-1); width: 100%; }
  .kbd { display: inline-block; font: 11px/16px var(--mono); padding: 0 5px; border: 1px solid var(--border-2); border-bottom-width: 2px; border-radius: 4px; color: var(--muted); background: var(--bg); }
  .empty-state { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; text-align: center; padding: 40px 16px; color: var(--muted); border: 1px dashed var(--border-2); border-radius: var(--r-3); font-size: 13px; }
  .run-fail { color: var(--pc8-fg); }
  /* sidebar reorder (records-links.js): where the dragged item will land */
  x-sidebar .drop-before { box-shadow: inset 0 2px 0 var(--accent); }
  x-sidebar .drop-after { box-shadow: inset 0 -2px 0 var(--accent); }
  /* Favorites on every space (layout.html .sb-favs) */
  x-sidebar > .sb-favs { padding: 6px 8px 2px; }
  /* Page cover (peek.html .rec-cover; gallery cards reuse the presets) */
  .rec-cover { position: relative; height: 180px; margin: 0 0 8px; background: var(--bg-2) center / cover no-repeat; border-radius: var(--r-2); }
  x-gcard .cover.img, x-gcard .cover.rec-cover { height: var(--cover-h, 120px); margin: 0; border-radius: 0; background-size: cover; background-position: center; }
  .rec-cover.g1 { background-image: linear-gradient(135deg, #f6d365, #fda085); }
  .rec-cover.g2 { background-image: linear-gradient(135deg, #84fab0, #8fd3f4); }
  .rec-cover.g3 { background-image: linear-gradient(135deg, #a1c4fd, #c2e9fb); }
  .rec-cover.g4 { background-image: linear-gradient(135deg, #fbc2eb, #a6c1ee); }
  .rec-cover.g5 { background-image: linear-gradient(135deg, #d4fc79, #96e6a1); }
  .rec-cover.g6 { background-image: linear-gradient(135deg, #e0c3fc, #8ec5fc); }
  .rec-cover.g7 { background-image: linear-gradient(135deg, #ffecd2, #fcb69f); }
  .rec-cover.g8 { background-image: linear-gradient(135deg, #434343, #000000); }
  .rec-cover .cover-acts { position: absolute; right: 8px; bottom: 8px; display: none; gap: 4px; }
  .rec-cover:hover .cover-acts, .rec-cover:focus-within .cover-acts { display: flex; }
  .rec-cover .cover-acts .ghost { background: var(--bg); }
  .rec-head .add-cover { opacity: 0; }
  .rec-head:hover .add-cover, .rec-head .add-cover:focus-visible { opacity: 1; }
  /* Card preview: Page content (macros/chips.html card_preview) */
  .card-snip { margin: 0 0 6px; color: var(--muted); font-size: 12px; line-height: 1.45; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
  /* Table of contents block ([TOC]) */
  .prose .toc-block { margin: 8px 0; }
  .prose .toc-block ul { list-style: none; margin: 0; padding: 0; }
  .prose .toc-block li { margin: 2px 0; }
  .prose .toc-block a { color: var(--muted); text-decoration: underline; text-decoration-color: var(--border-2); text-underline-offset: 3px; }
  .prose .toc-block .toc-h2 { padding-left: 16px; } .prose .toc-block .toc-h3 { padding-left: 32px; }
  /* Files property (macros/ui.html cellval) */
  .files-v { display: inline-flex; align-items: center; gap: 4px; min-width: 0; overflow: hidden; }
  .files-v .fthumb { flex: 0 0 auto; display: inline-flex; width: 22px; height: 22px; border-radius: 3px; overflow: hidden; border: 1px solid var(--border); }
  .files-v .fthumb img { width: 100%; height: 100%; object-fit: cover; }
  .files-v .fchip { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .files-v .file-add { opacity: 0; flex: 0 0 auto; }
  x-cell:hover .files-v .file-add, x-record .files-v .file-add, .files-v .file-add:focus-visible { opacity: 1; }
  /* Button property (macros/ui.html cellval) */
  .cell-btn { height: 22px; padding: 0 8px; border: 1px solid var(--border-2); border-radius: var(--r-1); background: var(--bg); color: var(--fg); font: inherit; font-size: 12px; cursor: pointer; white-space: nowrap; }
  .cell-btn:hover { background: var(--hover); }
  /* Inbox filters (inbox.html) */
  x-inbox .ifilter { display: flex; gap: 2px; margin: 4px 0 8px; }
  x-inbox .ifilter a { padding: 3px 10px; border-radius: var(--r-2); color: var(--muted); font-size: 13px; }
  x-inbox .ifilter a[aria-current] { background: var(--hover); color: var(--fg); }
  x-inbox .ifilter .n { font-weight: 600; }
  /* New ▾ (viewbar.html): New and the templates chevron as one split button */
  .newsplit { display: inline-flex; }
  .newsplit > .tool:first-child { border-top-right-radius: 0; border-bottom-right-radius: 0; }
  .newsplit > .tool.chev { border-top-left-radius: 0; border-bottom-left-radius: 0; padding: 0 4px; margin-left: 1px; }
  /* Trash (trash.html) */
  .trash-search { max-width: 320px; margin-bottom: 12px; }
  .trash-list { list-style: none; margin: 0; padding: 0; }
  .trash-list li { display: flex; align-items: center; gap: 8px; padding: 8px 4px; border-bottom: 1px solid var(--border); }
  .trash-list .tt { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
  /* the Share panel (share.js) */
  .popover.share { width: min(440px, calc(100vw - 24px)); padding: 12px; }
  .popover.share .sh-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 10px; }
  .popover.share .sh-add { display: flex; gap: 6px; align-items: center; margin-bottom: 12px; }
  .popover.share .sh-add > :first-child { flex: 1 1 auto; min-width: 0; }
  .popover.share .sh-list { max-height: 50vh; overflow-y: auto; }
  .popover.share .sh-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; }
  .popover.share .sh-who { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 0; }
  .popover.share .sh-name { display: flex; flex-direction: column; min-width: 0; }
  .popover.share .sh-name small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .popover.share .sh-row.inh { opacity: .85; }
  .popover.share .sh-note { font-size: 12px; margin: 8px 0 0; }
  .popover.share .sh-pub { border-top: 1px solid var(--border); margin-top: 10px; padding-top: 6px; }
  .popover.share .sh-url { flex: 1 1 auto; min-width: 0; font-size: 12px; color: var(--muted); text-decoration: underline; }
  .popover.share .sh-foot { display: flex; justify-content: flex-end; border-top: 1px solid var(--border); margin-top: 10px; padding-top: 8px; }
  /* the error page (error.rs error_pages): a page load that failed */
  body.errpage { display: grid; place-items: center; min-height: 100vh; margin: 0; padding: 16px; background: var(--bg); color: var(--fg); }
  .err-box { max-width: 420px; text-align: center; }
  .err-box h1 { font-size: 24px; margin: 4px 0 8px; }
  .err-box .err-code { margin: 0; color: var(--faint); font-size: 13px; font-weight: 600; letter-spacing: .04em; }
  .err-box p { margin: 0 0 16px; }
  .view-gone { margin: 0 0 8px; padding: 6px 10px; border-radius: var(--r-2); background: var(--warn-bg); color: var(--fg); font-size: 13px; }
  .empty-state svg { width: 28px; height: 28px; color: var(--faint); margin-bottom: 4px; }
  .empty-state b { color: var(--fg); font-weight: 600; font-size: 14px; }
  .empty-state .btn { margin-top: var(--s-2); }
  /* Same empty state at panel scale. A 40px-padded dashed box is right for a page, and far too
     tall inside a home card, a rail section or a tab panel — those were each growing their own
     one-line "Nothing yet" instead, which is how one pattern turns into five. */
  .empty-state.sm { padding: var(--s-4) var(--s-3); gap: var(--s-1); font-size: 12px; border-radius: var(--r-2); }
  .empty-state.sm svg { width: 20px; height: 20px; margin-bottom: 2px; }
  .empty-state.sm b { font-size: 13px; }
  .empty-state.sm .btn { margin-top: var(--s-1); }
  /* for a spot that is already inside a framed container: a second dashed border reads as a bug */
  .empty-state.bare { border: 0; }
  .eyebrow, h6.sec { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--faint); font-weight: 600; margin: 16px 0 8px; display: flex; align-items: center; gap: 8px; }
  .eyebrow .n, h6.sec .n { background: var(--hover); border-radius: 8px; padding: 0 6px; text-transform: none; letter-spacing: 0; }
  .eyebrow > .ghost, h6.sec > .ghost { margin-left: auto; text-transform: none; letter-spacing: 0; font-weight: 500; }
  .skeleton { background: linear-gradient(90deg, var(--hover) 25%, var(--hover-2) 37%, var(--hover) 63%); background-size: 400% 100%; animation: sk 1.4s ease infinite; border-radius: var(--r-1); }
  @keyframes sk { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
  /* A panel fetched after first paint should hold the SHAPE of what is coming. A single 32px bar
     reads as a broken layout; staggered lines read as text on its way. */
  .sk-lines { display: flex; flex-direction: column; gap: var(--s-2); padding: var(--s-2) 0; }
  .sk-lines > i { display: block; height: 10px; }
  .sk-lines > i:nth-child(1) { width: 42%; }
  .sk-lines > i:nth-child(2) { width: 100%; }
  .sk-lines > i:nth-child(3) { width: 74%; }
  .tabs-ui { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin: var(--s-2) 0 var(--s-5); overflow-x: auto; scrollbar-width: none; }
  .tabs-ui::-webkit-scrollbar { display: none; }
  /* a table's Activity page: its view tabs with "+ New view" pinned beside them (activity.html) */
  .act-vbar { display: flex; align-items: center; gap: 4px; border-bottom: 1px solid var(--border); margin: var(--s-2) 0 var(--s-5); }
  .act-vbar > .tabs-ui { flex: 1 1 auto; min-width: 0; border-bottom: 0; margin: 0; }
  .act-vbar .tab-add { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 8px; color: var(--faint); font-size: 13px; border-radius: var(--r-1, 3px); }
  .act-vbar .tab-add:hover { background: var(--hover); color: var(--fg); }
  .tabs-ui > button, .tabs-ui > a { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px; color: var(--muted); font-weight: 500; font-size: 13px; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; }
  .tabs-ui > button:hover, .tabs-ui > a:hover { color: var(--fg); background: var(--hover); border-radius: 3px 3px 0 0; }
  .tabs-ui > [aria-selected="true"], .tabs-ui > [aria-current] { color: var(--fg); border-bottom-color: var(--fg); }
  .tabs-ui .n { font-size: 11px; background: var(--hover); border-radius: 8px; padding: 0 5px; }
  .segment { display: inline-flex; padding: 2px; background: var(--hover); border-radius: var(--r-2); gap: 2px; }
  .segment > button { height: 24px; padding: 0 8px; border-radius: 4px; font-size: 12px; color: var(--muted); font-weight: 500; }
  .segment > button[aria-pressed="true"] { background: var(--bg); color: var(--fg); box-shadow: 0 1px 2px rgba(0,0,0,.08); }
  .searchfield { position: relative; }
  .searchfield svg { position: absolute; left: 8px; top: 50%; transform: translateY(-50%); color: var(--faint); pointer-events: none; }
  .searchfield input { padding-left: 28px; }

  /* ---------- popovers (portal-positioned by app.js: position fixed, JS computes top/left) ---------- */
  .pop-anchor { position: relative; display: inline-flex; }
  .popover {
    position: fixed; top: 0; left: 0; z-index: var(--z-pop); min-width: 240px; max-width: calc(100vw - 16px); padding: var(--s-2);
    /* hairline ring as well as the shadow: on a dark theme the panel background matches the
       page, so the shadow alone left popovers with no visible edge */
    background: var(--bg); border-radius: var(--r-3); box-shadow: 0 0 0 1px var(--border), var(--shadow-lg); font-size: 13px; max-height: calc(100vh - 16px); overflow-y: auto; overflow-x: hidden;
    animation: popin var(--t) ease;
  }
  @keyframes popin { from { opacity: 0; transform: translateY(-3px); } to { opacity: 1; transform: none; } }
  .popover.wide { min-width: min(420px, calc(100vw - 16px)); }
  .popover.confirm { min-width: 260px; max-width: 320px; display: grid; gap: 12px; }
  .popover.confirm > p { margin: 0; line-height: 1.45; }
  .popover.menu { min-width: 200px; padding: 4px; }
  .popover.menu form { padding: 4px; }
  .popover.menu hr { margin: 4px 0; }
  .popover.menu .mh { font-size: 11px; color: var(--faint); padding: 6px 8px 2px; text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
  .popover .stack > label input:not([type=checkbox]):not([type=radio]), .popover .stack > label select { width: 100%; }
  .mi { display: flex; align-items: center; gap: 8px; width: 100%; height: var(--menu-item-h); padding: 0 8px; border-radius: var(--r-1); text-align: left; font-size: 13px; color: var(--fg); }
  .mi:hover, .mi.on { background: var(--hover); }
  .mi svg { color: var(--muted); }
  .mi .kbd, .mi .r { margin-left: auto; }
  .mi .r { color: var(--faint); font-size: 12px; }
  .frow { display: flex; gap: 6px; align-items: center; min-width: 0; }
  .frow > input, .frow > select { min-width: 0; flex: 1; }
  .frow > label { flex: 1; min-width: 0; }
  .frow .icon-btn { flex: 0 0 auto; }
  .frow > .btn { flex: 0 0 auto; }
  .ctxmenu { position: fixed; z-index: var(--z-pop); min-width: 180px; padding: 4px; background: var(--bg); border-radius: var(--r-3); box-shadow: var(--shadow-lg); font-size: 13px; }
  /* ---------- icon rail ---------- */
  x-rail {
    height: 100%; width: var(--rail-w); flex: 0 0 var(--rail-w); z-index: calc(var(--z-side) + 1);
    display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 8px 0; background: var(--bg-rail); border-right: 1px solid var(--border);
    overflow-y: auto; overflow-x: hidden; scrollbar-width: none;
  }
  x-rail::-webkit-scrollbar { display: none; }
  /* the rail itself no longer scrolls: the middle region does, so the top and bottom
     items stay put and the collapsed rail can use chevrons instead of a scrollbar */
  x-rail { overflow: hidden; }
  x-rail .rail-scroll { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 100%; min-height: 0; flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; scrollbar-width: none; }
  x-rail .rail-scroll::-webkit-scrollbar { display: none; }
  /* labels visible = wide enough for a real scrollbar, which is what the user expects there */
  x-rail .rail-scroll.has-bar { scrollbar-width: thin; }
  x-rail .rail-scroll.has-bar::-webkit-scrollbar { display: block; width: 6px; }
  x-rail .rail-scrollbtn { flex: 0 0 auto; display: flex; align-items: center; justify-content: center; width: 28px; height: 18px; border-radius: var(--r-1); color: var(--faint); background: var(--bg-rail); }
  x-rail .rail-scrollbtn:hover { background: var(--hover); color: var(--fg); }
  x-rail .rail-scrollbtn.up svg { transform: rotate(180deg); }
  x-rail .rail-pins { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 100%; }
  x-rail .rail-pins > a[data-dragging] { opacity: .4; }
  x-rail .rail-add { opacity: 0; }
  x-rail:hover .rail-add, x-rail .rail-add:focus-visible { opacity: 1; }
  body[data-rail="wide"] x-rail .rail-add { opacity: 1; }
  x-rail > a, x-rail > button {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; width: 44px; height: 44px; border-radius: var(--r-3);
    color: var(--muted); font-size: 9px; font-weight: 500; position: relative; flex: 0 0 auto;
  }
  x-rail > a > span, x-rail > button > span { display: none; }
  x-rail > a:hover, x-rail > button:hover { background: var(--hover); color: var(--fg); }
  x-rail > a[aria-current] { background: var(--selected); color: var(--accent); }
  x-rail > a[aria-current]::before { content: ""; position: absolute; left: -6px; top: 12px; bottom: 12px; width: 3px; border-radius: 0 3px 3px 0; background: var(--accent); }
  x-rail hr { width: 24px; margin: 4px 0; }
  x-rail .sp { flex: 1; }
  x-rail .badge { position: absolute; top: 4px; right: 4px; }
  x-rail .ws { display: flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: var(--r-3); }
  x-rail .ws:hover { background: var(--hover); }
  x-rail .ws .ws-mark { width: 26px; height: 26px; font-size: 13px; line-height: 26px; }
  .badge { background: var(--accent); color: #fff; font-size: 10px; font-weight: 600; min-width: 16px; height: 16px; line-height: 16px; text-align: center; border-radius: 8px; padding: 0 4px; }
  .ws-mark { display: inline-flex; width: 22px; height: 22px; border-radius: var(--r-1); background: var(--fg); color: var(--bg); font: 700 12px/22px var(--font); align-items: center; justify-content: center; flex: 0 0 auto; }

  /* ---------- contextual sidebar ---------- */
  x-sidebar {
    height: 100%; width: var(--sidebar-w); flex: 0 0 var(--sidebar-w);
    display: flex; flex-direction: column; background: var(--bg-side); border-right: 1px solid var(--border);
    font-size: 13px; overflow: hidden; transition: width .15s ease, flex-basis .15s ease; z-index: var(--z-side);
  }
  x-sidebar > section { display: none; flex-direction: column; flex: 1; min-height: 0; }
  body[data-space="home"] x-sidebar > section[data-for="home"], body[data-space="inbox"] x-sidebar > section[data-for="home"], body[data-space="my"] x-sidebar > section[data-for="home"],
  body[data-space="settings"] x-sidebar > section[data-for="home"], body[data-space="admin"] x-sidebar > section[data-for="home"], body:not([data-space]) x-sidebar > section[data-for="home"],
  body[data-space="projects"] x-sidebar > section[data-for="projects"], body[data-space="crm"] x-sidebar > section[data-for="crm"],
  body[data-space="knowledge"] x-sidebar > section[data-for="knowledge"], body[data-space="notes"] x-sidebar > section[data-for="notes"],
  body[data-space="calendar"] x-sidebar > section[data-for="calendar"], body[data-space="databases"] x-sidebar > section[data-for="databases"] { display: flex; }
  x-sidebar > section > header { display: flex; align-items: center; gap: 6px; height: 44px; padding: 0 8px 0 14px; }
  x-sidebar > section > header h5 { display: flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-sidebar > section > header h5 .ico { color: var(--faint); }
  x-sidebar .collapse { opacity: 0; }
  x-sidebar:hover .collapse, x-sidebar .collapse:focus-visible { opacity: 1; }
  x-sidebar .sfilter { position: relative; margin: 0 8px 4px; }
  x-sidebar .sfilter svg { position: absolute; left: 8px; top: 50%; transform: translateY(-50%); color: var(--faint); pointer-events: none; }
  x-sidebar .sfilter input { height: 28px; padding-left: 28px; background: var(--bg); font-size: 12px; }
  x-sidebar nav { padding: 4px 8px; }
  x-sidebar nav a, x-sidebar nav button.nav {
    display: flex; align-items: center; gap: 8px; height: var(--side-item-h); padding: 0 8px; border-radius: var(--r-1); color: var(--muted); font-weight: 500;
    white-space: nowrap; overflow: hidden; width: 100%; text-align: left; font-size: 14px; line-height: 1;
  }
  x-sidebar nav a .ico, x-sidebar nav button.nav .ico { width: 18px; height: 18px; flex: 0 0 auto; }
  x-sidebar nav a span, x-sidebar nav button.nav span { overflow: hidden; text-overflow: ellipsis; }
  x-sidebar nav a:hover, x-sidebar nav button.nav:hover { background: var(--hover); color: var(--fg); }
  x-sidebar nav a[aria-current] { background: var(--hover-2); color: var(--fg); }
  x-sidebar nav .badge { margin-left: auto; }
  x-sidebar .tree { flex: 1; overflow-y: auto; overflow-x: hidden; padding-bottom: 12px; }
  x-sidebar .tree h6 { display: flex; align-items: center; padding: 10px 8px 4px; }
  x-sidebar .tree .overview { margin-bottom: 4px; }
  x-sidebar details > summary { display: flex; align-items: center; gap: 4px; height: var(--side-item-h); padding: 0 4px; border-radius: var(--r-1); cursor: pointer; list-style: none; color: var(--fg); font-weight: 600; position: relative; font-size: 14px; }
  x-sidebar details > summary::-webkit-details-marker { display: none; }
  x-sidebar details > summary:hover { background: var(--hover); }
  x-sidebar details > summary .tw { display: inline-flex; color: var(--faint); transition: transform .12s; }
  x-sidebar details[open] > summary .tw { transform: rotate(90deg); }
  x-sidebar details > summary a { flex: 1; padding: 0 2px; height: auto; color: inherit; font-weight: 600; min-width: 0; }
  x-sidebar details > summary a:hover { background: none; }
  x-sidebar details > summary .pill.xs { opacity: 0; }
  x-sidebar details > summary:hover .pill.xs { opacity: 1; }
  .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
  .dot.lg { width: 14px; height: 14px; }
  /* a project dot follows its status (cbDecorate maps data-v onto the pill palette) */
  .dot.c0 { background: var(--pc0-bg); } .dot.c1 { background: var(--pc1-bg); } .dot.c2 { background: var(--pc2-bg); }
  .dot.c3 { background: var(--pc3-bg); } .dot.c4 { background: var(--pc4-bg); } .dot.c5 { background: var(--pc5-bg); }
  .dot.c6 { background: var(--pc6-bg); } .dot.c7 { background: var(--pc7-bg); } .dot.c8 { background: var(--pc8-bg); }
  .dot[data-v]:not([class*="c"]) { background: var(--faint); }
  .ppin[aria-pressed="true"] { color: var(--warn, #d9730d); }
  .pill.xs { height: 16px; line-height: 16px; font-size: 10px; padding: 0 5px; }
  x-sidebar .tnode { padding-left: 12px; position: relative; }
  x-sidebar .tnode > a { padding-right: 26px; }
  x-sidebar .tnode .star { position: absolute; right: 2px; top: 4px; width: 22px; height: 22px; opacity: 0; color: var(--faint); }
  x-sidebar .tnode:hover .star, x-sidebar .tnode .star[aria-pressed="true"] { opacity: 1; }
  x-sidebar .tnode .star[aria-pressed="true"] { color: #e0a319; }
  x-sidebar .tnode .star svg { fill: none; }
  x-sidebar .tnode .star[aria-pressed="true"] svg { fill: currentColor; }
  x-sidebar > section > header { height: 40px; }
  x-sidebar .tree h6 { padding: 8px 8px 2px; }
  x-sidebar [data-recent] a, x-sidebar [data-favs] a { height: 26px; }
  x-sidebar [data-f][data-hide] { display: none; }
  x-sidebar [data-favs]:empty::after { content: "Star a table to pin it here"; display: block; color: var(--faint); font-size: 12px; padding: 4px 8px; }
  x-sidebar [data-recent]:empty::after { content: "Records you open appear here"; display: block; color: var(--faint); font-size: 12px; padding: 4px 8px; }
  x-sidebar [data-recent] a, x-sidebar [data-favs] a { display: flex; align-items: center; gap: 8px; height: 28px; padding: 0 8px; border-radius: var(--r-1); color: var(--muted); font-size: 13px; }
  x-sidebar [data-recent] a:hover, x-sidebar [data-favs] a:hover { background: var(--hover); color: var(--fg); }
  x-sidebar [data-recent] a span, x-sidebar [data-favs] a span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-sidebar .mspaces { display: none; }
  .popover.ws-menu { min-width: 280px; }
  .ws-menu .who { display: flex; align-items: center; gap: 10px; padding: 8px; }
  .ws-menu .who b { display: block; font-size: 13px; }
  .ws-menu .who span { display: block; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; }
  .ws-menu .wsi { display: flex; align-items: center; gap: 8px; width: 100%; height: var(--menu-item-h); padding: 0 8px; border-radius: var(--r-1); }
  .ws-menu .wsi:hover { background: var(--hover); }
  .ws-menu .wsi .ws-mark { width: 20px; height: 20px; font-size: 11px; line-height: 20px; }
  .ws-menu .wsi[aria-current] { background: var(--hover-2); }
  .ws-menu .wsi .ico { margin-left: auto; color: var(--accent); }
  .ws-menu .theme { display: flex; align-items: center; justify-content: space-between; padding: 4px 8px; }
  .side-backdrop { display: none; }
  body[data-collapsed] x-sidebar { width: 0; flex-basis: 0; border-right: 0; }
  x-topbar .expand { display: none; }
  body[data-collapsed] x-topbar .expand { display: inline-flex; }
  x-topbar .topbar-right .modes { display: inline-flex; gap: 2px; }
  x-topbar .bell { position: relative; }
  x-topbar .bell .badge { position: absolute; top: 0; right: 0; }
  x-topbar .topbar-right .btn.sm { margin: 0 6px; }

  /* ---------- main / topbar ---------- */
  /* the only vertical scroller on a normal page; x-topbar stays sticky inside it */
  main { flex: 1; min-width: 0; min-height: 0; height: 100%; display: flex; flex-direction: column; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; }
  x-topbar { display: flex; align-items: center; gap: 6px; height: 44px; padding: 0 12px 0 10px; flex: 0 0 44px; font-size: 13px; position: sticky; top: 0; background: var(--bg); z-index: var(--z-topbar); }
  x-topbar .crumbs { display: flex; align-items: center; gap: 2px; color: var(--muted); min-width: 0; overflow: hidden; white-space: nowrap; }
  x-topbar .crumbs a, x-topbar .crumbs span { padding: 3px 6px; border-radius: 3px; overflow: hidden; text-overflow: ellipsis; max-width: 240px; }
  x-topbar .crumbs a:hover { color: var(--fg); background: var(--hover); }
  x-topbar .crumbs > :last-child { color: var(--fg); font-weight: 500; }
  x-topbar .crumbs .sep { color: var(--faint); padding: 0; flex: 0 0 auto; }
  x-topbar .topbar-right { margin-left: auto; display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }
  /* one New per page: where the view bar carries its own, the top bar's steps aside (Notion has one) */
  body:has(x-viewbar .tool.primary) x-topbar .topbar-right > .pop-anchor:has([data-new-open]) { display: none; }
  x-topbar .topbar-right .txt { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 8px; border-radius: var(--r-1); color: var(--muted); font-size: 12px; }
  x-topbar .topbar-right .txt:hover { background: var(--hover); color: var(--fg); }
  /* Sticks under the 44px topbar rather than floating, so it can never be scrolled past, never
     covers the mobile rail, and stays below the topbar in the same z scale. */
  x-impersonating { position: sticky; top: 44px; z-index: var(--z-stickychrome); display: flex; align-items: center; gap: 8px; padding: 6px 12px; background: var(--warn-bg); color: var(--fg); border-bottom: 1px solid var(--border); font-size: 13px; }
  .live-bar { display: flex; align-items: center; gap: 12px; margin: 0 16px; padding: 6px 12px; background: var(--info-bg); color: var(--info-fg); border-radius: var(--r-2); font-size: 13px; }
  .live-bar a { font-weight: 600; text-decoration: underline; }
  .live-bar .icon-btn { margin-left: auto; }
  .page { flex: 1; padding: 0 0 48px; min-width: 0; }
  x-page { display: block; --gx: 24px; padding: 16px var(--gx) 0; margin: 0 auto; width: 100%; max-width: 100%; }
  x-page.narrow { max-width: calc(760px + var(--gx) * 2); }
  x-page.mid { max-width: calc(1100px + var(--gx) * 2); }
  x-page.wide { max-width: none; }
  .page-title { margin-bottom: 4px; padding: 0 2px; overflow-wrap: anywhere; }
  .page-head { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 8px; flex-wrap: wrap; }
  .page-head .page-title { margin: 0; }
  .page-head .sub { color: var(--muted); font-size: 13px; margin-top: 4px; }
  .page-head .actions { margin-left: auto; display: flex; gap: 6px; align-items: center; }
  /* a table view's header star: Favorite, as in the sidebar */
  .page-head.thead { align-items: center; }
  /* a chosen icon (emoji, image or set icon) anywhere an object's icon is drawn */
  .ico.emo { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; font-size: 14px; line-height: 1; font-style: normal; vertical-align: -3px; }
  .ico.oimg { width: 16px; height: 16px; object-fit: contain; border-radius: 3px; vertical-align: -3px; }
  .ico.emo.lg, .ico.oimg.lg, svg.ico.lg { width: 28px; height: 28px; font-size: 24px; }
  .oicon { display: inline-flex; align-items: center; justify-content: center; min-width: 36px; height: 36px; padding: 0 4px; border: 0; background: none; border-radius: var(--r-2); color: var(--muted); cursor: pointer; }
  .oicon:hover:not(:disabled) { background: var(--hover); }
  .oicon:disabled { cursor: default; }
  /* the icon picker (iconpick.js) */
  .popover.iconpick { width: 360px; padding: 6px; }
  .iconpick .ip-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
  .iconpick .ip-tab { border: 0; background: none; padding: 6px 8px; font-size: 13px; color: var(--muted); border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; }
  .iconpick .ip-tab[aria-selected="true"] { color: var(--fg); border-bottom-color: var(--fg); }
  .iconpick .ip-q { width: 100%; height: 30px; margin-bottom: 6px; }
  .iconpick .ip-grid { max-height: 300px; overflow-y: auto; }
  .iconpick .ip-row { display: flex; flex-wrap: wrap; gap: 2px; padding: 2px 0 6px; }
  .iconpick .ip-e { width: 32px; height: 32px; border: 0; background: none; border-radius: var(--r-1); font-size: 20px; line-height: 1; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; color: var(--fg); }
  .iconpick .ip-e:hover { background: var(--hover); }
  .iconpick .ip-row.icons .ico { width: 18px; height: 18px; }
  .iconpick .ip-drop { display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 22px 12px; border: 1px dashed var(--border-2); border-radius: var(--r-2); cursor: pointer; color: var(--muted); font-size: 12px; }
  .iconpick .ip-drop b { color: var(--fg); font-size: 13px; }
  .iconpick .ip-drop:hover { background: var(--hover); }
  .iconpick .ip-url { display: flex; gap: 6px; margin-top: 8px; }
  .iconpick .ip-url input { flex: 1; height: 30px; }
  .iconpick .ip-foot { display: flex; justify-content: flex-end; border-top: 1px solid var(--border); margin-top: 6px; padding-top: 6px; }
  /* header properties panel (hdrprops.js), drawn like View settings > Properties */
  .popover.hdrprops { width: 260px; padding: 6px; }
  .hdrprops .hp-sec { font-size: 11px; color: var(--faint); text-transform: uppercase; letter-spacing: .04em; padding: 8px 6px 2px; }
  .hdrprops .hp-row { display: flex; align-items: center; gap: 6px; height: 30px; padding: 0 4px; border-radius: var(--r-1); }
  .hdrprops .hp-row:hover { background: var(--hover); }
  .hdrprops .hp-row:not([draggable="true"]) .grip { visibility: hidden; }
  .hdrprops .hp-row .ico-wrap { display: inline-flex; color: var(--muted); }
  .hdrprops .hp-row .lbl { flex: 1; font-size: 13px; }
  .hdrprops .hp-row:not([draggable="true"]) .lbl { color: var(--muted); }
  .hdrprops .hp-foot { display: flex; justify-content: space-between; border-top: 1px solid var(--border); margin-top: 6px; padding-top: 6px; }
  .phead .pdesc .ellip { max-width: 260px; }
  .page-head.thead .star { color: var(--faint); }
  .page-head.thead .star[aria-pressed="true"] { color: #e0a319; }
  .page-head.thead .star[aria-pressed="true"] svg { fill: currentColor; }
  .cardgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; }
  .tplgrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
  .tplgrid label { display: flex; flex-direction: column; gap: 4px; padding: 8px; border: 1px solid var(--border); border-radius: var(--r-2); cursor: pointer; font-size: 12px; position: relative; }
  .tplgrid label:hover { background: var(--hover); }
  .tplgrid label:has(input:checked) { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); background: var(--selected); }
  /* a choice this surface cannot offer stays visible, so the menu is the same everywhere */
  .tplgrid label[data-off] { opacity: .45; cursor: not-allowed; }
  .tplgrid label[data-off]:hover { background: none; }
  .tplgrid label input { position: absolute; opacity: 0; }
  .tplgrid label b { display: flex; align-items: center; gap: 6px; font-weight: 600; min-width: 0; overflow-wrap: anywhere; }
  .tplgrid label small { color: var(--muted); font-size: 11px; line-height: 1.3; min-width: 0; overflow-wrap: anywhere; }
  .hscroll { display: flex; gap: 12px; overflow-x: auto; padding: 4px 2px 12px; scroll-snap-type: x proximity; scrollbar-width: thin; }
  .hscroll > * { scroll-snap-align: start; }
  x-recent { display: flex; flex-direction: column; gap: 6px; flex: 0 0 200px; width: 200px; padding: 12px; border: 1px solid var(--border); border-radius: var(--r-3); background: var(--bg); cursor: pointer; min-height: 96px; transition: box-shadow var(--t); }
  x-recent:hover { box-shadow: var(--shadow); }
  x-recent .rt { font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.3; }
  x-recent .rm { display: flex; align-items: center; gap: 6px; color: var(--muted); font-size: 12px; margin-top: auto; min-width: 0; }
  x-recent .rm > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-recent .rm time { margin-left: auto; color: var(--faint); }
  x-upcoming { display: block; border: 1px solid var(--border); border-radius: var(--r-3); }
  x-upcoming .up { display: flex; align-items: center; gap: 10px; height: 40px; padding: 0 12px; border-bottom: 1px solid var(--border); cursor: pointer; font-size: 13px; }
  x-upcoming .up:last-child { border-bottom: 0; }
  x-upcoming .up:hover { background: var(--hover); }
  x-upcoming .up .rt { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
  x-upcoming .up time { color: var(--muted); font-size: 12px; }
  .greeting { margin-bottom: 4px; }
  .home-sub { color: var(--muted); font-size: 13px; }

  /* ---------- viewbar ---------- */
  x-viewbar { display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--border); margin-bottom: 0; font-size: 13px; min-width: 0; }
  /* flex-end, not stretch: the tabs have a definite 32px height, so `stretch` degrades to
     flex-start and parked them at the TOP of the 40px strip — the active tab's 2px underline
     then floated 8px clear of the bar's own bottom border, which is the line the -1px margin
     below is there to overlap. */
  x-viewbar .tabs { display: flex; align-items: flex-end; gap: 2px; min-width: 0; height: 40px; overflow-x: auto; overflow-y: hidden; scrollbar-width: none; flex: 1 1 auto; }
  x-viewbar .tabs::-webkit-scrollbar { display: none; }
  x-viewbar .tabs::-webkit-scrollbar { display: none; }
  x-viewbar .tabs a, x-viewbar .tab-add {
    display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 8px; color: var(--muted); font-weight: 500; white-space: nowrap;
    border-bottom: 2px solid transparent; margin-bottom: -1px; border-radius: 3px 3px 0 0; flex: 0 0 auto;
  }
  x-viewbar .tabs a:hover, x-viewbar .tab-add:hover { background: var(--hover); color: var(--fg); }
  x-viewbar .tabs a[aria-current] { color: var(--fg); border-bottom-color: var(--fg); }
  x-viewbar .tab-add { color: var(--faint); }
  /* the pinned New view button: never part of the scroll, never squeezed by a long tab strip.
     It sits on the same baseline as the tabs it follows — stretched to the bar's full 40px it
     was visibly taller than every tab beside it. */
  x-viewbar > .pop-anchor.newview { flex: 0 0 auto; align-self: flex-end; }
  x-viewbar .tools { display: flex; align-items: center; gap: 2px; margin-left: auto; flex: 0 0 auto; }
  x-viewbar .tool { display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 8px; border-radius: var(--r-1); color: var(--muted); font-weight: 500; white-space: nowrap; font-size: 13px; }
  x-viewbar .tool:hover:not([disabled]) { background: var(--hover); color: var(--fg); }
  x-viewbar .tool[disabled] { opacity: .45; cursor: default; }
  x-viewbar .tool.on { color: var(--accent); }
  x-viewbar .tool.icon-only { padding: 0 6px; }
  x-viewbar .cluster.between { justify-content: space-between; }
  .toolbar-2 { display: flex; align-items: center; gap: 8px; height: 40px; font-size: 12px; color: var(--muted); }
  .toolbar-2 .sp { flex: 1; }

  /* ---------- grid ---------- */
  x-grid {
    --gutter-w: 44px; --title-w: 280px; --status-w: 140px; --cell-w: 160px; --gfoot-h: 30px;
    display: block; margin: 0 calc(-1 * var(--gx)); padding: 0 var(--gx); overflow: auto; font-size: 13px; position: relative;
    max-height: calc(100vh - 44px - 130px); max-height: calc(100dvh - 44px - 130px); overscroll-behavior-x: contain;
  }
  x-grid[data-rh="short"] { --row-h: 32px; }
  x-grid[data-rh="medium"] { --row-h: 48px; }
  x-grid[data-rh="tall"] { --row-h: 76px; }
  x-ghead { display: flex; position: sticky; top: 0; z-index: var(--z-stickyhead); background: var(--bg); height: 32px; border-bottom: 1px solid var(--border-2); min-width: max-content; }
  x-hcell {
    display: flex; align-items: center; gap: 4px; height: 32px; padding: 0 8px; flex: 0 0 var(--cell-w); width: var(--cell-w);
    border-right: 1px solid var(--border); color: var(--muted); font-weight: 500; position: relative; white-space: nowrap; font-size: 12.5px;
  }
  x-hcell:hover { background: var(--bg-2); }
  x-hcell .hn { display: flex; align-items: center; gap: 6px; min-width: 0; flex: 1; overflow: hidden; cursor: pointer; height: 100%; }
  x-hcell .hn > span { overflow: hidden; text-overflow: ellipsis; }
  x-hcell .hn svg { color: var(--faint); }
  x-hcell .sortdir { display: inline-flex; flex: 0 0 auto; }
  x-hcell .sortdir svg { width: 12px; height: 12px; color: var(--accent); }
  x-hcell[data-sort-desc] .sortdir { transform: rotate(180deg); }
  x-hcell .hmenu { position: static; display: inline-flex; }
  x-hcell .hbtn { opacity: 0; width: 22px; height: 22px; }
  x-hcell:hover .hbtn, x-hcell .hbtn:focus-visible { opacity: 1; }
  x-hcell .rz { position: absolute; right: -3px; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 2; }
  x-hcell .rz:hover, x-hcell .rz[data-on] { background: var(--accent); width: 3px; right: -1px; }
  /* while the drag is live the line runs the height of the grid, so the new edge is judged
     against the rows it cuts rather than against 32px of header */
  x-hcell .rz[data-on]::after { content: ""; position: absolute; left: 0; top: 0; width: 100%; height: 100vh; background: var(--accent); }
  x-hcell.gutter, x-cell.gutter { flex: 0 0 var(--gutter-w); width: var(--gutter-w); justify-content: center; padding: 0; position: sticky; left: 0; z-index: 2; background: var(--bg); }
  x-hcell.title, x-cell.title { flex: 0 0 var(--title-w); width: var(--title-w); position: sticky; left: var(--gutter-w); z-index: 2; background: var(--bg); box-shadow: var(--frz-shadow); }
  /* the frozen headers paint an opaque background of their own, which cancelled the hover every
     other header cell answers to - so the two columns always on screen were the two that felt dead */
  x-hcell.gutter:hover, x-hcell.title:hover { background: var(--bg-2); }
  x-hcell.status, x-cell.status { flex: 0 0 var(--status-w); width: var(--status-w); }
  /* a table whose records carry no status (contacts, companies, meetings) hides the column */
  x-grid[data-nostatus] :is(x-hcell, x-cell, x-scell).status { display: none; }
  x-hcell.addcol { flex: 0 0 40px; width: 40px; padding: 0; justify-content: center; overflow: visible; border-right: 0; }
  /* the whole 40px cell is the target, the way the trailing + column is in every grid it copies */
  x-hcell.addcol .hmenu, x-hcell.addcol .icon-btn { width: 100%; height: 100%; border-radius: 0; }
  x-hcell.filler, x-cell.filler { flex: 1 1 40px; width: auto; border-right: 0; }
  x-gbody { display: block; position: relative; min-width: max-content; }
  x-gbody .spacer { width: 1px; }
  x-gbody .rows { position: absolute; top: 0; left: 0; right: 0; }
  x-row {
    display: flex; height: var(--row-h); border-bottom: 1px solid var(--border); contain: strict; width: 100%; background: var(--bg);
    position: absolute; left: 0; top: 0; will-change: transform; min-width: max-content;
  }
  x-row:hover, x-row:hover x-cell.gutter, x-row:hover x-cell.title { background: var(--bg-2); }
  x-row[aria-selected="true"], x-row[aria-selected="true"] x-cell.gutter, x-row[aria-selected="true"] x-cell.title { background: var(--selected); }
  x-row.grp { background: var(--bg-side); position: absolute; contain: strict; cursor: pointer; }
  x-row.grp x-cell { border-right: 0; background: transparent; box-shadow: none; }
  x-row.grp .gh { display: flex; align-items: center; gap: 8px; position: sticky; left: 8px; font-weight: 600; }
  x-row.grp .gh .tw { display: inline-flex; color: var(--faint); transition: transform .12s; background: none; border: 0; padding: 0; cursor: pointer; border-radius: 4px; }
  x-row.grp .gh .tw:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
  x-row.grp[data-collapsed] .gh .tw { transform: rotate(-90deg); }
  x-row.grp .gh .n { color: var(--faint); font-weight: 500; font-size: 12px; }
  x-cell {
    display: flex; align-items: center; height: var(--row-h); padding: 0 8px; flex: 0 0 var(--cell-w); width: var(--cell-w);
    border-right: 1px solid var(--border); overflow: hidden; white-space: nowrap; outline: none; position: relative;
    /* Column virtualisation without a second windowing engine: rows already virtualise
       vertically, and this lets the browser skip layout+paint for cells scrolled out
       horizontally. The size hint keeps the row width stable so nothing reflows on scroll.
       Excluded below: sticky columns and the cell being edited must always render. */
    content-visibility: auto;
    contain-intrinsic-size: auto var(--cell-w) var(--row-h);
  }
  /* sticky columns are exempted by the generated freeze CSS (gridx.js); these are the
     structural ones plus whatever is being edited or focused */
  x-cell.gutter, x-cell.title, x-cell.editing, x-cell:focus-within { content-visibility: visible; }
  /* a grid cell fills the row's CONTENT height; the row's bottom border sits below it. A full
     --row-h overlapped that border and the row's paint containment clipped the overlap, which
     cut the bottom edge of the selection ring to half its width. */
  x-row > x-cell { height: 100%; }
  x-cell .v { overflow: hidden; text-overflow: ellipsis; }
  x-cell .v.num { margin-left: auto; font-variant-numeric: tabular-nums; }
  x-cell .v.md { color: var(--muted); }
  x-cell .who { display: inline-flex; align-items: center; }
  /* The focused cell's ring: ONE 2px border drawn inside the cell's padding box - the same box
     the range layer below draws in - so every edge is 2px of accent beside the 1px grid line.
     An outline here as well doubled the left and right edges, because an outline is drawn on the
     border box (over the cell's own right border) while the range ring sits inside it. */
  x-cell[data-focus]::after, x-cell:focus-visible::after { content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 1; border: 2px solid var(--accent); }
  x-cell[data-writable] { cursor: text; }
  x-cell[data-type="checkbox"][data-writable], x-cell[data-type="select"][data-writable], x-cell[data-type="status"][data-writable] { cursor: pointer; }
  x-cell.saving { opacity: .55; }
  /* A refused write used to leave nothing behind but a toast that had already gone, so the one
     cell out of a screenful that did not save was unfindable. It clears on the next edit. */
  x-cell[data-err] { outline: 2px solid var(--danger); outline-offset: -2px; background: var(--danger-bg); }
  x-cell.editing { padding: 0; overflow: visible; z-index: var(--z-active); outline: 2px solid var(--accent); outline-offset: -1px; box-shadow: var(--shadow); background: var(--bg); }
  x-cell.editing > input, x-cell.editing > select { height: 100%; border: 0; border-radius: 0; padding: 0 8px; box-shadow: none; background: transparent; }
  x-cell.editing > x-select { width: 100%; height: 100%; }
  x-cell.editing > x-select > .xs-btn { height: 100%; border: 0; border-radius: 0; background: transparent; }
  /* gutter: the row number and the checkbox occupy the SAME centered box, so the row
     checkbox lines up exactly with the header's select-all (Notion behaviour) */
  x-hcell.gutter, x-cell.gutter { position: sticky; }
  x-cell.gutter .rn, x-cell.gutter .sel, x-hcell.gutter .sel-all {
    position: absolute; left: calc(50% + 6px); top: 50%; transform: translate(-50%, -50%); margin: 0;
  }
  x-cell.gutter .rn { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
  x-cell.gutter .sel, x-hcell.gutter .sel-all { width: 14px; height: 14px; accent-color: var(--accent); cursor: pointer; }
  x-cell.gutter .sel { opacity: 0; }
  x-row:hover .gutter .rn, x-row[aria-selected="true"] .gutter .rn { opacity: 0; }
  x-row:hover .gutter .sel, x-row[aria-selected="true"] .gutter .sel, x-cell.gutter .sel:focus-visible { opacity: 1; }
  x-cell.title .v { font-weight: 500; }
  /* one hover affordance group at the right of the title cell: [Open] [⋯] */
  x-cell.title .rowacts { display: none; margin-left: auto; flex: 0 0 auto; align-items: center; gap: 4px; padding-left: 6px; }
  x-row:hover x-cell.title .rowacts, x-cell.title:focus-within .rowacts { display: inline-flex; }
  x-cell.title .rowacts .open { display: inline-flex; align-items: center; gap: 4px; height: 22px; padding: 0 6px; border-radius: 3px; font-size: 11px; color: var(--muted); background: var(--bg); box-shadow: 0 0 0 1px var(--border); }
  x-cell.title .rowacts .rowmenu { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 3px; color: var(--muted); background: var(--bg); box-shadow: 0 0 0 1px var(--border); }
  x-cell.title .rowacts .open:hover, x-cell.title .rowacts .rowmenu:hover { background: var(--hover); color: var(--fg); }
  x-cell.status .pill { max-width: 100%; }
  /* the whole line is the affordance, not just the 300px input parked in it: clicking anywhere
     on the row starts the title, and the + creates the blank record outright */
  x-addrow { display: flex; align-items: center; height: var(--row-h); border-bottom: 1px solid var(--border); position: sticky; left: 0; color: var(--faint); min-width: 100%; cursor: text; }
  x-addrow .gutter { display: inline-flex; align-items: center; width: var(--gutter-w); height: 100%; justify-content: center; color: var(--faint); border-radius: 0; cursor: pointer; }
  x-addrow .gutter:hover { background: var(--hover); color: var(--fg); }
  x-addrow .gutter:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  x-addrow input { border: 0; box-shadow: none; padding: 0 8px; width: 300px; max-width: calc(100vw - 100px); background: transparent; height: 100%; }
  x-addrow input::placeholder { color: var(--faint); }
  x-addrow:hover { background: var(--bg-2); }
  /* Airtable, NocoDB and Baserow all PIN the record count: it answers "how big is this table",
     and sitting in flow it was only readable once you had scrolled to the very last row. */
  .gfoot {
    position: sticky; left: 0; bottom: 0; z-index: var(--z-stickychrome); display: flex; align-items: center; gap: var(--s-3);
    height: var(--gfoot-h); padding: 0 var(--s-2) 0 var(--s-3); background: var(--bg); border-top: 1px solid var(--border);
    color: var(--muted); font-size: 12px;
  }
  .gfoot .count { font-variant-numeric: tabular-nums; }
  .gfoot .selc { color: var(--accent); font-weight: 500; font-variant-numeric: tabular-nums; }
  .gfoot .qres { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--faint); }
  .gfoot .selc:empty, .gfoot .qres:empty { display: none; }
  x-selbar {
    position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%); z-index: var(--z-pop); display: flex; align-items: center; gap: 8px;
    padding: 6px 8px 6px 14px; background: var(--fg); color: var(--bg); border-radius: var(--r-3); box-shadow: var(--shadow-lg); font-size: 13px; max-width: calc(100vw - 16px); flex-wrap: wrap;
  }
  x-selbar .n { font-weight: 600; margin-right: 6px; }
  x-selbar .ghost { color: inherit; opacity: .8; }
  x-selbar .ghost:hover { background: rgba(128,128,128,.25); opacity: 1; color: inherit; }
  x-selbar select { width: auto; height: 28px; background-color: transparent; color: inherit; border-color: rgba(128,128,128,.4); font-size: 12px; }
  x-selbar select option { color: var(--fg); background: var(--bg); }
  x-selbar .btn.danger { height: 28px; }

  /* ---------- board ---------- */
  x-board { display: flex; gap: 12px; align-items: flex-start; overflow-x: auto; padding: 16px 0 24px; min-height: 60vh; scroll-snap-type: x proximity; margin: 0 calc(-1 * var(--gx)); padding-left: var(--gx); padding-right: var(--gx); }
  x-kanban-column { display: flex; flex-direction: column; flex: 0 0 272px; width: 272px; max-height: calc(100vh - 220px); border-radius: var(--r-2); scroll-snap-align: start; transition: flex-basis var(--t), width var(--t); }
  x-kanban-column[data-collapsed] { flex-basis: 40px; width: 40px; }
  x-kanban-column[data-collapsed] > header { flex-direction: column; height: auto; padding: 8px 0; gap: 6px; }
  x-kanban-column[data-collapsed] > header .pill { writing-mode: vertical-rl; height: auto; padding: 6px 0; line-height: 20px; }
  x-kanban-column[data-collapsed] > header .add, x-kanban-column[data-collapsed] > header .sum, x-kanban-column[data-collapsed] > .cards, x-kanban-column[data-collapsed] > .addbtn, x-kanban-column[data-collapsed] > .newcard { display: none; }
  x-kanban-column[data-collapsed] > header .colmenu { display: none; }
  x-kanban-column > header { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 4px; font-size: 13px; }
  x-kanban-column > header .count { color: var(--faint); font-size: 12px; }
  x-kanban-column > header .sum { color: var(--faint); font-size: 11px; font-variant-numeric: tabular-nums; }
  x-kanban-column > header .add, x-kanban-column > header .colmenu { opacity: 0; }
  x-kanban-column > header .add { margin-left: auto; }
  x-kanban-column:hover > header .add, x-kanban-column:hover > header .colmenu { opacity: 1; }
  x-kanban-column > .cards { display: flex; flex-direction: column; gap: 6px; overflow-y: auto; min-height: 24px; padding: 2px; border-radius: var(--r-2); transition: background var(--t); }
  x-kanban-column[data-over] > .cards { background: var(--selected); }
  x-kanban-column .newcard input { margin: 4px 2px; width: calc(100% - 4px); }
  x-kanban-column .addbtn { margin: 4px 0; color: var(--faint); }
  x-kanban-column[data-empty][data-hide-empty] { display: none; }
  x-card {
    display: block; padding: 8px 10px; background: var(--bg); border-radius: var(--r-2); box-shadow: 0 0 0 1px var(--border), 0 1px 2px rgba(0,0,0,.04);
    cursor: pointer; font-size: 13px; outline: none; transition: box-shadow var(--t), transform var(--t), opacity var(--t);
  }
  x-card:hover { background: var(--bg-2); box-shadow: 0 0 0 1px var(--border-2), 0 2px 6px rgba(0,0,0,.08); }
  /* the record's ⋯ (the shared record menu), on hover, as on table and gantt rows */
  x-card, x-gcard, .tl-card { position: relative; }
  x-card > .more, x-gcard > .more, .tl-card .more { position: absolute; top: 4px; right: 4px; opacity: 0; background: var(--bg); }
  x-card:hover > .more, x-gcard:hover > .more, .tl-card:hover .more, x-card > .more:focus-visible, x-gcard > .more:focus-visible, .tl-card .more:focus-visible { opacity: 1; }
  x-card:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
  x-card[data-dragging] { opacity: .4; transform: rotate(1deg); }
  /* card size and cover, saved with the view as a gallery's are */
  /* Sub-group: lanes stacked, each a row of the same columns (view_board.html) */
  x-board[data-subgroup] { display: block; }
  x-board .kb-lane + .kb-lane { margin-top: 16px; }
  x-board .kb-cols { display: flex; gap: 12px; align-items: flex-start; }
  x-board[data-size="s"] .kb-cols > x-kanban-column:not([data-collapsed]) { flex-basis: 220px; width: 220px; }
  x-board[data-size="l"] .kb-cols > x-kanban-column:not([data-collapsed]) { flex-basis: 340px; width: 340px; }
  x-board { --cover-h: 56px; }
  x-board[data-size="s"] { --cover-h: 40px; }
  x-board[data-size="l"] { --cover-h: 96px; }
  x-card > .cover { margin: -8px -10px 8px; border-radius: var(--r-2) var(--r-2) 0 0; }
  @media (min-width: 900px) {
    x-board[data-size="s"] > x-kanban-column:not([data-collapsed]) { flex-basis: 220px; width: 220px; }
    x-board[data-size="l"] > x-kanban-column:not([data-collapsed]) { flex-basis: 340px; width: 340px; }
  }
  x-card h4 { font-weight: 500; font-size: 13px; margin-bottom: 4px; overflow-wrap: anywhere; }
  x-card .chips { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
  /* a card whose fields are all empty kept the 4px gutter under its title and sat optically
     high in its own box, next to cards that did not */
  x-card .chips:empty { display: none; }
  x-card:has(> .chips:empty) h4 { margin-bottom: 0; }
  x-card .chips .pill + .pill { margin-left: 0; }
  x-card .chips .avatar { margin: 0; }
  .drop-ph { height: 40px; border-radius: var(--r-2); border: 1px dashed var(--accent); background: var(--selected); }

  /* ---------- list ---------- */
  x-list { display: block; padding-top: 8px; }
  /* a grouped list's section heads (Group), as a board's column heads */
  x-list > h6.lgroup { display: flex; align-items: center; gap: 8px; margin: 16px 0 4px; }
  x-list > h6.lgroup:first-child { margin-top: 4px; }
  x-list > h6.lgroup .n { color: var(--faint); font-weight: 500; }
  x-item { display: flex; align-items: center; gap: 12px; min-height: 32px; padding: 0 6px; margin: 0 -6px; border-radius: var(--r-1); cursor: pointer; border-bottom: 1px solid var(--border); font-size: 14px; }
  x-item:hover { background: var(--hover); }
  x-item .ti { display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1; }
  x-item .ti > span, x-item .ti x-cell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-item .ti x-cell { border: 0; background: transparent; padding: 2px 4px; height: auto; min-height: 26px; flex: 1; width: auto; border-radius: 3px; }
  x-item .ti x-cell.editing > input { height: 26px; }
  x-item .props { display: flex; align-items: center; gap: 8px; font-size: 12px; flex: 0 0 auto; }
  x-item .props .pill + .pill { margin-left: 0; }
  x-item .props .hov { opacity: 0; transition: opacity var(--t); }
  x-item:hover .props .hov { opacity: 1; }
  x-item .props .open { display: none; }
  x-item:hover .props .open { display: inline-flex; }
  x-list .newitem { display: flex; align-items: center; gap: 8px; height: 32px; padding: 0 6px; margin: 0 -6px; color: var(--faint); }
  x-list .newitem input, x-gallery .newcard input { border: 0; box-shadow: none; padding: 0; background: transparent; }
  p.count { font-size: 12px; margin-top: 8px; }
  p.loadmore { display: flex; justify-content: center; margin: 12px 0 0; }

  /* ---------- gallery ---------- */
  x-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--card-w, 240px), 1fr)); gap: 16px; padding: 16px 0; --cover-h: 72px; }
  x-gallery[data-size="s"] { --card-w: 180px; --cover-h: 48px; }
  x-gallery[data-size="l"] { --card-w: 320px; --cover-h: 110px; }
  x-gcard { display: flex; flex-direction: column; border-radius: var(--r-3); box-shadow: 0 0 0 1px var(--border); overflow: hidden; cursor: pointer; background: var(--bg); outline: none; transition: transform var(--t), box-shadow var(--t); }
  x-gcard:hover { box-shadow: var(--shadow); transform: translateY(-2px); }
  x-gcard:focus-visible { box-shadow: 0 0 0 2px var(--accent); }
  /* the card cover, on a gallery card and (View settings > Layout > Show card cover) a board card */
  :is(x-gcard, x-card) > .cover { height: var(--cover-h); background: linear-gradient(135deg, var(--pc5-bg), var(--pc6-bg)); }
  :is(x-gcard, x-card) > .cover.c0 { background: linear-gradient(135deg, var(--pc0-bg), var(--pc1-bg)); } :is(x-gcard, x-card) > .cover.c1 { background: linear-gradient(135deg, var(--pc1-bg), var(--pc2-bg)); }
  :is(x-gcard, x-card) > .cover.c2 { background: linear-gradient(135deg, var(--pc2-bg), var(--pc3-bg)); } :is(x-gcard, x-card) > .cover.c3 { background: linear-gradient(135deg, var(--pc3-bg), var(--pc4-bg)); }
  :is(x-gcard, x-card) > .cover.c4 { background: linear-gradient(135deg, var(--pc4-bg), var(--pc5-bg)); } :is(x-gcard, x-card) > .cover.c6 { background: linear-gradient(135deg, var(--pc6-bg), var(--pc7-bg)); }
  :is(x-gcard, x-card) > .cover.c7 { background: linear-gradient(135deg, var(--pc7-bg), var(--pc8-bg)); } :is(x-gcard, x-card) > .cover.c8 { background: linear-gradient(135deg, var(--pc8-bg), var(--pc1-bg)); }
  x-gcard h4 { padding: 10px 12px 4px; font-size: 14px; overflow-wrap: anywhere; }
  x-gcard .chips { display: flex; flex-wrap: wrap; gap: 4px; padding: 0 12px; }
  x-gcard .chips .pill + .pill { margin-left: 0; }
  x-gcard .preview { padding: 6px 12px 12px; color: var(--muted); font-size: 12px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; line-height: 1.4; }
  x-gcard .preview:empty { display: none; }
  x-gcard > :last-child { padding-bottom: 12px; }
  x-gallery .newcard { display: flex; align-items: center; gap: 8px; padding: 12px; border: 1px dashed var(--border-2); border-radius: var(--r-3); color: var(--faint); min-height: 80px; }

  /* ---------- timeline (gantt) ---------- */
  /* ---- vertical timeline (date rail · status spine · card) ---- */
  x-timeline { display: block; padding: 8px 0 24px; --rail-w: 68px; --spine-x: 10px; position: relative; font-size: 13px; }
  x-timeline .tl-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 8px 0 12px; }
  /* the zone strip (macros/timeline.html tl_zones), wherever a time view draws it */
  .tl-zones { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  .cal-zones, .gt-zones, .mw-zones { padding: 6px 0; }
  .tzchip { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 4px 0 8px; border: 1px solid var(--border-2); border-radius: 999px; font-size: 12px; color: var(--muted); background: var(--bg); cursor: grab; }
  /* dragged zone: the one being moved fades, so the gap it will land in is what reads */
  .tzchip[draggable]:active { cursor: grabbing; }
  .zdrag { opacity: .4; }
  .cal-head .gh[draggable] { cursor: grab; }
  .cal-head .gh[draggable]:active { cursor: grabbing; }
  .tzchip b { font-weight: 600; color: var(--fg); }
  .tzchip small { font-variant-numeric: tabular-nums; color: var(--faint); }
  .tzchip .x { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 50%; color: var(--faint); opacity: 0; }
  .tzchip:hover .x, .tzchip .x:focus-visible { opacity: 1; }
  .tzadd { display: inline-flex; align-items: center; gap: 4px; height: 26px; padding: 0 10px; border: 1px dashed var(--border-2); border-radius: 999px; color: var(--muted); font-size: 12px; }
  .tzadd:hover { color: var(--accent); border-color: var(--accent); }
  x-timeline .tl-list { list-style: none; margin: 0; padding: 0; }
  .tl-item { position: relative; display: grid; grid-template-columns: var(--rail-w) 20px 1fr; align-items: start; gap: 0 8px; padding: 0 0 18px; }
  .tl-date { text-align: right; padding-top: 10px; line-height: 1.15; }
  /* direct children only: the zone times nested below carry their own type scale */
  .tl-date > b { display: block; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
  .tl-date > small { display: block; font-size: 11px; color: var(--faint); }
  .tl-item[data-nodate] .tl-date > b { color: var(--faint); font-weight: 500; }
  .tl-spine { position: relative; align-self: stretch; }
  .tl-spine::before { content: ""; position: absolute; left: var(--spine-x); top: 0; bottom: -18px; width: 2px; background: var(--border); }
  .tl-item:last-child .tl-spine::before { bottom: 50%; }
  .tl-item:first-child .tl-spine::before { top: 14px; }
  .tl-spine .dot { position: absolute; left: calc(var(--spine-x) - 4px); top: 12px; width: 10px; height: 10px; border-radius: 50%; background: var(--pc0-bg); box-shadow: 0 0 0 3px var(--bg); }
  .tl-card { border-bottom: 1px solid var(--border); padding: 8px 8px 12px; border-radius: var(--r-2); cursor: pointer; }
  .tl-card:hover { background: var(--hover); }
  .tl-card:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  .tl-card > header { display: flex; align-items: center; gap: 8px; min-width: 0; }
  .tl-card h4 { font-size: 15px; font-weight: 600; margin: 0; min-width: 0; }
  .tl-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 4px; color: var(--muted); font-size: 12px; }
  .tl-meta .rng { display: inline-flex; align-items: center; gap: 4px; }
  .tl-meta .rng svg { width: 14px; height: 14px; color: var(--faint); }
  .tl-meta .pct { font-variant-numeric: tabular-nums; }
  .tl-meta .over { color: var(--danger); font-weight: 500; }
  .tl-card > .chips { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 6px; }
  .tl-card > .chips:empty { display: none; }
  .tl-card > footer { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 6px; font-size: 12px; color: var(--muted); }
  .tl-card > footer .st, .tl-card > footer .who { display: inline-flex; align-items: center; gap: 6px; }
  .dot.sm { width: 8px; height: 8px; border-radius: 50%; display: inline-block; background: var(--pc0-bg); }
  .avatar.xs { width: 18px; height: 18px; font-size: 10px; line-height: 18px; }
  /* One zone per line under the date it qualifies, in the same label-then-time order as the
     chips at the top of the view. The rail only widens when a row is actually showing times. */
  .tl-zonetimes { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; margin-top: 4px; font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; line-height: 1.35; }
  .tl-zonetimes > span { white-space: nowrap; }
  .tl-zonetimes b { font-weight: 600; color: var(--muted); margin-right: 3px; }
  x-timeline:has(.tl-zonetimes:not([hidden])) { --rail-w: 104px; }
  @media (max-width: 640px) {
    x-timeline { --rail-w: 52px; }
    x-timeline:has(.tl-zonetimes:not([hidden])) { --rail-w: 88px; }
    .tl-card h4 { font-size: 14px; }
  }

  /* ---------- calendar ---------- */
  x-calendar { display: block; margin-top: 8px; font-size: 12px; --hh: 48px; --gw: 64px; --days: 7; }
  .cal-nav { display: flex; align-items: center; justify-content: space-between; height: 48px; gap: 8px; flex-wrap: wrap; }
  .cal-nav .cluster { display: flex; align-items: center; gap: 4px; }
  .cal-nav .month { font-size: 16px; margin-left: 8px; white-space: nowrap; }
  .cal-scroll { overflow: auto; max-height: calc(100vh - 230px); border: 1px solid var(--border); border-radius: var(--r-2); }
  .cal-grid { min-width: calc(var(--gutters, 1) * var(--gw) + var(--days) * 120px); }
  .cal-head, .cal-body { display: grid; grid-template-columns: repeat(var(--gutters, 1), var(--gw)) repeat(var(--days), minmax(110px, 1fr)); }
  .cal-head { position: sticky; top: 0; z-index: var(--z-stickychrome); background: var(--bg); border-bottom: 1px solid var(--border-2); }
  /* the all-day strip sticks under the day header: the grid opens scrolled to work hours, which
     used to carry the strip (and every date-only record) out of sight */
  .cal-allday { position: sticky; top: var(--cal-head-h, 65px); z-index: var(--z-stickychrome); }
  .cal-head .gh { position: relative; padding: 8px 4px; font-size: 11px; color: var(--faint); text-align: right; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid var(--border); display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; }
  .cal-head .gh b { color: var(--muted); font-weight: 600; }
  .cal-head .gh .off { font-size: 10px; }
  .cal-head .gh .gh-more { position: absolute; top: 2px; right: 2px; width: 18px; height: 18px; padding: 0; display: none; align-items: center; justify-content: center; background: var(--bg); border-radius: var(--r-1); color: var(--muted); }
  .cal-head .gh:hover .gh-more, .cal-head .gh .gh-more:focus-visible { display: inline-flex; }
  .cal-head .gh .inline-rename { width: 100% !important; height: 20px; font-size: 11px; text-align: right; }
  .cal-head .gh-add { position: absolute; top: 3px; left: 3px; z-index: 3; width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-1); color: var(--faint); opacity: 0; transition: opacity .12s ease, background .12s ease; }
  .cal-head:hover .gh-add, .cal-head .gh-add:focus-visible { opacity: 1; }
  .cal-head .gh-add:hover { background: var(--hover); color: var(--muted); }
  .popover.tzadd { min-width: 260px; display: flex; flex-direction: column; gap: 6px; }
  .popover.tzadd > b { font-size: 12px; }
  .popover.tzadd x-select { width: 100%; }
  .cal-head .dh { padding: 6px 8px; display: flex; flex-direction: column; align-items: flex-start; border-right: 1px solid var(--border); }
  .cal-head .dh .dow { color: var(--muted); font-size: 11px; text-transform: uppercase; }
  .cal-head .dh .dn { font-size: 18px; font-weight: 500; line-height: 26px; min-width: 26px; text-align: center; border-radius: 13px; margin-left: -4px; padding: 0 3px; }
  .cal-head .dh[data-today] .dn { background: var(--accent); color: #fff; }
  .cal-allday { display: grid; grid-template-columns: repeat(var(--gutters, 1), var(--gw)) repeat(var(--days), minmax(110px, 1fr)); border-bottom: 1px solid var(--border); background: var(--bg-2); min-height: 26px; }
  .cal-allday .al { font-size: 10px; color: var(--faint); text-align: right; padding: 5px 6px; grid-column: 1 / span var(--gutters, 1); }
  .cal-allday .ad { border-right: 1px solid var(--border); padding: 3px; display: flex; flex-wrap: wrap; gap: 2px; }
  .cal-body .gcol { border-right: 1px solid var(--border); position: relative; }
  .cal-body .gcol .hl { height: var(--hh); text-align: right; padding: 0 6px; color: var(--faint); font-size: 11px; transform: translateY(-7px); position: relative; }
  .cal-body .gcol .hl.bd { color: var(--accent); font-weight: 600; }
  .cal-body .gcol .hl.bd::before { content: ""; position: absolute; left: 0; right: 0; top: 7px; border-top: 1px dashed var(--accent); opacity: .5; }
  .cal-body .gcol .hl.bd small { display: block; font-size: 9px; font-weight: 400; color: var(--accent); margin-top: -3px; }
  .cal-body .dcol { position: relative; border-right: 1px solid var(--border); }
  .cal-body .dcol .hr { height: var(--hh); border-bottom: 1px solid var(--border); cursor: cell; }
  .cal-body .dcol .hr:hover { background: var(--hover); }
  .cal-body .dcol[data-today] { background: rgba(35,131,226,.03); }
  .cal-body .ev {
    position: absolute; left: 3px; right: 3px; height: 44px; padding: 3px 6px; border-radius: var(--r-1); background: var(--pc5-bg); color: var(--pc5-fg);
    border-left: 3px solid var(--accent); text-align: left; overflow: hidden; display: flex; flex-direction: column; font-size: 12px; line-height: 1.3; box-shadow: 0 0 0 1px var(--bg); transition: transform var(--t), box-shadow var(--t);
  }
  .cal-body .ev:hover { filter: brightness(.97); z-index: 2; transform: scale(1.01); box-shadow: 0 2px 8px rgba(0,0,0,.14); }
  .cal-body .ev .t { font-weight: 600; font-size: 11px; }
  .cal-body .ev .n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .cal-body .ev.more { background: var(--hover); color: var(--muted); border-left-color: var(--faint); height: 22px; align-items: center; justify-content: center; font-size: 11px; }
  .cal-body .nowline { position: absolute; left: 0; right: 0; height: 0; border-top: 2px solid var(--danger); z-index: 1; pointer-events: none; }
  .cal-body .nowline::before { content: ""; position: absolute; left: -4px; top: -5px; width: 8px; height: 8px; border-radius: 50%; background: var(--danger); }
  .conv { font-size: 12px; }
  .cal-days-toggle { display: none; }

  /* ---------- peek / modal / record ---------- */
  x-peek { position: fixed; inset: 0; z-index: var(--z-peek); }
  x-peek .peek-backdrop { position: absolute; inset: 0; background: rgba(15,15,15,.3); animation: fadein var(--t) ease; }
  x-peek .peek-panel { position: absolute; top: 0; right: 0; bottom: 0; width: min(560px, 100vw); background: var(--bg); box-shadow: -8px 0 24px rgba(0,0,0,.1); display: flex; flex-direction: column; animation: fadein2 .16s ease; }
  x-peek[data-mode="modal"] .peek-panel { top: 5vh; right: auto; left: 50%; bottom: auto; margin-left: calc(min(860px, 100vw - 16px) / -2); width: min(860px, calc(100vw - 16px)); max-height: 90vh; border-radius: var(--r-4); box-shadow: var(--shadow-lg); animation: fadein2 .16s ease; }
  x-peek[data-mode="modal"] .peek-body { max-height: calc(90vh - 44px); }
  @keyframes fadein2 { from { opacity: 0; } to { opacity: 1; } }
  x-peek .peek-head { display: flex; align-items: center; gap: 2px; height: 44px; padding: 0 8px; border-bottom: 1px solid var(--border); flex: 0 0 44px; }
  x-peek .peek-head .sp { flex: 1; }
  x-peek .peek-head .modes { display: inline-flex; gap: 2px; padding-right: 6px; margin-right: 6px; border-right: 1px solid var(--border); }
  /* The peek is a 560px column, not a page: nothing inside it may scroll the panel sideways.
     Padding is tighter than the full record page, wide children (tables, code, the grid used
     for related records) scroll inside their own box, and long words wrap instead of pushing. */
  x-peek .peek-body { flex: 1; min-width: 0; overflow-y: auto; overflow-x: hidden; padding: 8px 20px 48px; overscroll-behavior: contain; }
  x-peek .peek-body * { min-width: 0; }
  x-peek .peek-body :is(table, pre, x-grid, .tblwrap, .hscroll, x-board) { max-width: 100%; overflow-x: auto; }
  x-peek .peek-body :is(p, h1, h2, h3, h4, li, td, th, .v, .rt) { overflow-wrap: anywhere; }
  /* the modal peek is wider, so it can keep the roomier gutter */
  x-peek[data-mode="modal"] .peek-body { padding: 8px 32px 48px; }
  x-peek .peek-body:empty::before { content: ""; display: block; height: 28px; margin: 24px 0 12px; width: 60%; background: linear-gradient(90deg, var(--hover) 25%, var(--hover-2) 37%, var(--hover) 63%); background-size: 400% 100%; animation: sk 1.4s ease infinite; border-radius: var(--r-1); }
  /* The reading measure of the body, declared once. It is the width of the rendered prose AND of
     the editor that replaces it, so clicking into the text does not reflow the page. */
  x-record { display: block; --measure: 90ch; }
  x-record .rec-head { padding: 24px 0 4px; }
  x-record .rec-tools { display: flex; align-items: center; gap: 2px; margin: 0 0 8px -6px; flex-wrap: wrap; }
  x-record .rec-tools .ghost { height: 28px; font-size: 12px; }
  x-record .rec-title { font-size: 30px; font-weight: 700; line-height: 1.2; border: 0; padding: 0; box-shadow: none; background: transparent; width: 100%; height: auto; border-radius: 3px; overflow-wrap: anywhere; }
  x-record .rec-title:hover { background: transparent; }
  x-record .rec-title:focus-visible { box-shadow: none; }
  x-record .rec-title::placeholder { color: var(--faint); }
  /* A record nobody has named is not a record CALLED "Untitled": a reader who cannot write still
     needs to see the word as the placeholder it is, the same grey the writer's box shows. */
  x-record h1.rec-title.ph { color: var(--faint); }
  x-record .props { display: flex; flex-direction: column; gap: 1px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
  x-record .prop { display: flex; align-items: flex-start; min-height: 30px; font-size: 14px; }
  x-record .prop .k { flex: 0 0 140px; width: 140px; display: flex; align-items: center; gap: 6px; height: 30px; color: var(--muted); font-size: 13px; padding: 0 6px; border-radius: var(--r-1); overflow: hidden; }
  /* a property name is never cut short: it wraps, as Notion's do */
  x-record .prop .k { height: auto; min-height: 30px; align-items: flex-start; padding-top: 6px; }
  x-record .prop .k > span { overflow-wrap: anywhere; line-height: 1.3; }
  /* The label is half of the row's click target (editor.js opens the value from it), so it lights
     up only where there IS something to open - beside a computed or read-only value the hover was
     promising an edit that never arrived. */
  x-record .prop:has(x-cell[data-writable]) .k { cursor: pointer; }
  x-record .prop:has(x-cell[data-writable]) .k:hover { background: var(--hover); }
  x-record .prop x-cell { flex: 1; min-height: 30px; height: auto; padding: 4px 6px; border: 0; border-radius: var(--r-1); flex-wrap: wrap; white-space: normal; width: auto; min-width: 0; font-size: 14px; }
  x-record .prop x-cell[data-writable]:hover { background: var(--hover); }
  x-record .prop x-cell[data-writable] .empty::after { content: ""; }
  /* "Empty" stands where a value stands, so it is the same size as one - at 13px in a 14px column
     the placeholder rows sat visibly smaller than the filled ones */
  x-record .prop x-cell .empty { font-size: inherit; }
  x-record .prop x-cell.editing > input, x-record .prop x-cell.editing > select { height: 32px; }
  x-record .prop .v.muted { display: flex; align-items: center; height: 32px; padding: 0 6px; font-size: 13px; }
  x-record .prop .v.who .avatar { margin-right: 6px; }
  x-record .addprop { margin: 4px 0 0 -2px; color: var(--faint); }
  /* A tab panel IS its section: it needs air under the strip, and nothing follows it, so the
     closing rule under every panel was a divider between the content and the end of the page.
     Scoped to the panels it was written for - as a descendant rule it also ruled x-relations'
     own five sections, which bring their own 14px rhythm and no borders at all. */
  x-record .rec-main > div > section { padding: var(--s-4) 0 var(--s-6); }
  x-record .rec-rail > section { padding: var(--s-4) 0 0; }
  /* the panel's own top padding is the gap under the tab strip; the first eyebrow inside it must
     not stack a second one on top (same rule .card already follows) */
  x-record .rec-main > div > section > h6.sec:first-child,
  x-record .rec-main x-related > .rgroup:first-child h6.sec { margin-top: 0; }
  x-record section > h3, x-record .sec-head h3 { margin-bottom: 8px; }
  x-record .sec-head { display: flex; align-items: center; justify-content: space-between; }
  /* The record's tab strip WAS a second, byte-identical copy of .tabs-ui (settings, admin, table
     settings). It is now the same component, so the strip on a record and the strip on a settings
     page cannot drift apart again; only the two things that are genuinely the record's own stay:
     it must not shrink its tabs, and it must scroll rather than widen a 560px peek. */
  x-record .rtabs > button { flex: 0 0 auto; }
  x-record .prose, x-record section.body textarea[data-mdeditor] { max-width: var(--measure); font-size: 15px; line-height: 1.6; }
  x-record .prose h1 { font-size: 22px; margin: 16px 0 6px; }
  x-record .prose h2 { font-size: 18px; margin: 14px 0 6px; }
  x-record .prose h3 { font-size: 15px; margin: 12px 0 4px; }
  x-record .prose p, x-record .prose ul, x-record .prose ol, x-record .prose pre, x-record .prose blockquote, x-record .prose table { margin: 0 0 8px; }
  x-record .prose ul { list-style: disc; padding-left: 22px; }
  x-record .prose ol { padding-left: 22px; }
  x-record .prose a { color: var(--accent); text-decoration: underline; }
  x-record .prose pre { background: var(--bg-code); padding: 12px; border-radius: var(--r-2); overflow: auto; font: 12.5px/1.5 var(--mono); }
  x-record .prose blockquote { border-left: 3px solid var(--border-2); padding-left: 12px; color: var(--muted); }
  x-record .prose table { border-collapse: collapse; }
  x-record .prose td, x-record .prose th { border: 1px solid var(--border); padding: 4px 8px; }
  x-record .prose input[type=checkbox] { margin-right: 6px; }
  x-record .prose img { max-width: 100%; }
  /* ---- Obsidian-flavoured wiki markup (see crates/core/src/markdown.rs) ---- */
  .prose a.wikilink { color: var(--accent); text-decoration: none; border-bottom: 1px solid color-mix(in srgb, var(--accent) 35%, transparent); }
  .prose a.wikilink:hover { background: color-mix(in srgb, var(--accent) 10%, transparent); border-radius: 3px; }
  .prose a.wikilink[data-embed] { display: block; margin: 10px 0; padding: 10px 12px; border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: var(--r-2); background: var(--bg-2); font-weight: 500; }
  .prose a.wikilink[data-embed]::after { content: " ↗"; color: var(--faint); font-weight: 400; }
  .prose .callout { margin: 12px 0; padding: 10px 12px; border-radius: var(--r-2); border-left: 3px solid var(--accent); background: color-mix(in srgb, var(--accent) 7%, transparent); }
  .prose .callout .co-title { margin: 0 0 2px; font-weight: 600; font-size: 13px; text-transform: uppercase; letter-spacing: .03em; color: var(--accent); }
  /* Notion's callout: emoji beside the text on a tinted block (markdown.rs [!CALLOUT|💡|blue]) */
  .prose .callout.has-icon { display: grid; grid-template-columns: auto 1fr; column-gap: 10px; border-left: 0; background: var(--hover); }
  .prose .callout.has-icon > .co-icon { grid-row: 1 / span 20; font-size: 18px; line-height: 1.4; }
  .prose .callout.has-icon > :not(.co-icon) { grid-column: 2; }
  .prose .callout[data-color="gray"] { background: var(--pc0-bg); } .prose .callout[data-color="brown"] { background: var(--pc1-bg); }
  .prose .callout[data-color="orange"] { background: var(--pc2-bg); } .prose .callout[data-color="yellow"] { background: var(--pc3-bg); }
  .prose .callout[data-color="green"] { background: var(--pc4-bg); } .prose .callout[data-color="blue"] { background: var(--pc5-bg); }
  .prose .callout[data-color="purple"] { background: var(--pc6-bg); } .prose .callout[data-color="pink"] { background: var(--pc7-bg); }
  .prose .callout[data-color="red"] { background: var(--pc8-bg); }
  .prose .callout[data-kind="warning"], .prose .callout[data-kind="caution"] { border-left-color: var(--warn, #b26a00); background: color-mix(in srgb, var(--warn, #b26a00) 8%, transparent); }
  .prose .callout[data-kind="warning"] .co-title, .prose .callout[data-kind="caution"] .co-title { color: var(--warn, #b26a00); }
  .prose .callout[data-kind="danger"], .prose .callout[data-kind="important"] { border-left-color: var(--danger, #c62828); background: color-mix(in srgb, var(--danger, #c62828) 8%, transparent); }
  .prose .callout[data-kind="danger"] .co-title, .prose .callout[data-kind="important"] .co-title { color: var(--danger, #c62828); }
  .prose .callout[data-kind="tip"], .prose .callout[data-kind="success"] { border-left-color: var(--ok, #2e7d32); background: color-mix(in srgb, var(--ok, #2e7d32) 8%, transparent); }
  .prose .callout[data-kind="tip"] .co-title, .prose .callout[data-kind="success"] .co-title { color: var(--ok, #2e7d32); }
  .prose .callout p:last-child { margin-bottom: 0; }
  /* Notion's toggle: a chevron that turns, and the section indented under it. The marker has to
     be drawn here because the app-wide `details > summary::-webkit-details-marker` rule above
     hides the browser's own - without this a toggle reads as a plain paragraph with no handle. */
  .prose details.toggle { margin: 4px 0; }
  .prose details.toggle > summary { display: flex; align-items: flex-start; gap: 6px; padding: 2px 0; cursor: pointer; list-style: none; font-weight: 500; border-radius: var(--r-1); }
  .prose details.toggle > summary::marker, .prose details.toggle > summary::-webkit-details-marker { content: ""; display: none; }
  .prose details.toggle > summary::before { content: ""; flex: none; width: 16px; height: 16px; margin-top: 3px; background: currentColor; opacity: .55; transition: transform .12s ease; clip-path: polygon(35% 22%, 68% 50%, 35% 78%, 28% 71%, 54% 50%, 28% 29%); }
  .prose details.toggle[open] > summary::before { transform: rotate(90deg); }
  .prose details.toggle > summary:hover { background: var(--hover); }
  .prose details.toggle > *:not(summary) { margin-left: 22px; }
  /* a date reads as text with a quiet underline, not as a blue link in the middle of a sentence */
  .prose a.datechip { color: inherit; text-decoration: none; border-bottom: 1px solid var(--border-2); }
  .prose a.datechip:hover { background: var(--hover); border-radius: 3px; }
  x-record .body textarea { min-height: 220px; }
  x-record .backlinks li a { display: flex; align-items: center; gap: 6px; height: 28px; color: var(--accent); }
  x-record .versions { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
  x-record .versions li { display: flex; align-items: center; gap: 8px; height: 30px; }
  x-record .versions li .pill { font-variant-numeric: tabular-nums; }
  x-record .comments li { display: flex; gap: 8px; padding: 8px 0; font-size: 13px; }
  x-record .comments li .who { margin-bottom: 2px; }
  x-record .comments li p { overflow-wrap: anywhere; }
  x-record .comments .frow { margin-top: 8px; }
  x-record .comments .frow input { flex: 1; }
  x-record .rec-foot { padding: 16px 0; }
  x-record .prop.meta .k { color: var(--faint); }
  .cluster.between { justify-content: space-between; }
  .dropzone { border: 1px dashed var(--border-2); border-radius: var(--r-2); padding: 12px; text-align: center; color: var(--muted); font-size: 12px; transition: background var(--t), border-color var(--t); }
  .dropzone[data-over] { background: var(--selected); border-color: var(--accent); }
  .dropzone input[type=file] { display: none; }
  .dropzone .btn { margin: 4px auto 0; }

  /* ---------- command palette ---------- */
  x-palette { position: fixed; inset: 0; z-index: var(--z-pal); display: flex; align-items: flex-start; justify-content: center; padding-top: 12vh; }
  x-palette .pal-backdrop { position: absolute; inset: 0; background: rgba(15,15,15,.3); }
  x-palette .pal { position: relative; width: min(600px, calc(100vw - 16px)); max-height: 70vh; background: var(--bg); border-radius: var(--r-4); box-shadow: var(--shadow-lg); display: flex; flex-direction: column; overflow: hidden; animation: popin var(--t) ease; }
  x-palette .pal-in { display: flex; align-items: center; gap: 10px; padding: 0 14px; height: 50px; border-bottom: 1px solid var(--border); }
  x-palette .pal-in input { border: 0; box-shadow: none; background: transparent; font-size: 16px; padding: 0; height: 100%; }
  x-palette .pal-in svg { color: var(--faint); }
  x-palette .pal-list { overflow-y: auto; padding: 6px; }
  x-palette .pal-list .mh { font-size: 11px; color: var(--faint); padding: 8px 8px 2px; text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
  x-palette .pal-list .mi { height: auto; min-height: 34px; padding: 6px 8px; align-items: flex-start; }
  x-palette .pal-list .mi svg { margin-top: 2px; }
  x-palette .pal-list .mi .t { display: flex; flex-direction: column; min-width: 0; }
  x-palette .pal-list .mi .t small { color: var(--muted); font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-palette .pal-list .mi .t small b { background: var(--warn-bg); font-weight: 500; }
  x-palette .pal-list .empty { padding: 20px; text-align: center; }
  x-palette .pal-foot { display: flex; gap: 12px; padding: 6px 12px; border-top: 1px solid var(--border); color: var(--faint); font-size: 11px; }

  /* ---------- search / notifications / settings ---------- */
  .searchbox { display: flex; align-items: center; gap: 10px; padding: 0 12px; height: 46px; border: 1px solid var(--border-2); border-radius: var(--r-3); margin: 16px 0 16px; box-shadow: 0 1px 2px rgba(0,0,0,.03); }
  .searchbox input { border: 0; box-shadow: none; font-size: 16px; padding: 0; background: transparent; height: 100%; }
  .searchbox svg { color: var(--faint); }
  x-results { display: block; margin-top: 8px; }
  x-results .res { display: flex; gap: 10px; align-items: flex-start; padding: 8px 8px; margin: 0 -8px; border-radius: var(--r-1); min-width: 0; }
  x-results .res:hover { background: var(--hover); }
  x-results .res > div { min-width: 0; }
  x-results .rt { font-weight: 500; }
  x-results .rs { font-size: 13px; overflow-wrap: anywhere; }
  x-results .rs b { background: var(--warn-bg); font-weight: 500; }
  x-notifs { display: block; margin-top: 8px; }
  x-notifs .notif { display: flex; gap: 10px; padding: 10px 8px; margin: 0 -8px; border-bottom: 1px solid var(--border); font-size: 13px; border-radius: var(--r-1); }
  x-notifs .notif:hover { background: var(--hover); }
  x-notifs .dot { width: 8px; height: 8px; border-radius: 50%; margin-top: 6px; background: transparent; flex: 0 0 auto; }
  x-notifs .unread .dot { background: var(--accent); }
  x-notifs .nt { font-weight: 500; font-size: 14px; }
  x-notifs .nt a:hover { text-decoration: underline; }
  x-notifs .nb { min-width: 0; flex: 1; }
  x-notifs .nb > .muted { overflow-wrap: anywhere; }
  x-settings { display: block; }
  x-settings section { padding: 20px 0; border-bottom: 1px solid var(--border); }
  x-settings section:last-child { border-bottom: 0; }
  x-settings section h3 { margin-bottom: 4px; }
  x-settings section > .muted { margin-bottom: 12px; font-size: 13px; }
  x-settings .keys li { display: flex; align-items: center; gap: 10px; min-height: 38px; border-bottom: 1px solid var(--border); font-size: 13px; flex-wrap: wrap; }
  x-settings .keys .kl { flex: 1; font-weight: 500; }
  x-settings form.frow { margin-top: 10px; }
  x-settings .stack > label { max-width: 480px; }
  .tzrows { display: flex; flex-direction: column; gap: 6px; }
  .tzrows .frow { align-items: center; }
  .tzrows .frow .pin { flex: 0 0 auto; font-size: 11px; color: var(--accent); background: var(--selected); border-radius: 8px; padding: 0 6px; height: 18px; line-height: 18px; }
  .pref-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
  .pref-row:last-child { border-bottom: 0; }
  .pref-row .d { color: var(--muted); font-size: 12px; }
  .pref-row select { width: auto; min-width: 140px; }
  .switch { position: relative; width: 34px; height: 20px; border-radius: 10px; background: var(--hover-2); transition: background var(--t); flex: 0 0 auto; }
  .switch::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.2); transition: transform var(--t); }
  .switch[aria-checked="true"] { background: var(--accent); }
  .switch[aria-checked="true"]::after { transform: translateX(14px); }

  /* ---------- toasts ---------- */
  x-toasts { position: fixed; bottom: 24px; right: 24px; z-index: var(--z-toast); display: flex; flex-direction: column; gap: 8px; pointer-events: none; max-width: calc(100vw - 32px); }
  x-toasts .toast { padding: 8px 12px; background: var(--fg); color: var(--bg); border-radius: var(--r-2); font-size: 13px; box-shadow: var(--shadow); animation: fadein .15s ease; max-width: 360px; }
  x-toasts .toast.error { background: var(--danger); color: #fff; }
  x-toasts .toast.ok { background: var(--ok); color: #fff; }
  @keyframes fadein { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

  /* ---------- login ---------- */
  body.login-page { align-items: center; justify-content: center; background: var(--bg-side); background-image: radial-gradient(var(--border-2) 1px, transparent 1px); background-size: 22px 22px; padding: 16px; }
  x-login { display: block; width: 380px; max-width: 100%; padding: 36px 32px; background: var(--bg); border-radius: var(--r-4); box-shadow: var(--shadow-lg); }
  x-login .wordmark { display: flex; align-items: center; gap: 8px; font-weight: 700; margin-bottom: 28px; font-size: 15px; }
  x-login h1 { font-size: 22px; margin-bottom: 4px; }
  x-login p { margin-bottom: 20px; }
  x-login input { height: 38px; }
  x-login .foot { margin-top: 20px; font-size: 12px; color: var(--faint); text-align: center; }

  /* ---- admin / settings tables ---- */
  .tblwrap { overflow-x: auto; margin: 8px 0 12px; }
  .tbl { width: 100%; border-collapse: collapse; font-size: 13px; margin: 8px 0 12px; }
  .tblwrap .tbl { margin: 0; }
  .tbl th { text-align: left; font-weight: 500; color: var(--muted); padding: 6px 8px; border-bottom: 1px solid var(--border); white-space: nowrap; font-size: 12px; }
  .tbl td { padding: 7px 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
  .tbl td.end { text-align: right; }
  .tbl tr:hover td { background: var(--hover); }
  .tbl tr[hidden] { display: none; }
  .tbl .who { display: inline-flex; align-items: center; }
  .pill[data-role="superadmin"], .pill[data-role="admin"] { background: var(--pc8-bg); color: var(--pc8-fg); }
  .pill[data-role="lead"] { background: var(--pc2-bg); color: var(--pc2-fg); }
  .pill[data-role="member"] { background: var(--pc5-bg); color: var(--pc5-fg); }
  .pill[data-role="client"] { background: var(--pc6-bg); color: var(--pc6-fg); }
  .pill[data-role="guest"] { background: var(--pc0-bg); color: var(--pc0-fg); }
  details > summary.btn { list-style: none; display: inline-flex; cursor: pointer; }
  details > summary::-webkit-details-marker { display: none; }
  .icon-btn.danger:hover { color: var(--danger); background: var(--danger-bg); }
  a.mi { text-decoration: none; }
  .roles-help { display: grid; grid-template-columns: auto 1fr; gap: 4px 10px; font-size: 12px; color: var(--muted); margin: 8px 0; align-items: center; }
  .card { border: 1px solid var(--border); border-radius: var(--r-3); padding: 14px 16px; background: var(--bg); }

  /* ---- attachments ---- */
  x-files { display: block; }
  x-files ul.files { list-style: none; margin: 0 0 var(--s-2); padding: 0; display: flex; flex-direction: column; gap: 4px; }
  /* with no attachments the list still spent its bottom margin, leaving a phantom gap above
     the dropzone */
  x-files ul.files:empty { display: none; }
  x-files .empty-state { margin-bottom: var(--s-2); }
  x-files ul.files > li { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--r-1); font-size: 13px; min-width: 0; }
  x-files ul.files a { display: inline-flex; align-items: center; gap: 6px; color: var(--fg); text-decoration: none; min-width: 0; }
  x-files ul.files a:hover { color: var(--accent); }
  x-files ul.files a span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-files ul.files > li .muted { white-space: nowrap; font-size: 12px; }
  x-files input[type="file"] { font-size: 12px; }

  /* ---- markdown slash menu (Notion's: grouped sections, icon + label + description) ---- */
  .slash-menu { position: fixed; z-index: var(--z-pop); min-width: 320px; max-width: 340px; max-height: 340px; overflow-y: auto; overscroll-behavior: contain; background: var(--bg); border-radius: var(--r-3); box-shadow: var(--shadow-lg); padding: 4px; }
  .slash-menu .sm-sec { padding: 10px 10px 4px; font-size: 11px; font-weight: 600; color: var(--faint); text-transform: uppercase; letter-spacing: .04em; }
  .slash-menu .sm-empty { padding: 10px; font-size: 13px; color: var(--faint); }
  .slash-menu .mi { display: flex; align-items: center; gap: 10px; width: 100%; height: auto; min-height: 44px; text-align: left; padding: 6px 10px; margin-bottom: 2px; border-radius: var(--r-2); font-size: 13px; background: none; border: 0; cursor: pointer; color: var(--fg); }
  .slash-menu .mi:last-child { margin-bottom: 0; }
  .slash-menu .sm-t { gap: 0; }
  .slash-menu { padding: 6px; }
  .slash-menu .mi > .ico { flex: 0 0 auto; width: 30px; height: 30px; padding: 7px; border-radius: var(--r-1); box-shadow: inset 0 0 0 1px var(--border); color: var(--muted); }
  .slash-menu .sm-t { display: flex; flex-direction: column; min-width: 0; }
  .slash-menu .sm-t b { font-weight: 500; line-height: 18px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .slash-menu .sm-t small { font-size: 11px; line-height: 14px; color: var(--faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .slash-menu .mi.on, .slash-menu .mi:hover { background: var(--hover); }

  /* inline editing: the prose IS the editor, so it has to invite a click */
  section.body .prose { border-radius: var(--r-2); padding: 2px 4px; margin: 0 -4px; transition: background var(--t); }
  section.body:not(.editing) .prose:hover { background: var(--hover); cursor: text; }
  section.body .prose .empty { color: var(--faint); cursor: text; }
  /* the body is click-to-edit, so it is also tab-to-edit (editor.js): it needs to show where the
     keyboard has landed before Enter opens it */
  section.body .prose:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  section.body.editing .prose { display: none; }
  section.body .sec-head { display: flex; align-items: center; gap: 8px; min-height: 22px; }
  x-inbox .ihead > .tabs { display: flex; gap: 2px; margin: 4px 0 10px; border-bottom: 1px solid var(--border); }
  x-inbox .ihead > .tabs a { display: inline-flex; align-items: center; gap: 6px; height: 30px; padding: 0 10px; font-size: 13px; color: var(--muted); border-bottom: 2px solid transparent; margin-bottom: -1px; }
  x-inbox .ihead > .tabs a[aria-current] { color: var(--fg); border-bottom-color: var(--fg); font-weight: 500; }
  x-inbox .ihead > .tabs a:hover { color: var(--fg); }

  .md-status { margin-left: auto; font-size: 11px; color: var(--faint); }
  /* the block editor (blocks.js): each block a row with Notion's + and ⋮⋮ handles at the left */
  section.body.blocked form { display: none !important; }
  .blocks { max-width: var(--measure); padding-bottom: 40vh; }
  .blk { position: relative; display: flex; align-items: flex-start; gap: 4px; margin-left: -48px; padding-left: 48px; border-radius: var(--r-1); }
  .blk > .bh { position: absolute; left: 0; top: 2px; display: flex; gap: 0; opacity: 0; transition: opacity var(--t); }
  .blk:hover > .bh, .blk.editing > .bh { opacity: 1; }
  .blk > .bh button { width: 22px; height: 22px; border: 0; background: none; color: var(--faint); border-radius: var(--r-1); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; padding: 0; }
  .blk > .bh button:hover { background: var(--hover); color: var(--fg); }
  .blk > .bv { flex: 1; min-width: 0; padding: 2px 4px; border-radius: var(--r-1); font-size: 15px; line-height: 1.6; cursor: text; }
  .blk > .bv > :last-child { margin-bottom: 0; }
  .blk > .bv .empty { color: var(--faint); }
  .blk:hover:not(.editing) > .bv { background: var(--hover); }
  .blk.dragging { opacity: .4; }
  .blk > .bt { flex: 1; min-width: 0; width: 100%; font: inherit; font-size: 15px; line-height: 1.6; padding: 2px 4px; border: 0; border-radius: var(--r-1); background: var(--bg-2); resize: none; overflow: hidden; }
  .blk[data-k="code"] > .bt { font-family: var(--mono, ui-monospace, monospace); font-size: 13px; }
  .blk[data-k="heading"] > .bt { font-weight: 700; font-size: 20px; }
  .blk > .bt:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; }
  /* in-place editing: the rendered block itself is the editor */
  .blk.editing > .bv { background: var(--bg-2); cursor: text; }
  .blk > .bv[contenteditable], .blk > .bv [contenteditable] { outline: none; caret-color: var(--fg); }
  .blk > .bv .empty[data-ph]:empty::before { content: attr(data-ph); color: var(--faint); }
  .blk.editing > .bv td, .blk.editing > .bv th { min-width: 60px; }
  .blk.editing > .bv td:focus, .blk.editing > .bv th:focus { box-shadow: inset 0 0 0 2px var(--accent); }
  .blk > .bv input[type=checkbox] { cursor: pointer; }
  /* inline comments (blocks.js): the count in the margin, the commented text, the thread */
  .blk > .cm-mark { order: 3; flex: none; display: inline-flex; align-items: center; gap: 3px; height: 22px; margin-top: 2px; padding: 0 6px; border: 0; border-radius: var(--r-1); background: none; color: var(--muted); font-size: 12px; cursor: pointer; }
  .blk > .cm-mark:hover { background: var(--hover); color: var(--fg); }
  ::highlight(cb-comment) { background-color: rgba(255, 196, 0, .28); }
  .cm-thread { width: 320px; padding: 8px; display: flex; flex-direction: column; gap: 8px; }
  .cm-thread .cm-q { padding-left: 8px; border-left: 2px solid rgba(255, 196, 0, .8); font-size: 12px; color: var(--muted); overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; }
  .cm-thread .cm-h { display: flex; align-items: center; gap: 6px; font-size: 12.5px; }
  .cm-thread .cm-h time { color: var(--faint); }
  .cm-thread .cm-h .ghost { margin-left: auto; }
  .cm-thread .cm-row > p { margin: 2px 0 0; font-size: 13.5px; white-space: pre-wrap; overflow-wrap: anywhere; }
  .cm-thread .cm-new { display: flex; gap: 6px; }
  .cm-thread .cm-new input { flex: 1; min-width: 0; }
  .cm-thread .cm-rtog { align-self: flex-start; color: var(--muted); }
  .cm-thread .cm-row.done { opacity: .7; }
  /* the read-only body's blocks (blocks.js cbComments) carry markers only: no edit cursor or hover */
  .blk.ro > .bv { cursor: auto; }
  .blk.ro:hover > .bv { background: none; }
  .md-foot { margin-top: 6px; max-width: var(--measure); }
  section.body textarea[data-mdeditor] { border-color: transparent; padding: 2px 4px; margin: 0 -4px; resize: none; }
  section.body textarea[data-mdeditor]:focus-visible { border-color: transparent; box-shadow: none; }
  form.stack:has(textarea[data-mdeditor]) { position: relative; }

  /* ---------- shared page bits: cards, two-col, progress ---------- */
  .card { border: 1px solid var(--border); border-radius: var(--r-3); padding: 12px; background: var(--bg); }
  .card > h6.sec:first-child { margin-top: 0; }
  .two-col { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; align-items: start; }
  .two-col.rev { grid-template-columns: minmax(0, 1fr) 320px; }
  .two-col > aside h6.sec:first-child { margin-top: 16px; }
  .prog { display: inline-block; width: 90px; height: 6px; border-radius: 3px; background: var(--hover-2); overflow: hidden; vertical-align: middle; }
  .prog > i { display: block; height: 100%; background: var(--accent); border-radius: 3px; }
  .pg { display: inline-flex; align-items: center; gap: 6px; }
  .tips li { padding: 4px 0 4px 14px; position: relative; font-size: 12.5px; }
  .tips li::before { content: "·"; position: absolute; left: 2px; }
  .tagcloud { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
  .tagcloud .pill { height: auto; padding: 2px 8px; }
  .tagcloud .pill small { opacity: .7; }
  x-tcard { display: flex; flex-direction: column; gap: 4px; border: 1px solid var(--border); border-radius: var(--r-3); padding: 12px; background: var(--bg); min-height: 96px; transition: box-shadow var(--t); }
  x-tcard:hover { box-shadow: var(--shadow); }
  x-tcard .th { display: flex; align-items: center; gap: 8px; font-weight: 600; min-width: 0; }
  x-tcard .th > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-tcard .tm { color: var(--muted); font-size: 12px; }
  x-tcard .tv { display: flex; flex-wrap: wrap; gap: 4px; flex: 1; }
  x-tcard .tv .chip:hover { background: var(--hover-2); color: var(--fg); }
  x-tcard .open { align-self: flex-end; }
  .cardgrid.one { grid-template-columns: 1fr; }
  .spacegrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
  .scard { display: flex; flex-direction: column; gap: 4px; padding: 14px; border: 1px solid var(--border); border-radius: var(--r-3); background: var(--bg); transition: box-shadow var(--t); }
  .scard:hover { box-shadow: var(--shadow); }
  .scard svg { width: 20px; height: 20px; color: var(--accent); margin-bottom: 4px; }
  .scard b { font-size: 14px; }
  .home-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 16px; align-items: start; }
  .home-grid h6.sec { margin-top: 12px; }
  x-upcoming .up .pill { flex: 0 0 auto; }
  x-upcoming .up .chip { flex: 0 0 auto; max-width: 140px; }
  x-upcoming .up small, x-upcoming .up time { margin-left: auto; color: var(--muted); font-size: 12px; }
  a.up:hover { color: var(--fg); }

  /* ---------- projects list ---------- */
  .plist { border: 1px solid var(--border); border-radius: var(--r-3); overflow: hidden; }
  .prow { display: grid; grid-template-columns: 20px minmax(0, 2fr) 90px minmax(0, 1fr) 110px 170px 20px; align-items: center; gap: 10px; padding: 8px 12px; border-bottom: 1px solid var(--border); font-size: 13px; }
  .prow:last-child { border-bottom: 0; }
  a.prow:hover { background: var(--hover); }
  .prow.head { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--faint); font-weight: 600; background: var(--bg-2); padding: 6px 12px; }
  .prow .pn { min-width: 0; display: flex; flex-direction: column; }
  .prow .pn b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .prow .who { display: flex; align-items: center; min-width: 0; }
  .prow .who .avatar { margin-right: 6px; }

  /* ---------- CRM pipeline ---------- */
  x-pipeline { display: block; border: 1px solid var(--border); border-radius: var(--r-3); padding: 12px 14px; margin-bottom: 12px; background: var(--bg); }
  x-pipeline > header { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
  x-pipeline .th { display: flex; align-items: center; gap: 8px; font-size: 15px; }
  x-pipeline .amt { display: flex; flex-direction: column; margin-left: auto; text-align: right; line-height: 1.2; }
  x-pipeline .amt b { font-size: 16px; font-variant-numeric: tabular-nums; }
  x-pipeline .funnel { display: flex; gap: 4px; min-height: 64px; }
  x-pipeline .stage { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 4px; padding: 8px; border-radius: var(--r-2); background: var(--bg-2); position: relative; overflow: hidden; }
  x-pipeline .stage:hover { background: var(--hover); }
  x-pipeline .stage .pill { max-width: 100%; align-self: flex-start; }
  x-pipeline .stage b { font-size: 16px; }
  x-pipeline .stage small { font-size: 11px; font-variant-numeric: tabular-nums; }
  x-pipeline .stage .bar { position: absolute; left: 0; bottom: 0; height: 3px; background: var(--accent); opacity: .7; }

  /* ---------- agenda ---------- */
  x-agenda { display: block; }
  x-agenda .day { margin: 14px 0 4px; }
  x-agenda .ev { display: flex; align-items: center; gap: 10px; height: 32px; padding: 0 10px; border-radius: var(--r-1); cursor: pointer; font-size: 13px; }
  x-agenda .ev:hover { background: var(--hover); }
  x-agenda .ev > time { color: var(--muted); font-variant-numeric: tabular-nums; width: 70px; flex: 0 0 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-agenda .ev .rt { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }

  /* ---------- inbox ---------- */
  /* list and detail each scroll on their own; the list's head stays put above its rows */
  x-inbox { display: grid; grid-template-columns: 380px minmax(0, 1fr); height: calc(100vh - 44px); min-height: 0; }
  x-inbox .ilist { border-right: 1px solid var(--border); display: flex; flex-direction: column; min-height: 0; max-height: calc(100vh - 44px); overflow: hidden; }
  x-inbox .ihead { flex: none; padding: var(--s-3) var(--s-2) 0 var(--s-4); }
  x-inbox .irows { flex: 1; min-height: 0; overflow-y: auto; padding: 0 var(--s-2) var(--s-6) var(--s-4); }
  x-inbox .idetail { overflow-y: auto; max-height: calc(100vh - 44px); }
  /* the inbox fills the page exactly: no page padding under it, so the page itself never scrolls */
  main > .page:has(> x-inbox) { padding-bottom: 0; }
  x-inbox .ihead > header { display: flex; align-items: center; gap: 10px; padding: 8px 8px 12px; }
  x-inbox .ihead > header .page-title { font-size: 20px; margin: 0; }
  x-inbox .ihead > header form { margin-left: auto; }
  x-inbox .grp { display: flex; align-items: center; gap: 8px; padding: 10px 8px 4px; }
  x-inbox .grp .n { background: var(--hover); border-radius: 8px; padding: 0 6px; }
  x-inbox .irow { display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: var(--r-2); font-size: 13px; cursor: pointer; position: relative; min-width: 0; }
  x-inbox .irow:hover, x-inbox .irow[aria-selected="true"] { background: var(--hover); }
  x-inbox .irow .ki { display: inline-flex; width: 26px; height: 26px; align-items: center; justify-content: center; border-radius: 50%; background: var(--hover); color: var(--muted); flex: 0 0 auto; }
  x-inbox .irow.unread .ki { background: var(--selected); color: var(--accent); }
  x-inbox .irow.unread .nt { font-weight: 600; }
  x-inbox .irow.unread::before { content: ""; position: absolute; left: -2px; top: 50%; width: 6px; height: 6px; margin-top: -3px; border-radius: 50%; background: var(--accent); }
  x-inbox .irow .nb { flex: 1; min-width: 0; }
  x-inbox .irow .nt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-inbox .irow > time { color: var(--faint); font-size: 12px; flex: 0 0 auto; }
  x-inbox .irow .acts { display: none; gap: 2px; position: absolute; right: 6px; top: 50%; transform: translateY(-50%); background: var(--bg); border-radius: var(--r-1); box-shadow: var(--shadow); padding: 2px; }
  x-inbox .irow:hover .acts, x-inbox .irow:focus-within .acts { display: flex; }
  /* the placeholder centres itself in the pane rather than hanging off a magic 60px top margin,
     which put it near the top on a laptop and near nothing at all on a tall screen */
  x-inbox .idetail { padding: var(--s-5); display: flex; flex-direction: column; }
  x-inbox .idetail .placeholder { border: 0; margin: auto; }
  x-inbox .idetail article { max-width: 640px; display: flex; flex-direction: column; gap: 10px; align-items: flex-start; }
  x-inbox .idetail article p { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.6; }

  /* Home's My work card: the due date, red when overdue, as on the My Work page */
  x-upcoming .up .due { color: var(--muted); font-size: 12px; white-space: nowrap; }
  x-upcoming .up .due.over { color: var(--danger); }

  /* ---------- project overview ---------- */
  x-project { display: block; }
  x-project .phead { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 4px 0 8px; }
  x-project .pname { font-size: 26px; font-weight: 700; border: 0; box-shadow: none; background: transparent; padding: 0 4px; height: auto; flex: 1 1 260px; min-width: 200px; border-radius: 3px; }
  x-project .pname:hover { background: var(--hover); }
  x-project .meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; width: 100%; padding-left: 26px; }
  x-project .meta label { display: inline-flex; align-items: center; gap: 4px; margin: 0; }
  x-project .meta select, x-project .meta x-datepicker > .dp-btn { width: auto; height: 28px; font-size: 12px; border-color: transparent; background: var(--hover); }
  x-project .meta select:hover, x-project .meta x-datepicker > .dp-btn:hover { background: var(--hover-2); }
  x-project .ptabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin: 4px 0 16px; overflow-x: auto; scrollbar-width: none; align-items: center; }
  x-project .ptabs::-webkit-scrollbar { display: none; }
  x-project .ptabs > a, x-project .ptabs > button, x-project .ptabs .tab-add { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px; color: var(--muted); font-weight: 500; font-size: 13px; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; }
  x-project .ptabs > a:hover, x-project .ptabs > button:hover, x-project .ptabs .tab-add:hover { color: var(--fg); background: var(--hover); border-radius: 3px 3px 0 0; }
  x-project .ptabs > [aria-selected="true"] { color: var(--fg); border-bottom-color: var(--fg); }
  x-project .health { display: flex; gap: 6px; flex-wrap: wrap; }
  x-project .health label { display: inline-flex; cursor: pointer; }
  x-project .health input { position: absolute; opacity: 0; }
  x-project .health label:has(input:checked) .pill { box-shadow: 0 0 0 2px var(--accent); }
  x-project .health .pill { height: 24px; line-height: 24px; padding: 0 10px; }
  x-timeline-list { display: flex; flex-direction: column; gap: 4px; }
  x-timeline-list .upd { display: flex; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
  x-timeline-list .upd .avatar { margin-top: 2px; }
  x-timeline-list .uh { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
  x-timeline-list .upd p { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.55; }
  x-project .tlist li a { display: flex; align-items: center; gap: 8px; height: 28px; padding: 0 6px; margin: 0 -6px; border-radius: var(--r-1); font-size: 13px; }
  x-project .tlist li a:hover { background: var(--hover); }
  x-project .tlist li a > span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-project .mlist li { display: flex; align-items: center; gap: 6px; height: 28px; font-size: 13px; }
  x-project .mlist li > span.ellip { flex: 1; }
  x-project .kv { display: flex; justify-content: space-between; font-size: 13px; padding: 4px 0; border-bottom: 1px solid var(--border); }
  x-project .kv:last-child { border-bottom: 0; }
  x-project .kv > span { color: var(--muted); }

  /* ---------- universal record: 3-column layout ---------- */
  x-record .rec-crumb { display: flex; align-items: center; gap: 4px; font-size: 12px; color: var(--muted); padding-top: 12px; }
  x-record .rec-crumb a:hover { color: var(--fg); text-decoration: underline; }
  x-record .rec-crumb .sep { color: var(--faint); }
  /* The full record page already carries this trail in the topbar, so it was printing the same
     path twice, one line above the other. The peek has no topbar and keeps its own; below 900px
     the topbar collapses to the last crumb only, so the record's own trail is the trail. */
  @media (min-width: 900px) {
    x-page.recpage x-record > .rec-head > .rec-crumb { display: none; }
    x-page.recpage x-record .rec-head { padding-top: var(--s-3); }   /* the air the crumb used to hold */
  }
  x-record .rec-head { padding: 0 0 4px; }
  x-record .rec-title-row { padding: 6px 0 2px; }
  x-record .rec-tools .sp { flex: 1; }
  x-record .rec-tools x-cell.status { display: inline-flex; height: 28px; min-height: 28px; padding: 0 6px; border-radius: var(--r-1); cursor: pointer; }
  x-record .rec-tools x-cell.status[data-writable]:hover { background: var(--hover); }
  x-record .rec-tools .ver { white-space: nowrap; }
  x-record .rec-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 24px; align-items: start; }
  x-record .rec-rail { position: sticky; top: 52px; max-height: calc(100vh - 60px); overflow-y: auto; padding-left: 20px; border-left: 1px solid var(--border); }
  x-record .rec-rail .props { border-bottom: 0; padding-bottom: 0; }
  x-record .rec-rail .props > h6 { padding: 8px 6px 4px; }
  x-record .rec-rail .prop { flex-wrap: wrap; }
  x-record .rec-rail .prop .k { flex: 0 0 110px; width: 110px; font-size: 12px; }
  x-record .rec-rail .prop x-cell { font-size: 13px; }
  x-record .linkcell { flex: 1; min-height: 32px; display: flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 4px 6px; border-radius: var(--r-1); }
  x-record .linkcell .pill { margin: 0; }
  x-record .linkcell .add { cursor: pointer; opacity: .6; }
  x-record .linkcell:hover .add, x-record .linkcell .add:focus-visible { opacity: 1; }
  x-record .linkcell .empty { color: var(--faint); }
  /* the strip sits directly under the title block; the panel below supplies the gap */
  x-record .rtabs { margin: 0; }
  x-record .toc { font-size: 12px; color: var(--muted); display: flex; flex-wrap: wrap; gap: 4px 10px; }
  /* the record page has the outline in its rail: the strip above the body would only echo the title */
  x-record:has(.toc-side) .sec-head .toc { display: none; }
  x-record .toc a { padding: 2px 0; }
  x-record .toc a:hover { color: var(--fg); text-decoration: underline; }
  x-record .toc a[data-l="3"] { padding-left: 10px; }
  /* One look for "a link to another record", wherever the list appears - the outline rail and the
     Related tab had a quiet hover row and a line of blue links for the same idea, and x-related,
     which replaces the second one the moment it loads, uses the quiet row. */
  x-record .bl li a { display: flex; align-items: center; gap: 6px; min-width: 0; height: 28px; padding: 0 6px; border-radius: var(--r-1); color: var(--muted); font-size: 13px; }
  x-record .bl li a:hover { background: var(--hover); color: var(--fg); }
  x-record .bl li a > svg { color: var(--faint); }
  x-record .bl li a > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  /* in a tab the heading has no gutter of its own, so the rows hang back onto its left edge */
  x-record .rec-main .bl { margin-left: -6px; }
  x-record .body .sec-head { min-height: 32px; }
  x-peek .rec-grid { grid-template-columns: 1fr; gap: 8px; }
  x-peek .rec-rail { position: static; max-height: none; overflow: visible; padding-left: 0; border-left: 0; order: -1; border-bottom: 1px solid var(--border); padding-bottom: 8px; margin-bottom: 4px; }
  x-peek .rec-rail .prop .k { flex-basis: 140px; width: 140px; }
  /* The side peek is ONE column at every viewport. The desktop rule further down
     (`x-record .rec-grid` → two columns) is meant for the full record page; being later in the
     file it used to win here too, which squeezed the properties and the tabs side by side into
     560px and truncated every value. `x-peek[data-mode]` outranks it on specificity, so the
     order of the rules no longer matters. */
  x-peek[data-mode="peek"] .rec-grid { grid-template-columns: 1fr; gap: 8px; }
  x-peek[data-mode="peek"] .rec-rail { order: -1; position: static; max-height: none; overflow: visible; padding-left: 0; border-left: 0; border-bottom: 1px solid var(--border); padding-bottom: 10px; margin-bottom: 4px; }
  x-peek[data-mode="peek"] .rec-rail .prop .k { flex: 0 0 128px; width: 128px; }
  x-peek[data-mode="peek"] .rec-rail .prop { align-items: flex-start; }
  x-peek[data-mode="peek"] .rec-side { display: none; }   /* the outline needs a third column */
  x-peek[data-mode="modal"] .rec-grid { grid-template-columns: minmax(0, 1fr) 280px; gap: 24px; }
  x-peek[data-mode="modal"] .rec-rail { order: 0; border-bottom: 0; padding-left: 16px; border-left: 1px solid var(--border); }
  x-related, x-activity { display: block; }
  x-related .rgroup h6.sec { margin: var(--s-4) 0 var(--s-2); }
  x-related .rgroup h6.sec .add { margin-left: 4px; text-transform: none; letter-spacing: 0; cursor: pointer; }
  x-related .rlist li { display: flex; align-items: center; gap: 6px; min-height: 30px; }
  x-related .rlist li a { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; padding: 0 6px; margin-left: -6px; border-radius: var(--r-1); height: 28px; font-size: 13px; }
  x-related .rlist li a:hover { background: var(--hover); }
  x-related .rlist .rt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-related .rlist .gh { min-height: 24px; margin-top: 4px; }
  x-related .rlist li form .icon-btn { opacity: 0; }
  x-related .rlist li:hover form .icon-btn { opacity: 1; }
  x-activity .vlist li { display: flex; align-items: center; gap: 8px; min-height: 30px; font-size: 13px; }
  x-activity .vlist li .rt { flex: 1; }
  x-activity .vlist li .pill { font-variant-numeric: tabular-nums; }
  .pickpop { position: fixed; z-index: var(--z-pop); width: 300px; background: var(--bg); box-shadow: var(--shadow-lg); border-radius: var(--r-3); padding: 6px; }
  .pickpop input { margin-bottom: 4px; }
  .pickpop .mi small { color: var(--muted); margin-left: auto; font-size: 11px; }
  .pickpop .empty { padding: 8px; color: var(--muted); font-size: 12px; text-align: center; }

  /* ---------- KB page tree + notes graph ---------- */
  .gridwrap { display: flex; align-items: flex-start; gap: 0; }
  .gridwrap > x-grid { flex: 1; min-width: 0; }
  .treepanel { flex: 0 0 260px; width: 260px; max-height: calc(100vh - 44px - 130px); overflow-y: auto; border-right: 1px solid var(--border); padding: 8px 8px 8px 0; margin-right: 12px; font-size: 13px; }
  .treepanel ul ul { padding-left: 14px; }
  .treepanel li { list-style: none; }
  .treepanel .tn { display: flex; align-items: center; gap: 2px; height: 28px; border-radius: var(--r-1); padding-right: 6px; }
  .treepanel .tn:hover { background: var(--hover); }
  .treepanel .tn > button { width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; color: var(--faint); border-radius: 3px; flex: 0 0 auto; }
  .treepanel .tn > button.leaf { visibility: hidden; }
  .treepanel .tn > button svg { transition: transform .12s; }
  .treepanel li[data-open] > .tn > button svg { transform: rotate(90deg); }
  .treepanel li:not([data-open]) > ul { display: none; }
  .treepanel .tn > a { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 4px; }
  .treepanel .tn > a:hover { text-decoration: underline; }
  .treepanel .empty { padding: 8px; color: var(--muted); font-size: 12px; }
  x-graph { position: fixed; inset: 0; z-index: var(--z-pal); display: flex; align-items: center; justify-content: center; }
  x-graph .gpanel { position: relative; width: min(920px, calc(100vw - 24px)); height: min(640px, calc(100vh - 24px)); background: var(--bg); border-radius: var(--r-4); box-shadow: var(--shadow-lg); display: flex; flex-direction: column; overflow: hidden; }
  x-graph .peek-head { padding: 0 12px; gap: 10px; }
  /* the spacer between the title and the node/link count collapses without a width */
  x-graph .peek-head .sp { flex: 1; }
  x-graph canvas { flex: 1; width: 100%; height: 100%; display: block; cursor: grab; }
  /* ---------- shortcuts modal + status/priority icons ---------- */
  x-shortcuts { position: fixed; inset: 0; z-index: var(--z-pal); display: flex; align-items: center; justify-content: center; }
  x-shortcuts .sc { height: auto; max-height: calc(100vh - 24px); width: min(760px, calc(100vw - 24px)); }
  .sc-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px 16px; padding: 8px 16px 16px; overflow-y: auto; font-size: 13px; }
  .sc-grid section > div { display: flex; align-items: center; gap: 6px; min-height: 26px; color: var(--muted); flex-wrap: wrap; }
  .sc-grid h6 { margin: 8px 0 4px; }
  .sti { display: inline-flex; position: relative; width: 14px; height: 14px; flex: 0 0 auto; color: var(--faint); vertical-align: -2px; margin-right: 6px; align-items: center; }
  .sti:empty { display: none; }
  .sti svg { width: 14px; height: 14px; }
  .sti[data-k="done"] { color: var(--ok); }
  .sti[data-k="prog"] { color: #e0a319; }
  .sti[data-k="x"] { color: var(--danger); }
  .pri { display: inline-flex; width: 14px; height: 12px; flex: 0 0 auto; color: var(--faint); align-items: flex-end; gap: 1px; }
  .pri i { width: 3px; background: currentColor; border-radius: 1px; opacity: .25; }
  .pri i.on { opacity: 1; }
  .pri[data-k="urgent"] { color: var(--danger); }
  .pri[data-k="high"] { color: #e0a319; }
  x-card h4 .sti { margin-right: 4px; }
  /* ================= responsive ================= */
  @media (max-width: 1100px) {
    x-page { --gx: 20px; }
    x-record .rec-grid { grid-template-columns: 1fr; gap: 8px; }
    x-record .rec-rail { position: static; max-height: none; overflow: visible; padding-left: 0; border-left: 0; order: -1; border-bottom: 1px solid var(--border); padding-bottom: 8px; }
    .two-col, .two-col.rev { grid-template-columns: 1fr; }
    x-inbox { grid-template-columns: 320px minmax(0, 1fr); }
    .prow { grid-template-columns: 20px minmax(0, 2fr) 90px 40px 100px 130px 20px; }
  }
  @media (max-width: 899px) {
    x-rail { position: fixed; top: auto; bottom: 0; left: 0; right: 0; height: calc(52px + env(safe-area-inset-bottom)); width: auto; flex-direction: row; justify-content: space-around; padding: 4px 4px calc(4px + env(safe-area-inset-bottom)); border-right: 0; border-top: 1px solid var(--border); background: var(--bg); gap: 0; }
    x-rail > *:not([data-m]) { display: none; }
    x-rail > a[data-m], x-rail > button[data-m] { display: flex; width: 60px; height: 44px; font-size: 10px; }
    x-rail > a > span, x-rail > button > span { display: block; }
    x-rail > a[aria-current]::before { display: none; }
    x-rail .badge { top: 0; right: 8px; }
    main { padding-bottom: 60px; }
    x-toasts { bottom: 64px; }
    x-selbar { bottom: 64px; }
    x-sidebar .mspaces { display: block; }
    x-inbox { grid-template-columns: 1fr; min-height: 0; height: auto; }
    x-inbox .ilist { border-right: 0; max-height: none; display: block; overflow: visible; }
    x-inbox .ihead { padding: 8px 8px 0; }
    x-inbox .irows { overflow: visible; padding: 0 8px 24px; }
    x-inbox .idetail { display: none; }
    x-inbox .irow .acts { display: flex; position: static; transform: none; box-shadow: none; background: transparent; }
    x-inbox .irow > time { display: none; }
    .prow { grid-template-columns: 16px minmax(0, 1fr) 80px 90px; }
    .prow .who, .prow > span:nth-child(5), .prow > span:last-child, .prow.head > span:nth-child(4), .prow.head > span:nth-child(5), .prow.head > span:last-child { display: none; }
    .prow .pg small, .prow .pg .prog { width: 60px; }
    x-pipeline .funnel { flex-wrap: wrap; }
    x-pipeline .stage { flex-basis: calc(50% - 4px); }
    .treepanel { flex-basis: 200px; width: 200px; }
    x-project .pname { font-size: 20px; }
    x-page.recpage { --gx: 16px; }
    x-record .rec-crumb { padding-top: 4px; }
    x-record .rec-tools .ver { display: none; }
    x-graph .gpanel { width: 100vw; height: 100vh; border-radius: 0; }
    x-sidebar { position: fixed; top: 0; bottom: 0; left: calc(-1 * var(--sidebar-w) - 8px); width: var(--sidebar-w); flex: 0 0 0; transition: left .18s ease; box-shadow: none; }
    body[data-drawer] x-sidebar { left: 0; box-shadow: var(--shadow-lg); }
    body[data-collapsed] x-sidebar { width: var(--sidebar-w); }
    x-sidebar .collapse { display: none; }
    .side-backdrop { display: none; position: fixed; inset: 0; background: rgba(15,15,15,.3); z-index: calc(var(--z-side) - 1); }
    body[data-drawer] .side-backdrop { display: block; }
    x-topbar .expand { display: inline-flex; }
    x-topbar { padding: 0 8px; }
    x-topbar .crumbs > :not(:last-child) { display: none; }
    x-topbar .crumbs > :last-child { max-width: 60vw; }
    x-topbar .topbar-right .txt span { display: none; }
    main { min-height: 100vh; }
    x-page { --gx: 16px; padding-top: 12px; }
    h1, .page-title { font-size: 22px; }
    x-viewbar { flex-wrap: wrap; }
    x-viewbar .tools { margin-left: 0; width: 100%; overflow-x: auto; scrollbar-width: none; padding-bottom: 2px; }
    x-viewbar .tools::-webkit-scrollbar { display: none; }
    x-viewbar .tool span { display: none; }
    x-viewbar .tool { padding: 0 8px; }
    x-grid { --title-w: 200px; --cell-w: 140px; max-height: calc(100vh - 44px - 170px); max-height: calc(100dvh - 44px - 170px); }
    x-cell, x-hcell { padding: 0 6px; }
    x-cell.gutter .sel { display: none; }
    x-row[aria-selected="true"] .gutter .sel { display: block; }
    x-kanban-column { flex: 0 0 85vw; width: 85vw; scroll-snap-align: center; }
    x-board { scroll-snap-type: x mandatory; scroll-padding: var(--gx); }
    x-calendar { --days: 3; --gw: 52px; }
    x-calendar[data-days="7"] { --days: 7; }
    x-calendar:not([data-days="7"]) [data-i="4"], x-calendar:not([data-days="7"]) [data-i="5"], x-calendar:not([data-days="7"]) [data-i="6"], x-calendar:not([data-days="7"]) [data-i="7"] { display: none; }
    x-calendar .cal-head .gh:not(:first-child), x-calendar .cal-body .gcol:not(:first-child), x-calendar .cal-allday .al:not(:first-child) { display: none; }
    x-calendar .cal-head, x-calendar .cal-body, x-calendar .cal-allday { grid-template-columns: var(--gw) repeat(var(--days), minmax(90px, 1fr)); }
    x-calendar .cal-allday .al { grid-column: 1; }
    x-calendar .cal-grid { min-width: 0; }
    .cal-days-toggle { display: inline-flex; }
    x-record .prop .k { flex-basis: 110px; width: 110px; }
    x-peek .peek-body { padding: 8px 20px 40px; }
    x-record .rec-title { font-size: 24px; }
    .icon-btn { width: 36px; height: 36px; }
    .icon-btn.sm { width: 28px; height: 28px; }
    x-hcell .hbtn { width: 28px; height: 28px; }
    x-item, x-list .newitem { min-height: 40px; }
    x-item .props .hov { opacity: 1; }
    x-item .props time { display: none; }
    .btn, .ghost, .mi, .tool { min-height: 36px; }
    x-viewbar .tabs a, x-viewbar .tab-add { height: 40px; }
    x-sidebar nav a, x-sidebar nav button.nav, x-sidebar details > summary { height: 36px; }
    x-sidebar .tnode .star { opacity: 1; top: 7px; }
    x-toasts { bottom: 12px; right: 12px; left: 12px; align-items: flex-end; }
    x-selbar { bottom: 12px; }
    .tplgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .frow.stackable { flex-wrap: wrap; }
    .frow.stackable > label { flex-basis: 100%; }
    .page-head .actions { margin-left: 0; width: 100%; }
    .roles-help { grid-template-columns: 1fr; }
  }
  @media (max-width: 719px) {
    x-peek .peek-panel, x-peek[data-mode="modal"] .peek-panel { top: 0; left: 0; right: 0; bottom: 0; width: 100%; max-height: none; border-radius: 0; margin-left: 0; }
    x-peek[data-mode="modal"] .peek-body { max-height: none; }
    x-peek .peek-head .modes { display: none; }
    x-palette { padding-top: 8px; }
    x-palette .pal { max-height: 85vh; }
    .cardgrid { grid-template-columns: 1fr 1fr; }
    x-gallery { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
    x-gallery[data-size="l"] { grid-template-columns: 1fr; }
    .frow:not(.keep) { flex-wrap: wrap; }
    .frow:not(.keep) > label { flex-basis: 100%; }
    x-record .prop { flex-wrap: wrap; }
    x-record .prop .k { flex-basis: 100%; width: 100%; height: 24px; font-size: 12px; }
    x-record .prop x-cell { flex-basis: 100%; }
    .tbl { font-size: 12px; }
    x-recent { flex-basis: 170px; width: 170px; }
  }
  @media (max-width: 479px) {
    .cardgrid { grid-template-columns: 1fr; }
    x-page { --gx: 12px; }
    x-grid { --title-w: 160px; --cell-w: 120px; --gutter-w: 36px; }
    .cal-nav .month { font-size: 14px; }
    x-kanban-column { flex: 0 0 88vw; width: 88vw; }
    x-record .rec-tools .ghost span { display: none; }
  }
}

@layer utilities {
  .stack { display: flex; flex-direction: column; gap: 10px; }
  .cluster { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
  .cluster.end { justify-content: flex-end; }
  .grid { display: grid; gap: 12px; }
  .between { justify-content: space-between; }
  .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .mt-2 { margin-top: 8px; } .mt-3 { margin-top: 12px; } .mt-4 { margin-top: 16px; } .mb-2 { margin-bottom: 8px; } .mb-3 { margin-bottom: 12px; }
  .grow { flex: 1; min-width: 0; }
  .nowrap { white-space: nowrap; }
  .ellip { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .hide-mobile { } .only-mobile { display: none !important; }
  @media (max-width: 899px) { .hide-mobile { display: none !important; } .only-mobile { display: initial !important; } }
}

/* ===================== pass 4: full width, rail tooltips + wide rail, sidebar hierarchy, projects index, drawer, relations, forms, month calendar ===================== */
@layer components {
  /* ---- full width everywhere: no content caps ---- */
  x-page, x-page.narrow, x-page.mid, x-page.wide, x-page.recpage { max-width: none; --gx: 20px; padding: 12px var(--gx) 0; }
  x-page[data-embed] { padding: 0; }
  .two-col { grid-template-columns: minmax(0, 1fr) 340px; }
  .two-col.rev { grid-template-columns: minmax(0, 1fr) 360px; }
  /* auto-fit: empty tracks collapse, so a short row of cards stretches to fill the width */
  .cardgrid { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); gap: 12px; }
  .home-grid { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }
  x-settings .stack > label { max-width: 560px; }
  x-inbox .idetail article { max-width: none; }
  x-record .rec-grid { grid-template-columns: minmax(0, 1fr) 320px; gap: 24px; }
  x-record .rec-side { display: none; }
  @media (min-width: 1440px) {
    /* the record page reads as Notion's: outline at the left, then one column - title, the
       property list under it, the body below */
    x-page.recpage x-record .rec-grid { grid-template-columns: var(--w-recside, 240px) minmax(0, 1fr); grid-template-rows: auto 1fr; }
    x-page.recpage x-record .rec-side { grid-row: 1 / 3; }
    x-page.recpage x-record .rec-rail { grid-column: 2; grid-row: 1; position: static; max-height: none; overflow: visible; padding-left: 0; border-left: 0; border-bottom: 1px solid var(--border); padding-bottom: 8px; }
    x-page.recpage x-record .rec-main { grid-column: 2; grid-row: 2; }
    x-page.recpage x-record .rec-rail .prop .k { flex-basis: 180px; width: 180px; }
    x-page.recpage x-record .rec-side { display: block; position: sticky; top: 52px; max-height: calc(100vh - 60px); overflow-y: auto; padding-right: 12px; border-right: 1px solid var(--border); font-size: 12px; }
    x-page.recpage x-record .rec-side h6 { padding: 8px 6px 4px; }
    x-page.recpage x-record .rec-side .toc-side a { display: block; padding: 3px 6px 3px calc(6px + (var(--l, 1) - 1) * 10px); color: var(--muted); border-radius: var(--r-1); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    x-page.recpage x-record .rec-side .toc-side a:hover { background: var(--hover); color: var(--fg); }
    /* the outline rail runs a notch smaller than the page; only its scale differs from the shared row */
    x-page.recpage x-record .rec-side .bl a { height: 26px; font-size: inherit; }
  }

  /* ---- the one tooltip: placed and timed by tooltip.js, never by the OS ---- */
  x-tip {
    position: fixed; display: block; max-width: min(280px, calc(100vw - 16px)); pointer-events: none;
    background: var(--fg); color: var(--bg); font-size: 12px; font-weight: 500; line-height: 1.35;
    padding: 5px 8px; border-radius: var(--r-1); box-shadow: var(--shadow-lg);
    animation: tipin .1s ease;
  }
  x-tip[hidden] { display: none; }
  @keyframes tipin { from { opacity: 0 } to { opacity: 1 } }

  /* ---- rail: hover-expand + pinned wide ---- */
  x-rail { transition: width .15s ease, flex-basis .15s ease; align-items: stretch; padding: 8px 4px; overflow: visible; }
  x-rail > a, x-rail > button { flex-direction: row; justify-content: flex-start; gap: 10px; width: auto; height: 36px; padding: 0 12px; border-radius: var(--r-2); font-size: 13px; }
  x-rail > a > .ico, x-rail > button > .ico { flex: 0 0 16px; }
  x-rail > a > span, x-rail > button > span { display: block; opacity: 0; white-space: nowrap; overflow: hidden; transition: opacity var(--t); }
  x-rail > a[aria-current]::before { left: -4px; top: 8px; bottom: 8px; }
  x-rail hr { width: auto; margin: 4px 8px; }
  x-rail .cap { display: block; height: 0; overflow: hidden; padding: 0 12px; font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); opacity: 0; transition: opacity var(--t); white-space: nowrap; }
  x-rail .badge { top: 6px; right: 6px; }
  x-rail .pin { color: var(--faint); height: 28px; margin-top: 2px; }
  x-rail .pin .ico { transition: transform .15s; }
  x-rail .pin[aria-pressed="true"] .ico { transform: rotate(180deg); }
  x-rail .pin span { font-size: 11px; }
  x-rail > .pop-anchor { align-self: center; }
  /* The rail NEVER expands on hover — hover shows only the tooltip label. Icons stay centered in a
     fixed 52px column. (An explicit pinned-wide mode via the pin button is the only way to show labels.) */
  x-rail > a, x-rail > button { justify-content: center; padding: 0; width: 40px; margin: 0 auto; }
  x-rail > a > span, x-rail > button > span { display: none; }
  x-rail .cap { display: none; }
  x-rail .badge { top: 4px; right: 4px; }
  body[data-rail="wide"] x-rail { width: 168px; flex-basis: 168px; }
  body[data-rail="wide"] x-rail > a, body[data-rail="wide"] x-rail > button { justify-content: flex-start; padding: 0 12px; width: auto; margin: 0; }
  body[data-rail="wide"] x-rail > a > span, body[data-rail="wide"] x-rail > button > span { display: block; opacity: 1; }
  body[data-rail="wide"] x-rail .cap { display: block; height: 22px; opacity: 1; padding-top: 6px; }

  /* ---- sidebar hierarchy: header, eyebrows, indentation guides, accent bar ---- */
  x-sidebar > section > header { height: 48px; padding: 0 8px 0 12px; border-bottom: 1px solid var(--border); margin-bottom: 4px; }
  x-sidebar > section > header h5 .hn { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
  x-sidebar > section > header h5 .hn b { font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-sidebar > section > header h5 .hn small { font-size: 11px; color: var(--faint); font-weight: 400; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-sidebar > section > header h5 .ico { color: var(--muted); }
  x-sidebar > section > header .ws-mark { width: 20px; height: 20px; font-size: 11px; line-height: 20px; }
  x-sidebar .tree h6 { font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--faint); font-weight: 600; padding: 10px 8px 3px; display: flex; align-items: center; gap: 6px; }
  x-sidebar .tree h6 .n { font-weight: 500; letter-spacing: 0; color: var(--faint); background: var(--hover); border-radius: 8px; padding: 0 5px; font-size: 10px; line-height: 15px; }
  x-sidebar .lvl { position: relative; margin-left: 11px; padding-left: 8px; }
  x-sidebar .lvl::before { content: ""; position: absolute; left: 0; top: 2px; bottom: 2px; width: 1px; background: var(--border-2); }
  x-sidebar .lvl h6 { padding: 6px 6px 2px; }
  x-sidebar .tnode { padding-left: 0; }
  x-sidebar .tnode > a, x-sidebar .pnode > a.prow { position: relative; height: var(--side-item-h); }
  x-sidebar nav a[aria-current]::before, x-sidebar .prow[aria-current]::before { content: ""; position: absolute; left: -8px; top: 5px; bottom: 5px; width: 3px; border-radius: 0 2px 2px 0; background: var(--accent); }
  x-sidebar .pnode > a.prow { display: flex; align-items: center; gap: 8px; padding: 0 8px; border-radius: var(--r-1); color: var(--fg); font-weight: 500; }
  x-sidebar .pnode > a.prow:hover { background: var(--hover); }
  x-sidebar .pnode > a.prow[aria-current] { background: var(--hover-2); }
  x-sidebar .pnode > a.prow .ellip { flex: 1; }
  x-sidebar .pnode > a.prow .pill.xs { opacity: 0; transition: opacity var(--t); }
  x-sidebar .pnode > a.prow:hover .pill.xs, x-sidebar .pnode[data-active] > a.prow .pill.xs { opacity: 1; }
  x-sidebar .pnode[data-active] .lvl { padding-bottom: 4px; }
  x-sidebar .tnode .star { top: 3px; }
  x-sidebar .tnode > a .ico { color: var(--faint); }
  /* where a table is filed, shown on the table itself so organising is visible from its space */
  x-sidebar .tnode .fchip { display: inline-flex; align-items: center; gap: 3px; margin-left: auto; padding: 0 5px; height: 16px; border-radius: 8px; font-style: normal; font-size: 10px; color: var(--faint); background: var(--hover); flex: 0 0 auto; max-width: 90px; overflow: hidden; }
  x-sidebar .tnode .fchip svg { width: 10px; height: 10px; }
  x-sidebar .tnode[data-active] > a .ico, x-sidebar .vlist a[aria-current] .ico { color: var(--fg); }
  x-topbar .crumbs .dot { margin-right: 6px; }

  /* ---- projects single-page index ---- */
  x-page.projects-index { padding-top: 6px; }
  x-page.projects-index .phead { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; min-height: 40px; padding: 4px 0 6px; }
  x-page.projects-index .pmain { display: flex; align-items: center; gap: 10px; flex: 1; min-width: 0; flex-wrap: wrap; }
  x-page.projects-index .pmain .page-title { font-size: 20px; margin: 0; padding: 0; line-height: 1.2; }
  x-page.projects-index .colr { position: relative; display: inline-flex; cursor: pointer; }
  x-page.projects-index .colr form { position: absolute; inset: 0; }
  x-page.projects-index .colr input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; padding: 0; cursor: pointer; }
  x-page.projects-index .pmain .who, x-page.projects-index .pmain .meta-item { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
  x-page.projects-index .pmain .pg { display: inline-flex; align-items: center; gap: 6px; }
  x-page.projects-index .pmain .pg .prog { width: 90px; }
  x-page.projects-index .pacts { display: flex; align-items: center; gap: 6px; }
  x-page.projects-index .ttabs { display: flex; align-items: center; gap: 2px; border-bottom: 1px solid var(--border); margin: 0 0 8px; overflow-x: auto; scrollbar-width: none; }
  x-page.projects-index .ttabs::-webkit-scrollbar { display: none; }
  x-page.projects-index .ttabs > a[role=tab], x-page.projects-index .ttabs .tab-add { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px; color: var(--muted); font-weight: 500; font-size: 13px; border-bottom: 2px solid transparent; margin-bottom: -1px; white-space: nowrap; border-radius: 3px 3px 0 0; }
  x-page.projects-index .ttabs > a[role=tab]:hover, x-page.projects-index .ttabs .tab-add:hover { color: var(--fg); background: var(--hover); }
  x-page.projects-index .ttabs > a[aria-current] { color: var(--fg); border-bottom-color: var(--fg); }
  x-page.projects-index .ttabs .sp { flex: 1; }
  x-page.projects-index .embed { min-width: 0; }
  .empty-hero { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 8px; padding: 64px 16px; margin: 24px auto; max-width: 560px; }
  .empty-hero > svg { width: 36px; height: 36px; color: var(--faint); }
  .empty-hero h1 { font-size: 22px; }
  .empty-hero h2 { font-size: 18px; }
  .empty-hero.sm { padding: 40px 16px; }
  .empty-hero .tplgrid { width: 100%; }

  /* ---- left quick drawer ---- */
  x-drawer { position: fixed; inset: 0; z-index: var(--z-peek); }
  x-drawer[hidden] { display: none; }
  x-drawer .drawer-backdrop { position: absolute; inset: 0; background: rgba(15,15,15,.25); animation: fadein var(--t) ease; }
  x-drawer .drawer-panel { position: absolute; top: 0; bottom: 0; left: var(--rail-w); width: min(var(--w-drawer, 380px), calc(100vw - var(--rail-w))); background: var(--bg); box-shadow: 8px 0 24px rgba(0,0,0,.1); display: flex; flex-direction: column; animation: slidein .16s ease forwards; }
  x-drawer[side="right"] .drawer-panel { left: auto; right: 0; box-shadow: -8px 0 24px rgba(0,0,0,.1); animation: slideinr .16s ease forwards; }
  @keyframes slideinr { from { transform: translateX(16px); opacity: 0; } to { transform: none; opacity: 1; } }
  @keyframes slidein { from { transform: translateX(-16px); opacity: 0; } to { transform: none; opacity: 1; } }
  x-drawer .drawer-head { display: flex; align-items: center; gap: 8px; height: 44px; padding: 0 8px 0 14px; border-bottom: 1px solid var(--border); flex: 0 0 44px; font-size: 13px; }
  x-drawer .drawer-head .sp { flex: 1; }
  x-drawer .drawer-body { flex: 1; overflow-y: auto; padding: 12px 14px 32px; gap: 14px; }
  x-drawer .drawer-body section { padding-top: 10px; border-top: 1px solid var(--border); }
  x-drawer .drawer-body h6.sec { display: flex; align-items: center; gap: 6px; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--faint); margin-bottom: 8px; }
  x-drawer .drawer-body h6.sec .n { margin-left: auto; font-size: 11px; background: var(--hover); border-radius: 8px; padding: 0 6px; letter-spacing: 0; color: var(--muted); }
  x-drawer .kv { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; min-height: 26px; }
  x-drawer .kv > span:first-child { color: var(--muted); }
  x-drawer .kv .pg { display: inline-flex; align-items: center; gap: 6px; }
  x-drawer .kv .pg .prog { width: 100px; }
  x-drawer .meta-form label > span { font-size: 12px; }
  x-drawer .health { display: flex; gap: 4px; flex-wrap: wrap; }
  x-drawer .health label { cursor: pointer; position: relative; }
  x-drawer .health input { position: absolute; opacity: 0; }
  x-drawer .health input:not(:checked) + .pill { opacity: .5; }
  x-drawer .health input:checked + .pill { box-shadow: 0 0 0 2px var(--bg), 0 0 0 3px var(--accent); }
  x-drawer x-timeline-list .upd { display: flex; gap: 8px; padding: 6px 0; font-size: 13px; }
  x-drawer x-timeline-list .uh { display: flex; align-items: center; gap: 6px; margin-bottom: 2px; flex-wrap: wrap; }
  x-drawer x-timeline-list .upd p { white-space: pre-wrap; overflow-wrap: anywhere; line-height: 1.5; }
  x-drawer .mlist li { display: flex; align-items: center; gap: 6px; height: 28px; font-size: 13px; }
  x-drawer .mlist li > span.ellip { flex: 1; }
  x-drawer .tlist li a { display: flex; align-items: center; gap: 8px; height: 28px; padding: 0 6px; margin: 0 -6px; border-radius: var(--r-1); font-size: 13px; }
  x-drawer .tlist li a:hover { background: var(--hover); }
  x-drawer .tlist li a > span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-drawer .newtbl summary { list-style: none; display: inline-flex; cursor: pointer; margin-top: 4px; }
  x-drawer .newtbl summary::-webkit-details-marker { display: none; }
  x-drawer .newtbl form { margin-top: 8px; }
  x-drawer .newtbl .tplgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* ---- computed cells + header marks ---- */
  /* The hatch is what says "the system writes this, you do not" - and it was a hardcoded
     light-mode rgba, so in dark mode a computed column looked exactly like an editable one.
     It now runs up into the header too, so the column reads as computed before you reach a cell.
     `not-allowed` is gone: none of the reference grids report an error where none happened. */
  x-cell[data-computed], x-hcell[data-computed] { --hatch: repeating-linear-gradient(135deg, transparent 0 6px, var(--hover) 6px 7px); background: var(--hatch); }
  x-hcell[data-computed]:hover { background: var(--hatch), var(--bg-2); }
  x-cell[data-computed] { color: var(--muted); }
  x-cell[data-computed] .chip { height: 18px; font-size: 11px; margin-right: 2px; }
  x-cell .err, .chip.comp .err { color: var(--danger); font: 11px var(--mono); }
  .mono { font-family: var(--mono); font-size: 12px; }
  textarea.mono { font-size: 12.5px; }
  .fieldform optgroup { font-style: normal; color: var(--faint); }
  .fieldform small code { background: var(--bg-code); padding: 0 3px; border-radius: 3px; }

  /* ---- relations panel ---- */
  x-relations { display: flex; flex-direction: column; gap: 14px; font-size: 13px; }
  x-relations section.two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  x-relations h6.sec { display: flex; align-items: center; gap: 6px; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--faint); margin-bottom: 6px; }
  x-relations h6.sec .n { font-size: 11px; letter-spacing: 0; background: var(--hover); border-radius: 8px; padding: 0 6px; color: var(--muted); }
  x-relations h6.sec .prog { width: 70px; margin-left: 4px; }
  x-relations .rels { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; min-height: 24px; }
  x-relations .rels.list { flex-direction: column; align-items: stretch; gap: 2px; }
  x-relations .rels.list li { display: flex; align-items: center; }
  x-relations .rels.list li[data-done] .relchip a .ellip { text-decoration: line-through; color: var(--muted); }
  x-relations .relchip { display: inline-flex; align-items: center; gap: 2px; max-width: 100%; height: 26px; padding: 0 2px 0 6px; border-radius: var(--r-1); background: var(--hover); }
  x-relations .rels.list .relchip { flex: 1; background: transparent; padding-left: 4px; }
  x-relations .rels.list .relchip:hover { background: var(--hover); }
  x-relations .relchip a { display: inline-flex; align-items: center; gap: 6px; min-width: 0; color: var(--fg); }
  x-relations .relchip a small { color: var(--faint); font-size: 11px; }
  x-relations .relchip .icon-btn.xs { width: 20px; height: 20px; opacity: 0; }
  x-relations .relchip:hover .icon-btn.xs, x-relations .relchip .icon-btn.xs:focus-visible { opacity: 1; }
  x-relations .chip.add { cursor: pointer; opacity: .7; height: 24px; }
  x-relations .chip.add:hover { opacity: 1; background: var(--hover-2); }
  x-relations .subtask-new { margin: 6px 0; }
  x-relations .subtask-new input { height: 28px; }
  x-relations .relpick { position: relative; }
  x-relations .relpick-pop { position: absolute; left: 0; top: calc(100% + 4px); z-index: var(--z-pop); width: min(320px, 80vw); background: var(--bg); border-radius: var(--r-3); box-shadow: var(--shadow-lg); padding: 6px; }
  x-relations .relpick-pop input { height: 28px; margin-bottom: 4px; }
  x-relations .relpick-pop .menu-list { max-height: 220px; overflow-y: auto; }
  x-relations .relpick-pop .mi small { margin-left: auto; color: var(--faint); font-size: 11px; }
  x-relations .relpick-pop .empty { padding: 8px; color: var(--faint); font-size: 12px; }
  x-relations .faint { font-size: 12px; }

  /* ---- table settings extras ---- */
  .checkgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 2px 8px; }
  .checkgrid .check, label.check { display: flex; align-items: center; gap: 6px; min-height: 26px; font-size: 13px; cursor: pointer; }
  label.check > span { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
  label.check > input, label.check > svg { flex: 0 0 auto; }
  .pill.toggle { cursor: pointer; }
  .pill.toggle:hover { filter: brightness(.95); }
  .pill[data-role] { text-transform: none; }
  .note.warn { background: var(--warn-bg); color: var(--pc3-fg); align-items: flex-start; }
  .note.warn svg { flex: 0 0 auto; margin-top: 1px; }
  .tabs-ui .n { margin-left: 2px; }
  [data-import-result] .note { margin-top: 8px; }
  .dropzone { display: block; cursor: pointer; }
  .dropzone > span { display: inline-flex; align-items: center; gap: 6px; }

  /* ---- public form page ---- */
  body.pubform { display: block; background: var(--bg-side); min-height: 100vh; }
  .pubform-wrap { display: flex; justify-content: center; padding: 48px 16px; }
  x-pubform { display: block; width: 100%; max-width: 560px; background: var(--bg); border-radius: var(--r-4); box-shadow: var(--shadow); padding: 28px 28px 20px; }
  x-pubform header { margin-bottom: 16px; }
  x-pubform header small { text-transform: uppercase; letter-spacing: .05em; font-size: 11px; font-weight: 600; }
  x-pubform header h1 { font-size: 22px; margin: 2px 0 6px; }
  x-pubform label > span { display: block; font-size: 12px; color: var(--muted); margin-bottom: 4px; }
  x-pubform label > span em { color: var(--danger); font-style: normal; }
  x-pubform .check { display: inline-flex; align-items: center; gap: 6px; height: 28px; }
  x-pubform .hp { position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden; }
  x-pubform footer { text-align: center; margin-top: 20px; font-size: 11px; }
  x-pubform .thanks { text-align: center; padding: 24px 0; }
  x-pubform .thanks .ok-mark { display: inline-flex; width: 40px; height: 40px; border-radius: 50%; background: var(--ok-bg); color: var(--ok); align-items: center; justify-content: center; margin-bottom: 8px; }
  x-pubform .thanks .ok-mark svg { width: 20px; height: 20px; }
  x-pubform .thanks h2 { font-size: 18px; margin-bottom: 4px; }
  x-pubform .thanks .btn { margin-top: 12px; }
  /* a page or view published to web (templates/public.html) */
  body.pubpage { display: block; height: auto; min-height: 100vh; overflow: auto; }
  .pubpage-wrap { max-width: 760px; margin: 0 auto; padding: 56px 16px 32px; }
  .pubpage-wrap.wide { max-width: 1200px; }
  .pubpage-wrap > h1 { margin-bottom: 12px; overflow-wrap: anywhere; }
  .pub-props { display: grid; grid-template-columns: minmax(100px, 160px) 1fr; gap: 6px 16px; margin: 0 0 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border); }
  .pub-props dt { color: var(--muted); }
  .pub-props dd { margin: 0; overflow-wrap: anywhere; }
  .pub-table-scroll { overflow-x: auto; margin-top: 12px; border-top: 1px solid var(--border); }
  .pub-table { border-collapse: collapse; width: 100%; font-size: 13px; }
  .pub-table th { text-align: left; font-weight: 500; color: var(--muted); }
  .pub-table th, .pub-table td { padding: 6px 8px; border-bottom: 1px solid var(--border); border-right: 1px solid var(--border); vertical-align: top; max-width: 320px; overflow-wrap: anywhere; }
  .pub-table th:last-child, .pub-table td:last-child { border-right: 0; }
  .pub-table td:first-child { font-weight: 500; }
  .pubpage-wrap > footer { margin-top: 32px; font-size: 12px; }

  /* ---- calendar: range switcher, month grid, all-day, duration ---- */
  .cal-range { gap: 2px; }
  .cal-range > a { height: 24px; padding: 0 8px; border-radius: 4px; font-size: 12px; color: var(--muted); font-weight: 500; display: inline-flex; align-items: center; }
  .cal-range > a[aria-pressed="true"] { background: var(--bg); color: var(--fg); box-shadow: 0 1px 2px rgba(0,0,0,.08); }
  .cal-allday[data-empty] { display: none; }
  .cal-body .ev.pill { height: auto; min-height: 22px; line-height: 1.3; font-weight: 400; white-space: normal; border-radius: var(--r-1); }
  .cal-body .ev.pill .n { white-space: nowrap; }
  .cal-body .ev.pc0 { border-left-color: var(--faint); }
  .cal-month { border: 1px solid var(--border); border-radius: var(--r-2); overflow: hidden; margin-top: 4px; }
  .cal-month .mh-row { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--border-2); background: var(--bg); }
  .cal-month .mdow { padding: 6px 8px; font-size: 11px; text-transform: uppercase; color: var(--muted); font-weight: 500; }
  .cal-month .mgrid { display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: minmax(calc((100vh - 240px) / var(--rows, 6)), auto); }
  .cal-month .mday { border-right: 1px solid var(--border); border-bottom: 1px solid var(--border); padding: 4px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
  .cal-month .mday:nth-child(7n) { border-right: 0; }
  .cal-month .mday[data-out] { background: var(--bg-2); }
  .cal-month .mday[data-out] .dn { color: var(--faint); }
  .cal-month .mday .dn { font-size: 12px; font-weight: 500; width: 22px; height: 22px; line-height: 22px; text-align: center; border-radius: 11px; }
  .cal-month .mday[data-today] .dn { background: var(--accent); color: #fff; }
  .cal-month .mevs { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
  .cal-month .mev { display: flex; align-items: center; gap: 4px; height: 20px; padding: 0 5px; font-size: 11px; border-radius: 3px; text-align: left; max-width: 100%; cursor: pointer; }
  .cal-month .mev .t { font-weight: 600; flex: 0 0 auto; opacity: .8; }
  .cal-month .mev .ellip { min-width: 0; }
  .cal-month .more { font-size: 11px; color: var(--muted); padding: 0 5px; }
  .cal-month .more:hover { color: var(--fg); text-decoration: underline; }
  x-calendar[data-range="day"] .cal-grid, x-calendar[data-range="3day"] .cal-grid { min-width: 0; }
  x-calendar[data-range="day"] .cal-head, x-calendar[data-range="day"] .cal-body, x-calendar[data-range="day"] .cal-allday,
  x-calendar[data-range="3day"] .cal-head, x-calendar[data-range="3day"] .cal-body, x-calendar[data-range="3day"] .cal-allday { grid-template-columns: repeat(var(--gutters, 1), var(--gw)) repeat(var(--days), minmax(110px, 1fr)); }

  /* ---- density: 13px chrome, 28px controls, 12px card padding ---- */
  .card { padding: 12px; }
  .page-head { margin-bottom: 6px; }
  h1.page-title { font-size: 22px; }
  x-page.narrow h1.page-title, x-page.mid h1.page-title { font-size: 20px; }
  .tabs-ui { margin: 6px 0 14px; }
  x-settings section { padding: 14px 0; }
  x-record .rec-title { font-size: 26px; }
  x-record .rec-head { padding-top: 8px; }
  x-record .prop { min-height: 28px; font-size: 13px; }
  x-record .prop .k { height: 28px; }
  x-record .prop x-cell { min-height: 28px; font-size: 13px; }
  x-record .rec-main > div > section { padding: var(--s-3) 0 var(--s-6); }

  @media (max-width: 899px) {
    /* mobile bottom tab bar: icon + tiny label, no hover behaviour */
    x-rail > a > span, x-rail > button > span { display: block; opacity: 1; font-size: 10px; }
    x-rail > a, x-rail > button { flex-direction: column; gap: 2px; width: auto; height: auto; padding: 4px 6px; margin: 0; }
    body[data-rail="wide"] x-rail { width: auto; }
    x-rail > a, x-rail > button { flex-direction: column; gap: 2px; padding: 0; justify-content: center; }
    x-rail .cap, x-rail .pin, x-rail hr { display: none !important; }
    x-drawer .drawer-panel { left: 0; width: min(380px, 100vw); }
    x-page.projects-index .pmain .pg { display: none; }
    x-relations section.two { grid-template-columns: 1fr; }
    x-calendar[data-range="month"] [data-i], x-calendar[data-range="day"] [data-i], x-calendar[data-range="3day"] [data-i] { display: block; }
    x-calendar[data-range="day"] .cal-head, x-calendar[data-range="day"] .cal-body, x-calendar[data-range="day"] .cal-allday,
    x-calendar[data-range="3day"] .cal-head, x-calendar[data-range="3day"] .cal-body, x-calendar[data-range="3day"] .cal-allday { grid-template-columns: var(--gw) repeat(var(--days), minmax(90px, 1fr)); }
    x-calendar[data-range="day"] .cal-days-toggle, x-calendar[data-range="3day"] .cal-days-toggle, x-calendar[data-range="month"] .cal-days-toggle { display: none; }
  }
}
@layer components {
  x-page.projects-index x-grid { max-height: calc(100vh - 44px - 190px); max-height: calc(100dvh - 44px - 190px); }
  x-page.projects-index x-board { margin: 0; padding-left: 0; padding-right: 0; }
  x-page.projects-index x-kanban-column { max-height: calc(100vh - 270px); }
}
/* ---- pass5: tree/detail/chart views ---- */
@layer components {
  .tree-tools, .chart-tools { gap: 12px; align-items: center; margin: 4px 0 10px; font-size: 13px; flex-wrap: wrap; }
  .tree-tools > label, .chart-tools > label { gap: 6px; align-items: center; }
  .tree-tools select, .chart-tools select { font-size: 13px; }
  .tree-tools .count { margin-left: auto; }
  x-tree { display: block; }
  x-tree x-titem { display: block; }
  x-tree x-titem > .trow { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 6px 0 calc(6px + var(--d, 0) * 22px); border-radius: var(--r-2); position: relative; }
  x-tree x-titem > .trow::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: calc(var(--d, 0) * 22px + 6px); background: repeating-linear-gradient(to right, transparent 0 15px, var(--border-2) 15px 16px, transparent 16px 22px); background-position: 6px 0; pointer-events: none; opacity: .8; }
  x-tree x-titem > .trow:hover { background: var(--hover); }
  x-tree x-titem[data-over] > .trow { outline: 2px solid var(--accent); outline-offset: -2px; background: var(--selected); }
  x-tree x-titem > .trow > .v { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
  x-tree x-titem > .trow > .open, x-tree x-titem > .trow > .addc { opacity: 0; }
  x-tree x-titem > .trow:hover > .open, x-tree x-titem > .trow:hover > .addc { opacity: 1; }
  x-tree x-titem[data-leaf] > .trow > .tog { visibility: hidden; }
  x-tree x-titem > .trow > .tog svg { transition: transform .12s; }
  x-tree x-titem[data-collapsed] > .trow > .tog svg { transform: rotate(-90deg); }
  x-tree x-titem[data-collapsed] > .kids { display: none; }
  x-tree .newchild { padding: 2px 6px 2px calc(34px + var(--d, 0) * 22px); }
  x-tree .newchild input { width: 100%; font-size: 13px; }
  x-detail { display: grid; grid-template-columns: 280px 1fr; gap: 0; border: 1px solid var(--border); border-radius: var(--r-3); min-height: 60vh; overflow: hidden; }
  x-detail > .dlist { border-right: 1px solid var(--border); overflow-y: auto; max-height: 80vh; padding: 4px; }
  /* the pane is already inside the table: no breadcrumb repeating it; tabs scroll rather than clip */
  x-detail > .pane .rec-crumb { display: none; }
  x-detail > .pane .rtabs { overflow-x: auto; }
  x-detail > .dlist > .ditem { display: flex; align-items: center; gap: 6px; height: 32px; padding: 0 8px; border-radius: var(--r-2); color: inherit; text-decoration: none; font-size: 13px; }
  x-detail > .dlist > .ditem:hover { background: var(--hover); }
  x-detail > .dlist > .ditem[aria-current] { background: var(--selected); }
  x-detail > .dlist > .ditem > .v { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  x-detail > .dlist > .newitem { display: flex; align-items: center; gap: 6px; padding: 4px 8px; }
  x-detail > .dlist > .newitem input { flex: 1; border: 0; background: transparent; font-size: 13px; }
  x-detail > .dlist > .count { padding: 6px 8px; font-size: 12px; }
  x-detail > .pane { overflow-y: auto; max-height: 80vh; padding: 12px 20px; }
  x-detail > .pane [data-peek-close], x-detail > .pane .rec-close { display: none; }
  @media (max-width: 720px) { x-detail { grid-template-columns: 1fr; } x-detail > .dlist { max-height: 30vh; border-right: 0; border-bottom: 1px solid var(--border); } }
  x-chart { display: block; --c0: #2383e2; --c1: #d9730d; --c2: #0f7b6c; --c3: #e03e3e; --c4: #6940a5; --c5: #0b6e99; --c6: #ad1a72; --c7: #64473a; --c8: #9b9a97; }
  x-chart > canvas { display: block; width: 100%; height: 300px; }
  x-chart > .legend { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 10px; font-size: 12px; color: var(--muted); }
  x-chart > .legend > .li { display: inline-flex; align-items: center; gap: 6px; }
  x-chart > .legend > .li > i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
  x-chart > .legend > .li > b { color: var(--fg); font-weight: 500; }
}

/* ---- pass5: auth/admin/settings ---- */
@layer components {
  .hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
  x-login .note.ok a { text-decoration: underline; }
  x-login [aria-invalid="true"] { border-color: var(--danger, #c33); }
  #admin-root .admin-notice { display: block; }
  #admin-root .admin-notice pre.key { display: block; margin: 8px 0 0; padding: 6px 8px; font-size: 12px; white-space: pre-wrap; word-break: break-all; cursor: copy; border-radius: 4px; background: var(--hover); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
  #admin-root pre.key { display: block; margin: 0; padding: 6px 8px; font-size: 12px; white-space: pre-wrap; word-break: break-all; cursor: copy; border-radius: 4px; background: var(--hover); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
  #admin-root .admin-pop { min-width: min(440px, calc(100vw - 32px)); padding: 12px; }
  #admin-root .admin-pop.wide { min-width: min(500px, calc(100vw - 32px)); }
  #admin-root .admin-menu { min-width: 260px; }
  #admin-root .admin-menu form { display: block; }
  #admin-root .admin-menu .mi { width: 100%; }
  #admin-root .admin-menu .mi-form { display: flex; flex-direction: column; gap: 4px; padding: 4px 6px; }
  #admin-root .admin-menu .mi-form input { height: 28px; font-size: 12px; }
  #admin-root .tbl tr.inactive td { opacity: .55; }
  #admin-root .tbl td.num, #admin-root .tbl th.num { text-align: right; }
  #admin-root .tbl td.end .pop-anchor { justify-content: flex-end; }
  #admin-root .tabs-ui > button.danger { color: var(--danger, #c33); }
  #admin-root .statgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; margin: 0 0 12px; }
  #admin-root .statgrid .stat { border: 1px solid var(--border); border-radius: 6px; padding: 10px 12px; display: flex; flex-direction: column; gap: 2px; }
  #admin-root .statgrid .stat > b { font-size: 18px; font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }
  #admin-root .statgrid .stat > span { font-size: 12px; color: var(--muted); }
  #admin-root .radios { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
  #admin-root .radios .check { align-items: flex-start; height: auto; line-height: 1.4; }
  #admin-root .radios .check input { margin-top: 3px; }
  #admin-root .danger-zone { border-color: var(--danger, #c33); }
  #admin-root .danger-zone h3 { color: var(--danger, #c33); }
  #admin-root .btn.danger { color: #fff; background: var(--danger, #c33); border-color: var(--danger, #c33); }
  #admin-root .btn.danger:disabled { opacity: .5; cursor: not-allowed; }
  .pill[data-v="active"], .pill[data-v="pending"] { background: color-mix(in srgb, #2a9d5c 18%, transparent); color: #1f7a45; }
  .pill[data-v="inactive"], .pill[data-v="used"] { background: var(--hover); color: var(--muted); }
}
/* ---- pass5: x-select ---- */
@layer components {
  select.xs-native { position: absolute !important; width: 1px !important; height: 1px !important; opacity: 0 !important; pointer-events: none !important; margin: 0; padding: 0; border: 0; overflow: hidden; }
  x-select { display: inline-flex; position: relative; min-width: 0; max-width: 100%; }
  .frow > x-select, label > x-select, .stack > x-select, .popover .stack > label x-select { flex: 1; width: 100%; }
  x-select > .xs-btn {
    display: inline-flex; align-items: center; gap: 6px; width: 100%; min-height: var(--ctl-h); padding: 0 6px 0 8px; font-size: 13px; color: var(--fg); text-align: left;
    border: 1px solid var(--border-2); border-radius: var(--r-1); background: var(--bg); cursor: pointer; transition: border-color var(--t), box-shadow var(--t);
  }
  x-select > .xs-btn:hover { background: var(--hover); }
  /* --selected is a SELECTION tint, not a focus halo (see the token comment): at 14% it reads as
     almost nothing around a focused edge. The custom select stands in for a native one, so it
     gets the same inset accent perimeter every other field uses (never an outer ring). */
  x-select > .xs-btn:focus-visible { outline: none; border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
  x-select > .xs-btn:disabled { opacity: .55; cursor: default; }
  x-select > .xs-btn.lg { min-height: 34px; font-size: 14px; }
  x-select > .xs-btn > .xs-lab { flex: 1; min-width: 0; display: flex; align-items: center; flex-wrap: wrap; gap: 4px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
  x-select > .xs-btn > .xs-lab.ph { color: var(--faint); }
  x-select > .xs-btn > svg { flex: 0 0 auto; color: var(--faint); }
  x-select .chip { padding-right: 2px; }
  x-select .xs-rm { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; border-radius: 3px; font-weight: 500; color: var(--faint); }
  x-select .xs-rm:hover { background: var(--hover-2); color: var(--fg); }
  .xs-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
  .popover.xs-pop { padding: 4px; min-width: 180px; max-width: min(360px, calc(100vw - 16px)); outline: none; }
  .popover.xs-pop > .xs-q { width: 100%; height: var(--ctl-h); margin-bottom: 4px; }
  .popover.xs-pop > .xs-list { max-height: min(50vh, 320px); overflow: auto; }
  .popover.xs-pop .mh { font-size: 11px; color: var(--faint); padding: 6px 8px 2px; text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
  .popover.xs-pop .mi.hl { background: var(--hover); }
  /* two-line options (the field-type picker): icon, name, and what the type is for */
  .popover.xs-pop .mi.two { height: auto; min-height: 42px; padding: 5px 8px; align-items: center; gap: 9px; }
  .popover.xs-pop .mi > .xs-ico { flex: 0 0 auto; width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-1); box-shadow: inset 0 0 0 1px var(--border); color: var(--muted); }
  .popover.xs-pop .mi > .xs-ico svg { width: 14px; height: 14px; }
  .popover.xs-pop .mi.two .xs-t { display: flex; flex-direction: column; gap: 0; }
  .popover.xs-pop .mi.two .xs-t b { font-weight: 500; line-height: 17px; }
  .popover.xs-pop .mi.two .xs-t small { font-size: 11px; line-height: 14px; color: var(--faint); }
  .popover.xs-pop .mi .xs-t { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .popover.xs-pop .mi > svg { margin-left: auto; color: var(--accent); flex: 0 0 auto; }
  .popover.xs-pop .mi.xs-new { color: var(--accent); }
  .popover.xs-pop .xs-empty { padding: 8px; color: var(--faint); font-size: 12px; }
  x-tzlist { display: flex; flex-direction: column; gap: 6px; }
  x-tzlist > .tzrow { display: flex; align-items: center; gap: 6px; min-width: 0; padding: 2px; border-radius: var(--r-1); }
  x-tzlist > .tzrow.drag { opacity: .4; }
  x-tzlist > .tzrow > x-select { flex: 2; }
  x-tzlist > .tzrow > input { flex: 1; max-width: 160px; }
  x-tzlist > .tzrow > .pin[hidden] { display: none; }

  /* ---- x-datepicker: trigger + picker popover ----------------------------------------
     datepicker.js has always built <x-datepicker> and .dp-pop, but no stylesheet ever
     matched them: the native <input type=date> stayed visible beside the custom button
     (browser-painted calendar icon, locale-ordered fields) and the popover rendered as an
     unstyled stack. This is that missing layer. */
  /* a status/choice select that should read as a pill, not as a form field. The class sits on
     the real <select>, which select.js hides - so style the x-select it inserts right after. */
  select.sel-pill + x-select > .xs-btn {
    min-height: 22px; height: 22px; align-self: center; padding: 0 6px; gap: 4px; font-size: 12px; font-weight: 500; text-transform: capitalize;
    border-color: transparent; background: var(--hover); border-radius: 11px;
  }
  select.sel-pill + x-select > .xs-btn:hover { background: var(--hover-2); }
  select.sel-pill + x-select > .xs-btn > svg { opacity: .5; }
  .pstatus { display: inline-flex; align-items: center; width: auto; }

  /* datepicker.js and color.js are lazy: they tag the input they took over with .dp-native /
     .xc-native, but that is a round trip after the markup lands, and in the gap the browser
     paints its own calendar and its own OS colour dialog. Hide the raw control on the type
     alone so it is never on screen. Both are gated on scripting being available, because with
     it off nothing will ever replace them and they have to stay ordinary usable inputs: the
     media feature covers the gap before any script has run, [data-js] (set by app.js) covers
     browsers that do not support it. [data-native] is the opt-out both modules honour when a
     template really does want the browser control. */
  @media (scripting: enabled) {
    input[type=date]:not([data-native]),
    input[type=datetime-local]:not([data-native]),
    input[type=color]:not([data-native]) { position: absolute !important; width: 1px !important; height: 1px !important; opacity: 0 !important; pointer-events: none !important; margin: 0; padding: 0; border: 0; }
  }
  html[data-js] input[type=date]:not([data-native]),
  html[data-js] input[type=datetime-local]:not([data-native]),
  html[data-js] input[type=color]:not([data-native]),
  input.dp-native { position: absolute !important; width: 1px !important; height: 1px !important; opacity: 0 !important; pointer-events: none !important; margin: 0; padding: 0; border: 0; }
  x-datepicker { display: inline-flex; min-width: 0; max-width: 100%; }
  x-datepicker > .dp-btn {
    display: inline-flex; align-items: center; width: 100%; min-height: var(--ctl-h); padding: 0 8px; font-size: 13px; color: var(--fg); text-align: left;
    border: 1px solid var(--border-2); border-radius: var(--r-1); background: var(--bg); cursor: pointer; white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; transition: border-color var(--t), background var(--t);
  }
  x-datepicker > .dp-btn:hover { background: var(--hover); }
  x-datepicker > .dp-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
  x-datepicker > .dp-btn.ph { color: var(--faint); }
  x-cell x-datepicker > .dp-btn, .meta x-datepicker > .dp-btn { border-color: transparent; background: none; }
  x-cell x-datepicker > .dp-btn:hover, .meta x-datepicker > .dp-btn:hover { background: var(--hover); }

  .popover.dp-pop { width: 292px; padding: 8px; display: flex; flex-direction: column; gap: 4px; }
  .dp-pop .dp-top { display: flex; align-items: center; gap: 4px; }
  .dp-pop .dp-in, .dp-pop .dp-tin { height: var(--ctl-h); min-width: 0; flex: 1 1 auto; font-size: 13px; }
  .dp-pop .dp-arr, .dp-pop .dp-e { display: none; }
  .dp-pop.r .dp-arr { display: block; color: var(--faint); flex: 0 0 auto; }
  .dp-pop.r .dp-e { display: block; }
  .dp-pop .dp-tin { display: none; }
  .dp-pop.t .dp-tin { display: block; flex: 0 0 88px; }
  /* a timed range: the start's date and time on one line, the end's on the next */
  .dp-pop.r.t .dp-top { flex-wrap: wrap; }
  .dp-pop.r.t .dp-arr { display: none; }
  .dp-pop.r.t .dp-in { flex: 1 1 60%; }

  /* the 15-minute time list drops under the time field */
  .dp-pop .dp-tl { display: none; }
  .dp-pop .dp-tl:not([hidden]) { display: block; max-height: 178px; overflow: auto; overscroll-behavior: contain; padding: 3px; border: 1px solid var(--border); border-radius: var(--r-2); }
  .dp-pop .dp-tl > button { display: block; width: 100%; height: 26px; padding: 0 8px; text-align: left; font-size: 13px; color: var(--fg); border-radius: var(--r-1); }
  .dp-pop .dp-tl > button:hover { background: var(--hover); }

  .dp-pop .dp-h { display: flex; align-items: center; justify-content: space-between; padding: 4px 2px 0; }
  .dp-pop .dp-h > b { font-size: 13px; font-weight: 600; }
  .dp-pop .dp-h > span { display: flex; gap: 2px; }
  .dp-pop .dp-h button { width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; font-size: 16px; line-height: 1; color: var(--muted); border-radius: var(--r-1); }
  .dp-pop .dp-h button:hover { background: var(--hover); color: var(--fg); }

  .dp-pop .dp-g { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1px; }
  .dp-pop .dp-g > i { font-style: normal; font-size: 11px; font-weight: 500; color: var(--faint); text-align: center; line-height: 24px; }
  .dp-pop .dp-g > button { height: 30px; display: flex; align-items: center; justify-content: center; font-size: 13px; color: var(--fg); border-radius: var(--r-1); }
  .dp-pop .dp-g > button:hover { background: var(--hover); }
  .dp-pop .dp-g > button.o { color: var(--faint); }
  .dp-pop .dp-g > button.td { font-weight: 700; color: var(--danger); }
  .dp-pop .dp-g > button.in { background: var(--hover-2, var(--hover)); border-radius: 0; }
  .dp-pop .dp-g > button.on { background: var(--accent); color: #fff; font-weight: 500; }
  .dp-pop .dp-g > button.on.td { color: #fff; }

  .dp-pop .dp-r { display: flex; align-items: center; gap: 8px; min-height: 32px; padding: 0 2px; font-size: 13px; border-radius: var(--r-1); }
  .dp-pop .dp-r[data-a] { cursor: pointer; }
  .dp-pop .dp-r[data-a]:hover { background: var(--hover); }
  .dp-pop .dp-r > span:first-child { flex: 1; }
  .dp-pop .dp-r > b { color: var(--faint); }
  .dp-pop .dp-v { color: var(--muted); max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .dp-pop label.dp-r > x-select, .dp-pop label.dp-r > select { flex: 0 0 150px; max-width: 150px; }
  .dp-pop .dp-r[data-a="z"] { border-top: 1px solid var(--border); margin-top: 4px; padding-top: 4px; }

  /* the switches are <i role=switch>, painted entirely here */
  .dp-pop .dp-sw { position: relative; flex: 0 0 auto; width: 30px; height: 17px; border-radius: 9px; background: var(--border-2); transition: background var(--t); }
  .dp-pop .dp-sw::after { content: ""; position: absolute; top: 2px; left: 2px; width: 13px; height: 13px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.3); transition: transform var(--t); }
  .dp-pop .dp-sw[aria-checked="true"] { background: var(--accent); }
  .dp-pop .dp-sw[aria-checked="true"]::after { transform: translateX(13px); }

  .dp-pop .dp-tzp { display: none; }
  .dp-pop .dp-tzp:not([hidden]) { display: flex; flex-direction: column; gap: 4px; }
  .dp-pop .dp-tzl { max-height: 196px; overflow: auto; overscroll-behavior: contain; display: flex; flex-direction: column; }
  .dp-pop .dp-tzl > button { text-align: left; height: 28px; padding: 0 8px; font-size: 13px; color: var(--fg); border-radius: var(--r-1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .dp-pop .dp-tzl > button:hover { background: var(--hover); }
  .dp-pop .dp-tzl > button.on { color: var(--accent); font-weight: 500; }

  .dp-pop .dp-clr { height: 30px; margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--border); font-size: 13px; color: var(--muted); border-radius: 0 0 var(--r-1) var(--r-1); }
  .dp-pop .dp-clr:hover { color: var(--danger); background: var(--hover); }

  /* ---- x-color: the custom colour picker (native <input type=color> opens an OS dialog) ---- */
  input.xc-native { position: absolute !important; width: 1px !important; height: 1px !important; opacity: 0 !important; pointer-events: none !important; margin: 0; padding: 0; border: 0; }
  x-color { display: inline-flex; position: relative; vertical-align: middle; }
  x-color > .xc-btn {
    display: inline-flex; align-items: center; gap: 6px; min-height: var(--ctl-h); padding: 2px 6px; font-size: 12px; color: var(--fg);
    border: 1px solid var(--border-2); border-radius: var(--r-1); background: var(--bg); cursor: pointer; transition: border-color var(--t), box-shadow var(--t);
  }
  x-color > .xc-btn:hover { border-color: var(--border-3, var(--border)); background: var(--hover); }
  x-color > .xc-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
  x-color > .xc-btn > .xc-sw { width: 16px; height: 16px; border-radius: var(--r-1); box-shadow: inset 0 0 0 1px rgba(0,0,0,.18); flex: 0 0 auto; }
  x-color > .xc-btn > .xc-hex { font-variant-numeric: tabular-nums; letter-spacing: .02em; color: var(--muted); }
  .colr x-color > .xc-btn, [data-autosave] x-color > .xc-btn { padding: 2px; border-color: transparent; background: none; }
  .colr x-color > .xc-btn > .xc-sw, [data-autosave] x-color > .xc-btn > .xc-sw { width: 20px; height: 20px; border-radius: 50%; }

  .popover.xc-pop { width: 232px; padding: 8px; display: flex; flex-direction: column; gap: 8px; }
  .xc-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 6px; }
  .xc-cell {
    height: 26px; border-radius: var(--r-1); cursor: pointer; border: 0; color: #fff;
    display: inline-flex; align-items: center; justify-content: center; box-shadow: inset 0 0 0 1px rgba(0,0,0,.18);
  }
  .xc-cell.lt { color: #37352f; }
  .xc-cell:hover { transform: scale(1.06); }
  .xc-cell:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .xc-sv { position: relative; height: 108px; border-radius: var(--r-2); cursor: crosshair; touch-action: none; box-shadow: inset 0 0 0 1px rgba(0,0,0,.18); }
  .xc-hue {
    position: relative; height: 12px; border-radius: 6px; cursor: ew-resize; touch-action: none; box-shadow: inset 0 0 0 1px rgba(0,0,0,.18);
    background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
  }
  .xc-thumb {
    position: absolute; width: 12px; height: 12px; border-radius: 50%; transform: translate(-50%, -50%);
    border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0,0,0,.35), var(--shadow); pointer-events: none;
  }
  .xc-foot { display: flex; gap: 6px; align-items: center; }
  .xc-foot > .xc-in { flex: 1; min-width: 0; height: var(--ctl-h); font-variant-numeric: tabular-nums; text-transform: uppercase; }
}
@layer components {
  x-tzlist > .tzrow > .pin { flex: 0 0 auto; font-size: 11px; color: var(--accent); background: var(--selected); border-radius: 8px; padding: 0 6px; height: 18px; line-height: 18px; }
}

/* ---- pass5: field system, folder tree, link picker, modals, resizer, menus ---- */
@layer components {
  x-field { display: flex; align-items: center; position: relative; width: 100%; min-width: 0; }
  x-field > input, x-field > textarea { flex: 1; min-width: 0; padding-right: 26px; }
  x-field > .xclr, x-field > .xeye { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; border-radius: 4px; color: var(--faint); background: transparent; border: 0; padding: 0; cursor: pointer; }
  x-field > .xclr:hover, x-field > .xeye:hover { background: var(--hover); color: var(--fg); }
  x-field[data-empty] > .xclr { display: none; }
  x-field > .xeye[aria-pressed="true"] { color: var(--accent); }
  x-field > textarea ~ .xclr { top: 8px; transform: none; }
  x-field > .xclr:focus-visible, x-field > .xeye:focus-visible { background: var(--hover); color: var(--fg); }
  /* inside the control, never below it: .stack leaves only 10px between fields, so a counter
     hung underneath would land on the next label. It parks left of the clear button, and the
     input is given room for both so it can never sit on top of the value. */
  x-field > x-cnt { position: absolute; right: 26px; top: 50%; transform: translateY(-50%); font-size: 11px; line-height: 1; color: var(--faint); font-variant-numeric: tabular-nums; pointer-events: none; }
  x-field > textarea ~ x-cnt { top: auto; bottom: 6px; right: 8px; transform: none; }
  x-field:has(> x-cnt) > input { padding-right: 62px; }
  x-field:focus-within > x-cnt { color: var(--muted); }
  /* a counter that never changes colour is decoration; the wall is the only number that matters */
  x-field > x-cnt[data-full] { color: var(--danger); font-weight: 500; }
  x-field > x-meter { position: absolute; left: 0; right: 0; bottom: -6px; display: flex; gap: 3px; height: 3px; padding: 0 2px; }
  x-field > x-meter > i { flex: 1; background: var(--border-2); border-radius: 2px; }
  x-field > x-meter[data-score="1"] > i:nth-child(1) { background: var(--danger); }
  x-field > x-meter[data-score="2"] > i:nth-child(-n+2) { background: #e0a319; }
  x-field > x-meter[data-score="3"] > i { background: #3d9a50; }
  x-field > input[type=search] { padding-left: 26px; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 16 16' fill='none' stroke='%23888' stroke-width='1.6' stroke-linecap='round'%3E%3Ccircle cx='7' cy='7' r='4.5'/%3E%3Cpath d='M10.5 10.5 14 14'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: 8px center; }
  input[type=search]::-webkit-search-cancel-button { display: none; }
  input:hover:not(:focus):not(:disabled), textarea:hover:not(:focus):not(:disabled) { border-color: var(--faint); }
  input:disabled, textarea:disabled, select:disabled { background: var(--hover); color: var(--muted); }
  input:user-invalid, textarea:user-invalid, [aria-invalid="true"] { border-color: var(--danger) !important; }
  /* an invalid field kept the accent-blue focus ring, which contradicted its own red border */
  input:user-invalid:focus-visible, textarea:user-invalid:focus-visible, [aria-invalid="true"]:focus-visible { box-shadow: inset 0 0 0 1px var(--danger); }
  input[type=number] { text-align: right; font-variant-numeric: tabular-nums; }
  label[data-required] > span:first-child::after { content: " *"; color: var(--danger); }
  label > small { display: block; font-size: 11px; color: var(--muted); margin-top: 3px; }
  x-auth input, .auth input, x-auth .btn, .auth .btn { --ctl-h: 32px; }
  x-auth .btn.primary, .auth .btn.primary { width: 100%; justify-content: center; }
  /* not a grid cell: its focus ring is the ::after ring drawn inside it (one 2px border); this
     outline on top of it doubled the left and right edges and spilled over the row line */
  :is(button, a, [tabindex]:not(x-cell)):focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

  x-sidebar .fnode { position: relative; }
  x-sidebar .fnode > .frow2 { display: flex; align-items: center; height: var(--side-item-h); border-radius: var(--r-1); position: relative; padding-right: 2px; }
  x-sidebar .fnode > .frow2:hover, x-sidebar .fnode.dropping > .frow2 { background: var(--hover); }
  x-sidebar .fnode.dropping > .frow2 { box-shadow: inset 0 0 0 1.5px var(--accent); }
  x-sidebar .ftree.dropping { box-shadow: inset 0 0 0 1.5px var(--accent); border-radius: var(--r-1); }
  x-sidebar .fnode > .frow2 > .chev { width: 18px; height: 18px; border: 0; background: transparent; color: var(--faint); border-radius: 4px; display: inline-flex; align-items: center; justify-content: center; margin-left: 2px; cursor: pointer; }
  x-sidebar .fnode > .frow2 > .chev svg { transition: transform var(--t); }
  x-sidebar .fnode[data-open] > .frow2 > .chev svg { transform: rotate(90deg); }
  x-sidebar .fnode > .frow2 > .prow { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; padding: 0 4px; height: 100%; color: var(--fg); font-weight: 500; border-radius: var(--r-1); }
  x-sidebar .fnode > .frow2 > .prow[aria-current] { background: var(--hover-2); }
  /* folder icons stay monochrome like every other sidebar icon (the colour lives on the
     project dot, not the folder glyph) */
  x-sidebar .fico { color: var(--faint); display: inline-flex; }
  x-sidebar .fico svg { fill: none; }
  x-sidebar .fnode > .frow2 > .rowmore, x-sidebar .fnode > .frow2 > .rowadd, x-sidebar .pnode > .rowmore { opacity: 0; width: 20px; height: 20px; color: var(--faint); }
  x-sidebar .tree h6 .rowadd { opacity: 1; width: 20px; height: 20px; color: var(--faint); }
  x-sidebar .tree h6 .rowadd:hover { color: var(--fg); background: var(--hover); }
  x-sidebar .fnode > .frow2:hover > .icon-btn, x-sidebar .pnode:hover > .rowmore, x-sidebar .tree h6:hover .rowadd { opacity: 1; }
  x-sidebar .pnode { position: relative; }
  x-sidebar .pnode > .rowmore { position: absolute; right: 2px; top: 3px; }
  x-sidebar .pnode > a.prow { padding-right: 24px; }
  x-sidebar .tree h6 .rowadd:first-of-type { margin-left: auto; }
  x-sidebar .tree h6 .rowadd + .rowadd { margin-left: 2px; }
  x-sidebar .fnode > .fkids { display: none; }
  x-sidebar .fnode[data-open] > .fkids { display: block; }
  x-sidebar [data-drag].dragging { opacity: .4; }
  .popover.fmove { min-width: 200px; }
  x-folderhead { display: block; padding: 8px 0 4px; border-bottom: 1px solid var(--border); margin-bottom: 8px; }
  x-folderhead .fcrumbs { display: flex; align-items: center; gap: 4px; font-size: 13px; flex-wrap: wrap; }
  x-folderhead .fh-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
  x-folderhead .fh-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
  x-folderhead .ftables { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
  x-folderhead .ftables a { display: inline-flex; align-items: center; gap: 6px; height: 26px; padding: 0 10px; border: 1px solid var(--border-2); border-radius: 999px; font-size: 12px; color: var(--fg); }
  x-folderhead .ftables a:hover { border-color: var(--accent); color: var(--accent); }
  x-folderhead .fcrumbs a { display: inline-flex; align-items: center; gap: 4px; color: var(--muted); padding: 2px 4px; border-radius: 3px; }
  x-folderhead .fcrumbs a:hover { background: var(--hover); color: var(--fg); }
  x-folderhead .fcrumbs a.cur { color: var(--fg); font-weight: 600; font-size: 15px; }
  x-folderhead .fcrumbs .sep { color: var(--faint); }
  x-folderhead .fdata { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
  x-folderhead .fdata .chip b { color: var(--muted); font-weight: 500; margin-right: 4px; }
  x-folderhead .fdata .chip.inh { border-style: dashed; }
  x-folderhead .fhint { font-size: 12px; margin: 4px 0 0; }

  .popover.linkpick { width: 320px; padding: 6px; display: flex; flex-direction: column; gap: 4px; }
  .popover.linkpick .lp-list { max-height: 260px; overflow-y: auto; display: flex; flex-direction: column; }
  .popover.linkpick .lp-list .mi { display: flex; align-items: center; gap: 8px; height: var(--menu-item-h); padding: 0 6px; cursor: pointer; border-radius: var(--r-1); }
  .popover.linkpick .lp-list .mi:hover { background: var(--hover); }
  .popover.linkpick .lp-list .mi .ellip { flex: 1; }
  .popover.linkpick .lp-list .empty { padding: 12px; color: var(--faint); font-size: 12px; text-align: center; }
  .popover.linkpick .lp-foot { display: flex; align-items: center; gap: 6px; border-top: 1px solid var(--border); padding-top: 6px; }
  .popover.linkpick .lp-foot .sp { flex: 1; }
  x-cell[data-type="link"] { gap: 3px; flex-wrap: nowrap; overflow: hidden; }
  /* whole pills: the cell clips at a pill's edge, never through its text */
  x-cell[data-type="link"] .pill, x-cell[data-type="multiselect"] .pill, x-cell[data-type="select"] .pill { flex: 0 0 auto; }
  x-cell[data-type="multiselect"] { flex-wrap: nowrap; overflow: hidden; }
  .pill.lk { cursor: pointer; }
  .pill.lk:hover { text-decoration: underline; }

  /* native <dialog> in the top layer: no z-index/clipping games, focus trap + ::backdrop free */
  dialog.settings-modal { padding: 0; border: 0; background: none; max-width: none; max-height: none; width: min(var(--w-settings, var(--mw, 900px)), calc(100vw - 16px)); height: min(80vh, 760px); color: var(--fg); overflow: visible; }
  dialog.settings-modal::backdrop { background: rgba(15,15,15,.45); backdrop-filter: blur(1px); }
  dialog.settings-modal .mbox { width: 100%; height: 100%; background: var(--bg); border-radius: var(--r-4); box-shadow: var(--shadow-lg); display: flex; flex-direction: column; overflow: hidden; animation: fadein2 .16s ease; }
  /* imperative menus join the top layer (above the dialog). Reset the UA popover box:
     `inset: 0` would stretch them, and margin would recentre them. */
  .popover:popover-open { inset: auto; margin: 0; border: 0; padding: var(--s-2); background: var(--bg); overflow: auto; }
  .popover.ctx:popover-open { padding: 4px; }
  /* legacy selector kept so any x-modal left in a cached page still renders */
  x-modal.settings-modal { position: fixed; inset: 0; z-index: var(--z-peek); }
  x-modal.settings-modal[hidden] { display: none; }
  x-modal.settings-modal .mbox { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: min(var(--mw, 900px), calc(100vw - 16px)); height: min(80vh, 760px); background: var(--bg); border-radius: var(--r-4); box-shadow: var(--shadow-lg); display: flex; flex-direction: column; overflow: hidden; animation: fadein2 .16s ease; }

  /* ---- shared inner layout: applies to BOTH <dialog class="settings-modal"> and legacy x-modal.
     (These used to be scoped to x-modal only, so after the move to native <dialog> the whole
     settings/admin/table-settings body rendered unstyled — header, tab rail and panels stacked.) ---- */
  /* the dialog reuses the peek header markup (b + .sp + open-as-page + close) */
  .settings-modal .mhead, .settings-modal .peek-head { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; height: 46px; padding: 0 10px 0 16px; border-bottom: 1px solid var(--border); background: var(--bg); position: static; }
  .settings-modal .mhead h2, .settings-modal .peek-head > b { flex: 0 0 auto; font-size: 15px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .settings-modal .peek-head > .sp { flex: 1 1 auto; }
  .settings-modal .peek-head .icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: var(--r-1); color: var(--muted); }
  .settings-modal .peek-head .icon-btn:hover { background: var(--hover); color: var(--fg); }
  .settings-modal .mbody { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0 16px 16px; }
  .settings-modal .mbody x-page, .settings-modal .mbody .page-title { max-width: none; width: 100%; padding: 0; }
  .settings-modal .mbody x-page.narrow, .settings-modal .mbody x-page.mid, .settings-modal .mbody x-page.wide { max-width: none; }
  /* The injected root (#settings-root / #admin-root / #tsettings-root) is:
     .page-head + [data-notice]? + .tabs-ui[data-tabs] + x-settings > section[data-panel].
     Use flex wrap so the panels container (x-settings) sits beside the tab rail regardless
     of nesting depth — a grid on direct children mis-placed x-settings into column 1. */
  .settings-modal .mbody > div { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 0 16px; }
  .settings-modal .mbody > div > h1,
  .settings-modal .mbody > div > .page-title,
  .settings-modal .mbody > div > .page-head,
  .settings-modal .mbody > div > .note,
  .settings-modal .mbody > div > [data-notice] { flex: 1 0 100%; min-width: 0; }
  .settings-modal .mbody > div > .page-head { padding-top: 4px; margin-bottom: 8px; }
  .settings-modal .mbody > div > .page-head .page-title { font-size: 20px; }
  /* the tab rail stays in view while a long panel scrolls beside it; the divider is the panel's
     left border, so it still runs the panel's full height */
  .settings-modal .mbody > div > [data-tabs] {
    flex: 0 0 var(--w-mtabs, 190px); display: flex; flex-direction: column; align-items: stretch; gap: 2px;
    border-bottom: 0; padding: 0 8px 8px 0; align-self: flex-start; position: sticky; top: 0;
    max-height: 100%; overflow-y: auto;
  }
  .settings-modal .mbody > div > [data-tabs] [data-tab] { justify-content: flex-start; height: var(--side-item-h); border-radius: var(--r-1); border-bottom: 0; margin: 0; padding: 0 8px; font-size: 13px; color: var(--muted); }
  .settings-modal .mbody > div > [data-tabs] [data-tab]:hover { background: var(--hover); color: var(--fg); }
  .settings-modal .mbody > div > [data-tabs] [data-tab][aria-selected="true"] { background: var(--hover-2); color: var(--fg); font-weight: 500; }
  .settings-modal .mbody > div > x-settings,
  .settings-modal .mbody > div > [data-panel] { flex: 1 1 320px; min-width: 0; border-left: 1px solid var(--border); margin-left: -16px; padding-left: 16px; align-self: stretch; }
  /* only the selected panel shows; without this every section stacked at once */
  .settings-modal .mbody x-settings > section[data-panel][hidden],
  .settings-modal .mbody > div > section[data-panel][hidden] { display: none; }
  .settings-modal .mbody x-settings section:first-child { padding-top: 4px; }
  .settings-modal .mbody .tblwrap { overflow-x: auto; }
  .settings-modal .mbody table { width: 100%; }
  .settings-modal .mbody .actions .btn { white-space: nowrap; }
  .settings-modal .mfoot { flex: 0 0 auto; display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 10px 16px; border-top: 1px solid var(--border); background: var(--bg); }
  .muted.pad { padding: 16px; }
  @media (max-width: 700px) {
    .settings-modal .mbody > div > [data-tabs] { flex: 1 0 100%; flex-direction: row; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--border); padding: 0 0 6px; position: static; }
    .settings-modal .mbody > div > x-settings, .settings-modal .mbody > div > [data-panel] { flex: 1 0 100%; border-left: 0; margin-left: 0; padding-left: 0; }
  }

  /* month view: drag a chip onto another day */
  x-calendar .mev { cursor: grab; }
  x-calendar .mev[data-dragging] { opacity: .45; cursor: grabbing; }
  x-calendar .mev.saving { opacity: .6; }
  x-calendar .mday[data-over] { background: color-mix(in srgb, var(--accent) 10%, transparent); outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent); outline-offset: -2px; }

  /* dragging events on the calendar (move anywhere, resize from the bottom 8px) */
  x-calendar .dcol .ev { cursor: grab; touch-action: none; }
  x-calendar .dcol .ev.dragging { cursor: grabbing; z-index: var(--z-drag); opacity: .9; box-shadow: var(--shadow-lg); }
  x-calendar .dcol .ev.saving { opacity: .6; }
  x-calendar .dcol .ev::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 8px; cursor: ns-resize; }
  x-calendar .dcol .ev.more::after { display: none; }

  /* ---------- discussions (x-chat) ---------- */
  /* one-click decision bar (leave requests) */
  .decide-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 0 10px; border-bottom: 1px solid var(--border); margin-bottom: 8px; font-size: 12px; }
  .decide-bar .btn.ok { background: var(--ok, #2e7d32); color: #fff; }
  .decide-bar .btn.danger { background: var(--danger, #c62828); color: #fff; }
  .decide-bar .btn[disabled] { opacity: .5; }

  /* tag index */
  .tagcloud { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
  .tagchip { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border-radius: 14px; background: var(--hover); color: var(--muted); font-size: 13px; }
  .tagchip:hover { background: var(--hover-2); color: var(--fg); }
  .tagchip > b { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
  .tagchip.on { background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); }
  .tagchip.on > b { color: inherit; }

  /* presence stack: overlapping avatars of everyone viewing this page */
  .who-stack { display: inline-flex; align-items: center; margin-right: 6px; }
  .who-stack > .avatar { margin-left: -6px; box-shadow: 0 0 0 2px var(--bg); }
  .who-stack > .avatar:first-child { margin-left: 0; }
  .who-stack > .avatar.more { background: var(--hover-2); color: var(--muted); }

  /* ---------- filter / sort / group editors (viewbar.js), hosted by View settings ---------- */
  .vb-body { display: flex; flex-direction: column; gap: 6px; }
  .vb-row { display: flex; align-items: flex-start; gap: 6px; }
  .vb-lead { flex: 0 0 62px; padding-top: 5px; font-size: 12px; color: var(--faint); }
  .vb-lead-sel { flex: 0 0 62px; }
  .vb-rule { display: flex; align-items: center; gap: 6px; flex: 1 1 auto; min-width: 0; flex-wrap: wrap; }
  .vb-rule > select, .vb-rule > x-select { flex: 1 1 130px; min-width: 110px; }
  .vb-rule > input { flex: 1 1 130px; min-width: 100px; }
  .vb-group { display: flex; flex-direction: column; gap: 6px; }
  /* a nested group is boxed so the And/Or it applies to is unambiguous */
  .vb-subgroup { flex: 1 1 auto; min-width: 0; padding: 6px; border: 1px solid var(--border); border-radius: var(--r-2); background: var(--bg-2); }
  .vb-subgroup .vb-lead { flex-basis: 46px; }
  .vb-more { flex: 0 0 auto; margin-top: 2px; color: var(--faint); }
  .vb-more:hover { color: var(--fg); background: var(--hover); }
  .vb-foot { display: flex; align-items: center; gap: 6px; padding-top: 6px; margin-top: 2px; border-top: 1px solid var(--border); }
  .vb-check { margin-left: 68px; font-size: 13px; }
  .muted.sm, .ghost.xs { font-size: 12px; }
  .ghost.xs { align-self: flex-start; margin-left: 68px; color: var(--muted); }

  /* filter rows: Notion's "Where / And / Or" lead-in column */
  .popover .frow > .fw { flex: 0 0 46px; font-size: 12px; color: var(--faint); }
  .popover .frow > select.conj { flex: 0 0 72px; }
  /* one badge, wherever a count rides a control in this bar: the viewbar's own tools (a static
     <b> from the template, a b.n built by viewbar.js) and the
     discussion button's unread count. --bg as the ink went dark-on-blue in dark mode. */
  x-viewbar .tool > b, [data-chat-drawer] > b.n {
    display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px;
    padding: 0 4px; margin-left: 2px; border-radius: 8px;
    font-size: 10px; font-weight: 600; font-variant-numeric: tabular-nums;
    color: var(--accent-fg); background: var(--accent);
  }
  .mention { padding: 0 3px; border-radius: 3px; color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); font-weight: 500; }
  .popover.ment { padding: 4px; max-height: 260px; overflow-y: auto; }
  .popover.ment .mi { display: flex; align-items: center; gap: 8px; width: 100%; height: var(--menu-item-h); padding: 0 8px; border-radius: var(--r-1); font-size: 13px; color: var(--fg); text-align: left; }
  .popover.ment .mi.on, .popover.ment .mi:hover { background: var(--hover); }
  x-chat { position: relative; display: flex; flex-direction: column; min-height: 0; height: 100%; }
  x-chat .ch-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; display: flex; flex-direction: column; gap: 2px; padding: 8px 2px; }
  x-chat .ch-msg { display: flex; gap: 8px; padding: 4px 6px; border-radius: var(--r-2); }
  x-chat .ch-msg:hover { background: var(--hover); }
  x-chat .ch-msg.pending { opacity: .55; }
  x-chat .ch-msg.failed { opacity: .8; box-shadow: inset 0 0 0 1px var(--danger, #c62828); cursor: pointer; }
  x-chat .ch-b { min-width: 0; flex: 1; }
  x-chat .ch-b header { display: flex; align-items: baseline; gap: 6px; }
  x-chat .ch-b header b { font-size: 13px; font-weight: 600; }
  x-chat .ch-b header time { font-size: 11px; color: var(--faint); font-variant-numeric: tabular-nums; }
  /* threading: one level, shown as a quote line above the reply */
  x-chat .ch-reply { margin-left: auto; opacity: 0; font-size: 11px; color: var(--faint); padding: 0 4px; border-radius: 3px; }
  x-chat .ch-msg:hover .ch-reply, x-chat .ch-reply:focus-visible { opacity: 1; }
  x-chat .ch-reply:hover { background: var(--hover-2); color: var(--fg); }
  x-chat .ch-quote { display: flex; align-items: baseline; gap: 6px; margin-bottom: 2px; padding-left: 8px; border-left: 2px solid var(--border-2); font-size: 11.5px; color: var(--faint); }
  x-chat .ch-quote > b { color: var(--muted); font-weight: 600; flex: 0 0 auto; }
  x-chat .ch-quote > span { min-width: 0; }
  x-chat .ch-replying { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-radius: var(--r-1); background: var(--hover); font-size: 11.5px; color: var(--muted); margin-bottom: 4px; }
  x-chat .ch-replying > span { flex: 1; }
  x-chat .ch-b p { font-size: 13.5px; line-height: 1.5; white-space: pre-wrap; word-wrap: break-word; }
  x-chat .ch-more { align-self: center; height: 26px; padding: 0 10px; margin-bottom: 6px; border-radius: 13px; font-size: 12px; color: var(--muted); background: var(--hover); }
  x-chat .ch-more:hover { background: var(--hover-2); color: var(--fg); }
  /* shape and type come from .empty-state (sm, bare); this only parks it in the middle of the
     message list, which is a flex column */
  x-chat .ch-empty { margin: auto; max-width: 320px; }
  x-chat .ch-typing { height: 16px; padding: 0 8px; font-size: 11px; color: var(--faint); font-style: italic; }
  x-chat .ch-new { position: absolute; left: 50%; bottom: 62px; transform: translateX(-50%); height: 26px; padding: 0 12px; border-radius: 13px; font-size: 12px; color: var(--bg); background: var(--accent); box-shadow: var(--shadow); z-index: 2; }
  x-chat .ch-form { display: flex; align-items: flex-end; gap: 6px; padding: 6px 2px 2px; border-top: 1px solid var(--border); }
  x-chat .ch-form textarea { flex: 1; min-height: var(--ctl-h); max-height: 160px; resize: none; padding: 6px 8px; font-size: 13.5px; line-height: 1.45; }
  x-chat .ch-form .btn { flex: 0 0 auto; height: var(--ctl-h); }
  x-chat[data-compact] .ch-list { max-height: 320px; }
  /* in a drawer the chat owns the scrolling, not the drawer body - otherwise the composer
     gets pushed past the bottom edge and clipped */
  x-drawer .drawer-body[data-chat-mount] { display: flex; flex-direction: column; overflow: hidden; padding-bottom: 12px; }
  x-drawer [data-chat-mount] { display: flex; flex-direction: column; flex: 1; min-height: 0; }
  x-drawer x-chat .ch-form { padding-bottom: 4px; }

  /* A wide grab area with a hairline drawn inside it: 6px is what the pointer needs, 2px is
     what the eye wants. Painting the whole grab area gives a fat blue slab. */
  x-resizer { position: absolute; top: 0; bottom: 0; width: 6px; cursor: col-resize; z-index: 5; right: -3px; user-select: none; touch-action: none; background: none; }
  x-resizer::after {
    content: ""; position: absolute; top: 0; bottom: 0; left: 50%; width: 3px; transform: translateX(-50%);
    background: transparent; transition: background var(--t) ease;
  }
  x-resizer:hover::after, x-resizer.on::after, x-resizer:focus-visible::after { background: var(--accent); }
  x-resizer:focus-visible { outline: none; }
  x-resizer[data-side="left"] { right: auto; left: -3px; }
  @media (min-width: 900px) { x-sidebar { position: relative; } }
  /* the sidebar clips its overflow, so the handle sits inside the edge and its line rides the border */
  x-sidebar > x-resizer { right: 0; }
  x-sidebar > x-resizer::after { left: auto; right: 0; transform: none; }
  body[data-collapsed] x-sidebar > x-resizer { display: none; }
  @media (hover: none), (pointer: coarse) { x-sidebar > x-resizer { display: none; } }
  body { --sidebar-w: var(--w-sidebar, 240px); }
  x-peek .peek-panel { width: min(var(--w-peek, 560px), 100vw); }
  /* Which edge the side peek flies in from is the reader's choice: a right-handed layout puts it
     opposite the sidebar, a left one keeps it beside the tree it was opened from. */
  x-peek[data-side="left"] .peek-panel { right: auto; left: 0; box-shadow: 8px 0 24px rgba(0,0,0,.1); }
  /* The centred card keeps a width of its own, --w-peek-modal, dragged from the same handle: app.js
     re-keys it by mode and marks it data-center, so the drag grows both edges. */
  x-peek[data-mode="modal"] .peek-panel { margin-left: calc(min(var(--w-peek-modal, 860px), calc(100vw - 16px)) / -2); width: min(var(--w-peek-modal, 860px), calc(100vw - 16px)); }
  /* Below 720px the peek is the whole screen in either mode. The phone rule earlier in this file
     says so, but the width rules above come later and win: a dragged width shrank it, and the
     centred card's negative margin pushed it half off the left edge. Nothing to drag there either. */
  @media (max-width: 719px) {
    x-peek .peek-panel, x-peek[data-mode="modal"] .peek-panel { width: 100%; margin-left: 0; }
    x-peek .peek-panel > x-resizer { display: none; }
  }
  dialog.settings-modal > .mbox { position: relative; }
  /* list pane ~40% of the inbox so notification titles fit; a dragged width still wins */
  x-inbox { grid-template-columns: var(--w-inbox, clamp(380px, 40%, 640px)) minmax(0, 1fr); }
  @media (max-width: 899px) { x-inbox { grid-template-columns: 1fr; } }
  x-detail { grid-template-columns: var(--w-detail, 280px) minmax(0, 1fr); }
  .peek-panel, x-inbox > :first-child, x-detail > .dlist { position: relative; }
  /* These four clip their own overflow (or sit against another pane), so the handle rides just
     inside the edge instead of hanging 3px outside it, where it would be cut off or unreachable. */
  x-inbox > .ilist > x-resizer, x-detail > .dlist > x-resizer,
  x-record .rec-side > x-resizer, x-drawer .drawer-panel > x-resizer { right: 0; }
  x-inbox > .ilist > x-resizer::after, x-detail > .dlist > x-resizer::after,
  x-record .rec-side > x-resizer::after, x-drawer .drawer-panel > x-resizer::after { left: auto; right: 0; transform: none; }
  x-drawer[side="right"] .drawer-panel > x-resizer { right: auto; left: 0; }
  x-drawer[side="right"] .drawer-panel > x-resizer::after { left: 0; right: auto; }
  /* the outline column only exists on the wide record layout; nothing to drag below that */
  x-record .rec-side > x-resizer { display: none; }
  @media (min-width: 1440px) { x-page.recpage x-record .rec-side > x-resizer { display: block; } }
  body.resizing, body.resizing * { cursor: col-resize !important; user-select: none !important; }

  .popover.ctx { min-width: 200px; }
  .popover.ctx .mi { display: flex; align-items: center; gap: 8px; width: 100%; height: var(--menu-item-h); padding: 0 8px; border: 0; background: transparent; text-align: left; border-radius: var(--r-1); cursor: pointer; color: var(--fg); font: inherit; }
  .popover.ctx .mi:hover { background: var(--hover); }
  .popover.ctx .mi.danger { color: var(--danger); }
  .toast .undo { margin-left: 10px; color: var(--accent); background: none; border: 0; font: inherit; font-weight: 600; cursor: pointer; }
  .skel { display: block; height: 12px; border-radius: 4px; background: linear-gradient(90deg, var(--hover) 25%, var(--hover-2) 50%, var(--hover) 75%); background-size: 200% 100%; animation: skel 1.2s infinite linear; margin: 8px 0; }
  @keyframes skel { from { background-position: 200% 0; } to { background-position: -200% 0; } }
}
@layer components {
  .popover.ctx.xmenu { padding: 4px; min-width: 220px; max-width: 300px; }
  .popover.ctx.xmenu > input { margin-bottom: 4px; height: 26px; }
  .popover.ctx.xmenu .ml { display: flex; flex-direction: column; max-height: 60vh; overflow-y: auto; }
  .popover.ctx.xmenu hr { margin: 4px 0; }
  .popover.ctx .mi .arr { margin-left: auto; display: inline-flex; align-items: center; color: var(--faint); }
  .popover.ctx .mi .arr > svg { width: 14px; height: 14px; }
  .popover.ctx .mi .kbd { margin-left: auto; }
  .popover.ctx .mi .kbd + .arr { margin-left: 6px; }
  .tz-grip > svg, .tz-del > svg, .gh-more > svg, .vb-more > svg { width: 14px; height: 14px; }
  .xs-rm > svg { width: 11px; height: 11px; vertical-align: -1px; }
  .popover.ctx .mi .dot { width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto; }
  .popover.ctx .mi:disabled { opacity: .5; cursor: default; }
  /* A 6% hover tint is not a focus indicator — it composites to about 1.05:1 and is exactly what
     the mouse already paints, so keyboard focus in a menu was invisible. Keep the tint, put the
     ring back inside the item's own box so it does not overlap the neighbour above it. */
  .popover.ctx .mi:focus-visible { background: var(--hover); outline: 2px solid var(--accent); outline-offset: -2px; }
  .popover.ctx .mfoot { border-top: 1px solid var(--border); margin-top: 4px; padding: 5px 8px 2px; font-size: 11px; color: var(--faint); }
  .popover.ctx.submenu { min-width: 160px; }
  .inline-rename { height: 24px; font: inherit; }
  x-sidebar .pnode > [data-ctx-open] { position: absolute; right: 2px; top: 3px; }
}
@layer components {
  body[data-density="compact"] { --row-h: 30px; --ctl-h: 26px; --side-item-h: 25px; --menu-item-h: 26px; }
}

/* ===================== pass 6: grid parity — cell ranges, drag order, freeze, summaries, new field types ===================== */
@layer components {
  x-grid { --frz-shadow: none; }
  x-grid[data-sx] { --frz-shadow: 6px 0 8px -6px rgba(0,0,0,.22); }
  x-grid[data-sy] x-ghead { box-shadow: 0 6px 8px -8px rgba(0,0,0,.45); }
  x-grid[data-busy] x-gbody { opacity: .55; transition: opacity .12s; pointer-events: none; }
  x-grid[data-rangeing], x-grid[data-coldrag] { user-select: none; -webkit-user-select: none; }

  /* ---------- A. cell range selection ----------
     Notion draws a single selected cell as a blue BORDER with no fill - the value has to stay
     readable - and tints only a multi-cell range, lightly. A single cell carries all four edges
     ("tblr"), which is exactly how we tell the two apart. */
  x-cell[data-rng]::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 1;
    border: 0 solid var(--accent); background: transparent;
  }
  x-cell[data-rng]:not([data-rng="tblr"])::after { background: var(--range-fill); }
  x-cell.editing[data-rng]::after { display: none; }   /* never paint over what is being edited */
  x-cell[data-rng*="t"]::after { border-top-width: 2px; }
  x-cell[data-rng*="b"]::after { border-bottom-width: 2px; }
  x-cell[data-rng*="l"]::after { border-left-width: 2px; }
  x-cell[data-rng*="r"]::after { border-right-width: 2px; }
  .dropline { position: absolute; left: 0; right: 0; top: 0; height: 2px; z-index: var(--z-guide); pointer-events: none; background: var(--accent); }

  /* ---------- B. rows: drag handle, group headers, colour rules ---------- */
  /* The one drag handle (Notion's): six dots in an 18 x 24 target, faint, a soft grey square under
     the pointer, a grab cursor. Grid rows, blocks, property lists, options, zones and header items
     all draw this, so a handle looks and behaves the same wherever something can be dragged. */
  .grip-h, x-cell.gutter .dh, .blk > .bh .bg, .vs-panel .vs-grip, .hdrprops .hp-row .grip, .tagpick .tp-row .grip, x-tzlist > .tzrow > .tz-grip {
    display: inline-flex; align-items: center; justify-content: center; flex: 0 0 18px; width: 18px; height: 24px; padding: 0;
    border: 0; border-radius: 4px; background: none; color: var(--faint); cursor: grab; user-select: none;
  }
  :is(.grip-h, x-cell.gutter .dh, .blk > .bh .bg, .vs-panel .vs-grip, .hdrprops .hp-row .grip, .tagpick .tp-row .grip, x-tzlist > .tzrow > .tz-grip) > svg { width: 14px; height: 14px; }
  :is(.grip-h, x-cell.gutter .dh, .blk > .bh .bg, .vs-panel .vs-grip, .hdrprops .hp-row .grip, .tagpick .tp-row .grip, x-tzlist > .tzrow > .tz-grip):hover { background: var(--hover); color: var(--muted); }
  :is(.grip-h, x-cell.gutter .dh, .blk > .bh .bg, .vs-panel .vs-grip, .hdrprops .hp-row .grip, .tagpick .tp-row .grip, x-tzlist > .tzrow > .tz-grip):active { cursor: grabbing; }
  /* in the grid it sits at the gutter's left edge, beside the checkbox, and shows on row hover */
  x-cell.gutter .dh { position: absolute; left: 1px; top: 50%; transform: translateY(-50%); opacity: 0; }
  x-row:hover .gutter .dh, x-cell.gutter .dh:focus-visible { opacity: 1; }
  x-grid:not([data-can-write]) .dh { display: none; }
  x-row[data-dragging] { opacity: .45; z-index: var(--z-drag); }
  x-row.grp .gh .ga { color: var(--faint); font-size: 11px; font-weight: 500; font-variant-numeric: tabular-nums; }
  x-row.grp .gh .gnew { opacity: 0; font-size: 12px; color: var(--muted); padding: 2px 6px; border-radius: 3px; }
  x-row.grp:hover .gh .gnew { opacity: 1; }
  x-row.grp .gh .gnew:hover { background: var(--hover); color: var(--fg); }
  /* conditional colouring (config.colors) — row scope tints the sticky cells too */
  x-row[data-rc], x-row[data-rc] x-cell.gutter, x-row[data-rc] x-cell.title,
  x-row[data-rc]:hover, x-row[data-rc]:hover x-cell.gutter, x-row[data-rc]:hover x-cell.title { background: var(--rc); }
  x-cell[data-rc] { background: var(--rc); }
  /* a pill keeps its shape on a tinted row: its own tint would melt into the row's */
  x-row[data-rc] .pill, x-cell[data-rc] .pill { background: color-mix(in srgb, currentColor 22%, var(--bg)); box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 35%, transparent); }
  [data-rc="c0"] { --rc: var(--pc0-bg); } [data-rc="c1"] { --rc: var(--pc1-bg); } [data-rc="c2"] { --rc: var(--pc2-bg); }
  [data-rc="c3"] { --rc: var(--pc3-bg); } [data-rc="c4"] { --rc: var(--pc4-bg); } [data-rc="c5"] { --rc: var(--pc5-bg); }
  [data-rc="c6"] { --rc: var(--pc6-bg); } [data-rc="c7"] { --rc: var(--pc7-bg); } [data-rc="c8"] { --rc: var(--pc8-bg); }

  /* ---------- C. columns: reorder, freeze, fields panel ---------- */
  x-hcell[data-movable] .hn { cursor: grab; }
  x-hcell[data-dragging] { opacity: .45; }
  x-hcell[data-drop]::before { content: ""; position: absolute; top: 0; bottom: 0; width: 2px; background: var(--accent); z-index: 5; }
  x-hcell[data-drop="l"]::before { left: -1px; }
  x-hcell[data-drop="r"]::before { right: -1px; }
  /* the Fields panel that used to live here is View settings > Property visibility now (.vs-frow) */

  /* ---------- D. newer field types ---------- */
  .rate { display: inline-flex; gap: 1px; }
  .rate i { font-style: normal; font-size: 13px; line-height: 1; color: var(--border-2); }
  .rate i.on { color: #e0a319; }
  x-cell[data-writable] .rate i { cursor: pointer; }
  x-cell[data-writable] .rate i.hv { color: #e0a319; opacity: .55; }
  .pbar { flex: 0 0 32px; height: 4px; margin-left: 6px; border-radius: 2px; background: var(--hover-2); position: relative; overflow: hidden; }
  .pbar::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: var(--p, 0%); background: var(--accent); }
  .anum { font: 12px/1 var(--mono); color: var(--faint); }
  x-cell .v.ro { color: var(--muted); }
  .v.files { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; color: var(--muted); }
  .v.files:hover { color: var(--accent); }
  x-cell[data-type="currency"], x-cell[data-type="percent"], x-cell[data-type="duration"], x-cell[data-type="autonumber"], x-cell[data-type="number"] { justify-content: flex-end; }
  x-cell[data-type="rating"] { justify-content: flex-start; }

  /* ---------- E. summary bar ---------- */
  /* sits on top of the pinned count bar, so the two read as one piece of bottom chrome */
  x-gsum { display: flex; position: sticky; bottom: var(--gfoot-h); z-index: var(--z-stickychrome); min-width: max-content; height: 32px; background: var(--bg); border-top: 1px solid var(--border-2); }
  x-scell {
    display: flex; align-items: center; justify-content: flex-end; height: 32px; padding: 0 4px; position: relative; overflow: hidden;
    flex: 0 0 var(--cell-w); width: var(--cell-w); border-right: 1px solid var(--border); background: var(--bg);
  }
  x-scell.gutter { flex: 0 0 var(--gutter-w); width: var(--gutter-w); position: sticky; left: 0; z-index: 2; }
  x-scell.title { flex: 0 0 var(--title-w); width: var(--title-w); position: sticky; left: var(--gutter-w); z-index: 2; box-shadow: var(--frz-shadow); }
  x-scell.status { flex: 0 0 var(--status-w); width: var(--status-w); }
  x-scell.filler { flex: 1 1 40px; width: auto; border-right: 0; }
  x-scell .sfn { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; height: 24px; padding: 0 6px; border-radius: 3px; font-size: 12px; color: var(--muted); }
  x-scell .sfn:hover { background: var(--hover); }
  x-scell .sfn .lbl { opacity: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--faint); transition: opacity var(--t); }
  x-scell .sfn[data-on] .lbl, x-gsum:hover .sfn .lbl { opacity: 1; }
  x-scell .sfn .val { color: var(--fg); font-weight: 500; font-variant-numeric: tabular-nums; }
  x-scell .sfn .val:empty { display: none; }

  /* ---------- F. polish: skeletons, empty state, search, bulk bar, wrap + hover expand ---------- */
  x-row.skel { pointer-events: none; }
  x-row.skel .sk { display: block; width: 62%; height: 8px; border-radius: 3px; background: linear-gradient(90deg, var(--hover) 25%, var(--hover-2) 37%, var(--hover) 63%); background-size: 400% 100%; animation: cbsk 1.3s ease-in-out infinite; }
  x-row.skel x-cell.title .sk { width: 78%; }
  @keyframes cbsk { from { background-position: 100% 0; } to { background-position: 0 0; } }
  /* the grid's empty state IS the shared one (.empty-state bare). It sits in the flow under the
     header, pinned to the grid's left edge: laid over the zero-height row area it was scrolled out
     of sight inside the grid */
  x-gempty { position: sticky; left: 0; width: min(100%, 560px); }
  x-gempty.empty-state { padding: var(--s-6) var(--s-4); }
  x-gempty span { max-width: 44ch; }
  .qbox { display: flex; align-items: center; gap: 4px; height: var(--ctl-h); padding: 0 6px; border-radius: var(--r-2); color: var(--muted); }
  .qbox:hover, .qbox:focus-within { background: var(--hover); }
  /* the input inside is deliberately chrome-less and clears its own ring, so without this the
     search-in-table box was the one toolbar control you could tab to with nothing to see */
  .qbox:focus-within { box-shadow: inset 0 0 0 1px var(--accent); }
  .qbox .qin { width: 140px; height: 22px; padding: 0 2px; border: 0; background: transparent; box-shadow: none; font-size: 13px; }
  /* in the view toolbar the search is an icon, as Notion's: the field opens on click or focus and
     stays open while it holds a term (data-open, set by the server for ?q= and by the grid search) */
  x-viewbar .qbox { cursor: pointer; }
  x-viewbar .qbox:not(:focus-within):not([data-open]) .qin { width: 0; padding: 0; opacity: 0; }
  x-viewbar .qbox:not(:focus-within):not([data-open]) .qn { display: none; }
  /* the box ships its own clear button, so hide the UA's search cancel widget and keep the
     input flat — the global field chrome skips .qbox inputs entirely (see fields.js) */
  .qbox .qin::-webkit-search-cancel-button, .qbox .qin::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
  .qbox .qin:focus, .qbox .qin:focus-visible { outline: 0; box-shadow: none; }
  .qbox x-field { display: contents; }
  .qbox .qn { font-size: 11px; color: var(--faint); white-space: nowrap; }
  .qbox .qx { display: inline-flex; align-items: center; color: var(--faint); }
  .qbox .qx:hover { color: var(--fg); }
  x-selbar .sb { display: inline-flex; align-items: center; gap: 5px; height: 28px; padding: 0 8px; border-radius: var(--r-1); font-size: 12px; color: inherit; }
  x-selbar .sb:hover { background: rgba(128,128,128,.28); }
  x-selbar .sb.danger { color: #ffb4b4; }
  /* the tag picker (tagpick.js): chips and a text box over the cell, then the options as pills */
  .popover.tagpick { padding: 0; width: max-content; max-width: min(420px, calc(100vw - 16px)); }
  .tagpick .tp-head { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; padding: 6px 8px; background: var(--bg-2); border-bottom: 1px solid var(--border); min-height: 34px; }
  .tagpick .tp-head .pill { display: inline-flex; align-items: center; gap: 4px; margin: 0; }
  .tagpick .tp-head .pill .x { display: inline-flex; cursor: pointer; opacity: .6; } .tagpick .tp-head .pill .x:hover { opacity: 1; }
  .tagpick .tp-head .pill .x svg { width: 12px; height: 12px; }
  .tagpick .tp-head input { flex: 1 1 60px; min-width: 60px; height: 22px; border: 0; background: transparent; box-shadow: none; padding: 0 2px; font-size: 13px; }
  .tagpick .tp-hint { padding: 6px 10px 2px; font-size: 12px; color: var(--faint); }
  .tagpick .tp-list { padding: 4px; max-height: 320px; overflow: auto; }
  .tagpick .tp-list .mh { padding: 8px 8px 4px; font-size: 12px; color: var(--faint); font-weight: 500; }
  .tagpick .tp-row { display: flex; align-items: center; gap: 6px; height: 30px; padding: 0 6px; border-radius: var(--r-1); cursor: pointer; }
  .tagpick .tp-row.hl, .tagpick .tp-row:hover { background: var(--hover); }
  .tagpick .tp-row .ck { margin-left: auto; display: inline-flex; color: var(--accent); }
  .tagpick .tp-row .more { margin-left: auto; display: none; width: 22px; height: 22px; border-radius: var(--r-1); color: var(--muted); align-items: center; justify-content: center; }
  .tagpick .tp-row .ck + .more, .tagpick .tp-row .more { margin-left: auto; }
  .tagpick .tp-row:hover .more { display: inline-flex; }
  .tagpick .tp-row .more:hover { background: var(--hover-2); color: var(--fg); }
  .tagpick .tp-row.create > span:first-child { color: var(--muted); font-size: 13px; }
  .tagpick .tp-empty { padding: 8px 10px; color: var(--faint); font-size: 13px; }
  /* a status pill carries a dot, as Notion's: in the picker and wherever a status property shows */
  .pill > i.st { display: inline-block; flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: currentColor; margin-right: 6px; opacity: .8; }
  /* Bulk selection outside the grid (bulk.js): the box sits over a record's status icon (a timeline's
     spine dot, a gantt row's dot, a card's corner when it has none), shown on hover and on every
     record while any is selected; a selected record is tinted as a grid row is, a card ringed */
  .rsel { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 1; display: none; }
  x-card > .rsel, x-gcard > .rsel { left: 8px; top: 8px; transform: none; }
  .gt-row > .dot { position: relative; }
  x-item:is(:hover, :focus-visible, [aria-selected]) .rsel, x-card:is(:hover, :focus-visible, [aria-selected]) .rsel,
  x-gcard:is(:hover, :focus-visible, [aria-selected]) .rsel, .tl-item:is(:hover, [aria-selected]) .rsel,
  x-titem > .trow:hover .rsel, x-titem[aria-selected] > .trow .rsel, .ditem:is(:hover, :focus-visible, [aria-selected]) .rsel,
  .gt-row:is(:hover, [aria-selected]) .rsel, [data-selecting] .rsel { display: block; }
  x-item[aria-selected], x-titem[aria-selected] > .trow, .ditem[aria-selected], .gt-row[aria-selected] { background: var(--selected); }
  x-card[aria-selected], x-gcard[aria-selected], .tl-item[aria-selected] > .tl-card { box-shadow: 0 0 0 2px var(--accent); }
  x-viewbar .tabs a .pv { display: inline-flex; opacity: .45; margin-left: 1px; }
  x-viewbar .tabs a[data-dragging] { opacity: .4; }
  .frow.wrap { flex-wrap: wrap; }
  /* long text edited in place (grid.js cbEditCell): a box over the cell that grows with its text */
  textarea.cell-long { min-height: 96px; max-height: 360px; resize: vertical; padding: 6px 8px; border: 0; border-radius: var(--r-2); box-shadow: var(--shadow), 0 0 0 2px var(--accent); background: var(--bg); color: var(--fg); font: inherit; font-size: 14px; line-height: 1.45; }
  x-record x-cell.editing > textarea.cell-long { width: 100%; box-shadow: 0 0 0 1px var(--border-2); }
  x-grid[data-rh="medium"] { --wrap-lines: 2; }
  x-grid[data-rh="tall"] { --wrap-lines: 4; }
  x-grid[data-wrap] x-cell { white-space: normal; }
  x-grid[data-wrap] x-cell > .v { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; white-space: normal; overflow: hidden; }
  x-grid[data-wrap][data-rh="medium"] x-cell > .v { -webkit-line-clamp: 2; }
  x-grid[data-wrap][data-rh="tall"] x-cell > .v { -webkit-line-clamp: 4; }
  /* Expand a truncated cell sideways so the whole value can be read (the row is contain:strict,
     so it stays on one line). The keyboard-focused cell expands too: reading a clipped value was
     one of the things only a mouse could do. */
  x-grid:not([data-wrap]) x-cell:is([data-type="text"]:not(.title), [data-type="markdown"], [data-type="url"], [data-type="email"], [data-type="phone"]):is(:hover, [data-focus]):not(.editing) {
    overflow: visible; z-index: var(--z-active);
  }
  x-grid:not([data-wrap]) x-cell:is([data-type="text"]:not(.title), [data-type="markdown"], [data-type="url"], [data-type="email"], [data-type="phone"]):is(:hover, [data-focus]):not(.editing) > .v {
    width: max-content; max-width: min(460px, 34vw); background: var(--bg); border-radius: 3px; box-shadow: 0 0 0 4px var(--bg), var(--shadow);
  }
  @media (max-width: 760px) {
    x-cell.gutter .dh { display: none; }
    .qbox .qin { width: 120px; }
    /* the toolbar is already horizontally scrollable; presence avatars are the first thing
       worth dropping, and the discussion drawer takes the full width */
    .who-stack { display: none; }
    x-drawer[side="right"] .drawer-panel { width: 100vw; }
    x-chat .ch-list { padding-bottom: 4px; }
  }
}

@layer components {
  /* The column menu (assets/js/fieldmenu.js). Every item in a ctx menu now carries an icon, so
     the sizing rule lives with the menu rather than with any one builder. */
  .popover.ctx .mi > svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--faint); }
  .popover.ctx .mi.danger > svg { color: var(--danger); }
  .popover.ctx.fieldmenu { min-width: 264px; }
  /* identity row: the property name is edited here, so there is no "Rename" item below */
  .fieldmenu .mprop { display: flex; align-items: center; gap: 8px; padding: 2px 4px 7px; margin-bottom: 3px; border-bottom: 1px solid var(--border); }
  .fieldmenu .mprop-t { width: 15px; height: 15px; flex: 0 0 auto; color: var(--faint); }
  .fieldmenu .mprop-n { flex: 1 1 auto; min-width: 0; height: 27px; padding: 0 7px; border: 1px solid transparent; border-radius: var(--r-1); background: var(--hover); font: inherit; color: var(--fg); }
  .fieldmenu .mprop-n:focus { background: var(--bg); border-color: var(--accent); outline: none; }
  .fieldmenu .mprop > .ellip { font-weight: 500; padding-left: 1px; }
  /* "current" beside the field's own type is a label, not a keyboard shortcut */
  .fieldmenu .mi .kbd { text-transform: none; letter-spacing: 0; }
}

/* ===================== pass 7: shell — current space, a rail you can reach the end of, tree chrome on hover ===================== */
@layer components {
  /* ---- the rail says which space you are in ----
     Nothing could set aria-current here: the space is named by the child template's body
     attribute, which is emitted before the rail and cannot be read back from it. So the pairing
     is enumerated the way the sidebar's own section switch already enumerates it (one line per
     space), which also means the marker survives with JS off. app.js adds aria-current on top,
     for the readers that need the word rather than the colour. */
  x-rail > a::before, x-rail > a[aria-current]::before {
    content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 3px;
    border-radius: 0 2px 2px 0; background: var(--accent); opacity: var(--cur, 0); pointer-events: none;
  }
  x-rail > a[aria-current],
  body:not([data-space]) x-rail > a[data-space="home"],
  body[data-space="home"] x-rail > a[data-space="home"],
  body[data-space="inbox"] x-rail > a[data-space="inbox"],
  body[data-space="my"] x-rail > a[data-space="my"],
  body[data-space="calendar"] x-rail > a[data-space="calendar"],
  body[data-space="projects"] x-rail > a[data-space="projects"],
  body[data-space="crm"] x-rail > a[data-space="crm"],
  body[data-space="knowledge"] x-rail > a[data-space="knowledge"],
  body[data-space="notes"] x-rail > a[data-space="notes"],
  body[data-space="databases"] x-rail > a[data-space="databases"],
  body[data-space="settings"] x-rail > a[data-space="settings"],
  body[data-space="admin"] x-rail > a[data-space="admin"] { --cur: 1; background: var(--selected); color: var(--accent); }

  /* ---- the rail can be scrolled to its last item ----
     `overflow: visible` meant a short window simply cut the bottom off: Settings, Admin and the
     workspace switcher had no way of being reached, and rail.js's own overflow chevrons could
     never appear because a visible box reports no scroll height to compare. The scrollbar stays
     hidden in the 52px column; the chevrons stick to the ends so they read as "more this way". */
  x-rail { overflow-y: auto; overflow-x: hidden; }
  /* rail.js marks the scroller .has-bar once labels are pinned: at 168px wide an ordinary
     scrollbar is what a reader expects and the chevrons stand down. It was written for a
     `.rail-scroll` wrapper that does not exist, so it landed on the rail and styled nothing. */
  x-rail.has-bar { scrollbar-width: thin; }
  x-rail.has-bar::-webkit-scrollbar { display: block; width: 6px; }
  x-rail .rail-scrollbtn { margin: 0 auto; z-index: var(--z-stickychrome); }
  x-rail .rail-scrollbtn.up { position: sticky; top: 0; }
  x-rail .rail-scrollbtn.down { position: sticky; bottom: 0; }

  /* ---- the workspace switcher is a rail item like the rest ----
     It sat in a 44px box while every glyph beside it is 36 high in a 40 wide one, so the bottom
     of the column stepped out of the line the whole rail otherwise keeps. */
  x-rail .ws { width: 40px; height: 36px; border-radius: var(--r-2); }
  x-rail .ws .ws-mark { width: 24px; height: 24px; font-size: 12px; line-height: 24px; }

  /* ---- the crumb you are standing on survives the squeeze ----
     Every crumb shrank at the same rate, so a deep trail in a narrow window ellipsised the page's
     own name alongside its ancestors. A trail may lose its middle; it may not lose its leaf. */
  x-topbar .crumbs > * { min-width: 2.5em; flex: 0 40 auto; }
  x-topbar .crumbs > .sep { min-width: 0; flex: 0 0 auto; }
  x-topbar .crumbs > :last-child { flex: 0 1 auto; }

  /* ---- the sidebar header sits on the topbar's line ----
     44px is this shell's chrome height everywhere else (topbar, drawer head, peek head); the
     sidebar's own header was the single strip at 48, so the two panes started 4px apart. */
  x-sidebar > section > header { height: 44px; }

  /* ---- create controls appear with the row, and with keyboard focus ----
     The section header's + and folder buttons were the last permanently visible chrome in the
     tree; every reference reveals them on hover. Anything hover-reveals must reveal on focus
     too, or tabbing lands on a control nobody can see - which was already true of the favourite
     star and both row menus. */
  x-sidebar .tree h6 .rowadd { opacity: 0; }
  x-sidebar .tree:hover h6 .rowadd,
  x-sidebar .tree h6 .rowadd:focus-visible,
  x-sidebar .tnode .star:focus-visible,
  x-sidebar .pnode > .rowmore:focus-visible,
  x-sidebar .fnode > .frow2 > .icon-btn:focus-visible { opacity: 1; }

  /* ---- one way for the tree to say "nothing here yet" ----
     Five inline-styled strings at three different paddings said it before, which is how one
     density becomes several. Where there is an action for it, the message offers it. */
  x-sidebar .tree .tnone { display: block; padding: 3px 8px 6px; font-size: 12px; color: var(--faint); }
  x-sidebar .tree .tnone > button { display: block; margin-top: 2px; padding: 0; font: inherit; font-weight: 500; color: var(--muted); }
  x-sidebar .tree .tnone > button:hover { color: var(--accent); }

  /* ---- "how records open here" is one control, so it is one shape ----
     A label glyph plus a disclosure chevron, in the topbar and in the peek header alike. */
  .modes [data-qv-menu] { width: auto; gap: 1px; padding: 0 4px; }
  .modes [data-qv-menu] svg[data-icon="chevron-down"] { width: 12px; height: 12px; color: var(--faint); }

  @media (max-width: 899px) {
    /* the rail is a bottom tab bar down here: it lays out across, not down */
    x-rail { overflow: visible; }
    x-rail > a::before { display: none; }
    x-rail .rail-scrollbtn { display: none; }
  }
}

/* ===================== pass 8: the view toolbar — one order, one badge, one open state ===================== */
@layer components {
  /* ---- nothing in the strip can be pushed past its own edge ----
     "+ New view" was clipped because it lived inside the scrolling tab strip. The tools had the
     same bug at the other end for a different reason: the cluster could not shrink, so between
     the mobile breakpoint and the width where every control fits, the strip pushed the page
     wider than the window instead of scrolling. The page tools and the view's configuration
     scroll; the primary create action and the view menu are pinned outside that scroller. */
  x-viewbar .tools:has(> .tscroll) { min-width: 0; flex: 0 1 auto; }
  x-viewbar .tscroll {
    display: flex; align-items: center; gap: 2px; min-width: 0;
    overflow-x: auto; scrollbar-width: none;
    /* the search box's focus ring is 4px of box-shadow, and overflow-x:auto also clips
       vertically — the padding gives it room, the negative margin gives the padding back */
    padding: 4px 0; margin: -4px 0;
  }
  x-viewbar .tscroll::-webkit-scrollbar { display: none; }
  x-viewbar .tend { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }
  /* the clusters ARE the separator: a hairline drawn between them by the boundary itself, so
     there is no rule to leave behind when a cluster turns out to be the first one present */
  x-viewbar .tgrp { display: inline-flex; align-items: center; gap: 2px; }
  x-viewbar .tgrp + .tgrp, x-viewbar .tend { margin-left: 6px; padding-left: 6px; border-left: 1px solid var(--border); }
  /* the presence stack overrides [hidden] with its own display, so an empty one still spent its
     margin and opened the page cluster with a gap before the first button */
  x-viewbar .who-stack[hidden] { display: none; }

  /* ---- a control that is doing something says so; a control whose panel is open says so ----
     `.on` recoloured 13px of label and nothing else; every grid this bar answers to tints the
     whole control. And nothing at all marked the open one, so with three near-identical buttons
     in a row you had to remember which you had clicked. */
  x-viewbar .tool.on, x-viewbar .tool.on:hover:not([disabled]) { background: var(--selected); color: var(--accent); }
  x-viewbar .tool[aria-expanded="true"], x-viewbar .tab-add[aria-expanded="true"] { background: var(--hover-2); color: var(--fg); }
  x-viewbar .tool.on[aria-expanded="true"] { background: var(--selected); color: var(--accent); }
  /* hover reveals these controls' meaning; the keyboard has to be able to see where it landed */
  x-viewbar .tool:focus-visible, x-viewbar .tab-add:focus-visible, x-viewbar .tabs a:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  /* the one primary action a bar may carry (the calendar's New event, attendance's stamp) was
     already marked `.primary` in the markup and styled nowhere, so it read as one more grey tool */
  x-viewbar .tool.primary, x-viewbar .tool.primary:hover:not([disabled]) { background: var(--accent); color: var(--accent-fg); }
  x-viewbar .tool.primary:hover:not([disabled]) { filter: brightness(.94); }

  /* ---- the panels are visibly one family ----
     The eyebrow had a rule only inside .popover.menu, so "Fields in this view" rendered as plain
     body text while "Row height" one panel over was a small-caps label, and the filter, sort and
     group panels — which are shared code — carried no heading at all. */
  .popover .mh { font-size: 11px; color: var(--faint); padding: 6px 8px 2px; text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
  /* the segment control carried the same inline margin in each panel that used one */
  .popover.menu > .segment { margin: 0 6px 4px; }

  @media (max-width: 899px) {
    /* the whole cluster scrolling would carry the pinned end away with it, which is the bug the
       inner scroller exists to stop; the bar without one keeps scrolling as a whole */
    x-viewbar .tools:has(> .tscroll) { overflow: visible; padding-bottom: 0; }
    x-viewbar .tscroll { flex: 1 1 auto; }
  }
}

/* ---- sidebar tree head: the create controls and the inline forms they open ----
   One macro (templates/macros/sidebar.html) draws every space's tree head, so these rules are the
   only shape a sidebar create form has. The name gets the whole first row; whatever qualifies it -
   the folder a project is filed in, the template a table starts from - shares the second row with
   Add and Cancel. A colour swatch on the name's row used to squeeze the name to a stub. */
@layer components {
  x-sidebar .treenew { display: grid; gap: 4px; padding: 4px 6px 6px; }
  x-sidebar .treenew > .nf-row { display: flex; align-items: center; gap: 4px; min-width: 0; }
  x-sidebar .treenew > .nf-row > x-select, x-sidebar .treenew > .nf-row > select { flex: 1 1 auto; width: auto; min-width: 0; }
  x-sidebar .treenew > .nf-row > .btn { margin-left: auto; flex: 0 0 auto; }
  /* the head's create buttons reveal on hover, and a touch screen has none: the footer they
     replace was always visible there, so they stay visible where nothing can hover */
  @media (hover: none) { x-sidebar .tree h6 .rowadd { opacity: 1; } }

  /* ---- a layer opened from the sidebar paints above the rail ----
     x-sidebar carried a z-index, and a flex item with a z-index is a stacking context: everything
     inside it painted at the sidebar's level (35), under the rail (36), whatever z-index a popover
     inside it had. placeFloat clamps a panel wider than the sidebar to 8px from the window edge -
     on top of the rail - so the rail covered the panel's left edge: the "New table" popover that
     kept floating half off-screen. Its box measured fully inside the window, so cbContain had
     nothing to correct. On a desktop the sidebar is a column beside main and needs no layer of its
     own; below 900px it is a drawer over the page and keeps one. */
  @media (min-width: 900px) { x-sidebar { z-index: auto; } }
}

/* ---- "Open pages in": the one chooser for how a record opens (assets/js/openmode.js) ----
   x-openmode is the radiogroup of illustrated tiles, used inline (Settings > Appearance, view
   settings) and inside .openmode-pop (top bar, peek header, settings overlay, record menus). The
   drawings paint themselves with tokens; this only frames the tiles and marks the current one. */
@layer components {
  x-openmode { display: flex; flex-wrap: wrap; gap: 8px; }
  x-openmode > button { flex: 1 1 70px; max-width: 104px; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 4px 2px; border-radius: var(--r-2); color: var(--muted); font-size: 12px; line-height: 1.2; text-align: center; }
  x-openmode > button > svg { display: block; width: 100%; height: auto; aspect-ratio: 64 / 44; border-radius: 6px; transition: box-shadow var(--t); }
  x-openmode > button:hover { color: var(--fg); --om-frame: var(--faint); }
  x-openmode > button[aria-checked="true"] { color: var(--fg); font-weight: 500; --om-edge: var(--accent); --om-frame: transparent; }
  x-openmode > button[aria-checked="true"] > svg { box-shadow: 0 0 0 2px var(--accent); }
  x-openmode > button:focus-visible { outline: none; }
  x-openmode > button:focus-visible > svg { box-shadow: 0 0 0 2px var(--accent), 0 0 0 5px var(--ring); }
  .popover.openmode-pop { min-width: 0; width: min(420px, calc(100vw - 16px)); padding: 10px 10px 8px; }
  .popover.openmode-pop > .mh { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; padding: 0 2px 10px; }
  .popover.openmode-pop > .mh > .om-for { text-transform: none; letter-spacing: 0; font-weight: 500; font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .popover.openmode-pop > .om-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 8px; padding: 6px 2px 0; border-top: 1px solid var(--border); font-size: 12px; color: var(--muted); min-height: 32px; }
  .pref-row.stacked { flex-direction: column; align-items: stretch; }
  .pref-row.stacked > [data-openmode-picker] { min-height: 86px; }

  /* the trigger's glyph: a window with the record shaded where the current choice opens it. The box
     comes from the one option list (app.js qvGlyph), so nothing here names a choice. */
  svg[data-icon="openmode"] > .om { fill: currentColor; fill-opacity: .4; stroke: none; }

  /* the settings overlay docked to an edge when its context is set to a side peek */
  dialog.settings-modal[data-dock] { margin: 0; height: 100%; max-height: none; }
  dialog.settings-modal[data-dock="right"] { margin-left: auto; }
  dialog.settings-modal[data-dock="left"] { margin-right: auto; }
  dialog.settings-modal[data-dock] > .mbox { border-radius: 0; }
}

@layer components {
  /* ---- Activity: one feed for every surface ------------------------------------------------
     The Activity page, a project's and a table's Activity tab, a person's profile and the record
     panel all render x-activity-feed from routes/activity.rs; the filter bar and the week summary
     are x-activity-panel. Entries read as sentences (Notion's updates, Asana's project activity):
     actor, verb, the object as a link, then the before -> after of what changed. */
  x-activity-panel, x-activity-feed { display: block; }
  x-activity-panel > .tabs-ui { margin-top: 0; }

  x-activity-panel > form {
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
    padding: 4px 0 10px; margin-bottom: 2px; border-bottom: 1px solid var(--border);
  }
  /* on the Activity page the filter bar stays in view (under the 44px top bar) while the feed scrolls */
  x-page.mid > x-activity-panel > form { position: sticky; top: 44px; z-index: 3; background: var(--bg); padding-top: 8px; }
  x-activity-panel > form > x-select { width: auto; min-width: 132px; max-width: 220px; }
  x-activity-panel > form > label { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
  x-activity-panel > form > label > x-datepicker { min-width: 112px; }
  x-activity-panel > form > label > input[type=date] { width: auto; }
  x-activity-panel > form > .af-sp { flex: 1; }
  /* the form submits itself on change once scripting runs (form[data-autosave]); Apply is the
     no-JS path and would only be a second way to do the same thing */
  html[data-js] x-activity-panel > form > .af-apply { display: none; }

  x-activity-panel > .act-week { margin: 0 0 12px; }
  x-activity-panel > .act-week > h6.sec { margin-top: 4px; }
  x-activity-panel > .act-week > .act-tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
  x-activity-panel > .act-week > .act-tiles > .act-tile {
    display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; min-width: 0;
    border: 1px solid var(--border); border-radius: var(--r-2); color: inherit; transition: background var(--t);
  }
  x-activity-panel > .act-week > .act-tiles > a.act-tile:hover { background: var(--hover); }
  x-activity-panel > .act-week > .act-tiles > a.act-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
  x-activity-panel > .act-week > .act-tiles > .act-tile > b { font-size: 20px; font-weight: 600; line-height: 1.2; font-variant-numeric: tabular-nums; }
  x-activity-panel > .act-week > .act-tiles > .act-tile > span { font-size: 12px; color: var(--muted); }
  x-activity-panel > .act-week > .act-tiles > .act-tile.warn > b { color: var(--danger); }
  x-activity-panel > .act-week > .act-people { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; font-size: 12px; }
  x-activity-panel > .act-week > .act-people > .chip { height: 22px; color: var(--fg); }
  x-activity-panel > .act-week > .act-people > .chip > .avatar { margin-right: 2px; }
  x-activity-panel > .act-week > .act-people > .chip > b { margin-left: 2px; color: var(--muted); font-weight: 600; font-variant-numeric: tabular-nums; }

  x-activity-feed > h3 { margin: 14px 0 2px; padding: 0 4px; font-size: 12px; font-weight: 600; color: var(--muted); }
  x-activity-feed > h3:first-child { margin-top: 6px; }
  x-activity-feed > ol { list-style: none; margin: 0; padding: 0; }
  x-activity-feed > ol > li { display: flex; align-items: flex-start; gap: 10px; padding: 7px 4px; border-radius: var(--r-2); }
  x-activity-feed > ol > li:hover { background: var(--hover); }
  x-activity-feed > ol > li > .avatar { margin: 0; flex: 0 0 auto; }
  x-activity-feed > ol > li > .act-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
  x-activity-feed > ol > li > .act-at { flex: 0 0 auto; padding-top: 1px; font-size: 12px; color: var(--faint); font-variant-numeric: tabular-nums; }
  x-activity-feed > ol > li > .act-body > p { margin: 0; }
  x-activity-feed > ol > li > .act-body > .act-line { font-size: 13px; line-height: 20px; color: var(--muted); overflow-wrap: anywhere; }
  x-activity-feed > ol > li > .act-body > .act-line > a,
  x-activity-feed > ol > li > .act-body > .act-line > b { color: var(--fg); font-weight: 500; }
  x-activity-feed > ol > li > .act-body > .act-line > a:hover { text-decoration: underline; text-decoration-color: var(--border-2); }
  x-activity-feed > ol > li > .act-body > .act-line > .gone { text-decoration: line-through; text-decoration-color: var(--faint); }
  x-activity-feed > ol > li > .act-body > .act-line > .pill { vertical-align: 1px; }
  x-activity-feed > ol > li > .act-body > .act-change { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-size: 13px; line-height: 20px; }
  x-activity-feed > ol > li > .act-body > .act-change > .act-v { font-weight: 400; color: var(--fg); overflow-wrap: anywhere; }
  /* the old value reads as the past: struck and quieter, while a pill keeps its colour legible */
  x-activity-feed > ol > li > .act-body > .act-change > :first-child { opacity: .7; }
  x-activity-feed > ol > li > .act-body > .act-change > .act-v:first-child { text-decoration: line-through; text-decoration-color: var(--faint); }
  x-activity-feed > ol > li > .act-body > .act-change > .act-empty,
  x-activity-feed > ol > li > .act-body > .act-line > .act-empty { color: var(--faint); font-style: italic; }
  x-activity-feed > ol > li > .act-body > .act-quote {
    margin: 0; padding: 2px 0 2px 10px; border-left: 2px solid var(--border-2);
    font-size: 13px; line-height: 20px; color: var(--fg); white-space: pre-wrap; overflow-wrap: anywhere;
  }
  x-activity-feed > ol > li > .act-body > .act-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; font-size: 12px; }
  x-activity-feed > ol > li > .act-body > .act-meta > a.chip:hover { color: var(--fg); background: var(--hover-2); }
  x-activity-feed > ol > li[data-kind="deleted"] > .avatar { background: var(--danger-bg, var(--hover)); color: var(--danger); }
  x-activity-feed > .act-more { margin: 8px 4px 4px; }
  x-activity-feed > .empty-state { margin-top: 8px; }

  /* inside the record panel the feed sits under the Versions list at the panel's own density */
  x-activity > x-activity-feed > ol > li { padding: 6px 2px; }

  @media (max-width: 640px) {
    x-activity-panel > .act-week > .act-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    x-activity-panel > form > x-select { max-width: none; flex: 1 1 140px; }
    x-activity-panel > form > .af-sp { display: none; }
  }
}

/* ---- View settings (assets/js/viewsettings.js) ----
   One floating panel for everything a database view is. Its items ARE the column menu's items
   (.popover.ctx .mi: height, icon size, hover, focus ring), so the two menus read as one system;
   what is added here is only what a menu has no use for - the drill-in header, a muted value
   before the chevron, a switch, the name row, the layout tiles, property rows and notes. The
   Filter / Sort / Group editors inside it keep their own .vb-* rules. */
@layer components {
  .popover.vs-panel { min-width: 0; padding: 0 0 4px; }
  .vs-panel > .vs-head { display: flex; align-items: center; gap: 4px; min-height: 42px; padding: 6px 8px 4px 12px; }
  .vs-panel:not([data-page="root"]) > .vs-head { padding-left: 6px; }
  .vs-panel .vs-title { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 600; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .vs-panel .vs-back, .vs-panel .vs-x { flex: 0 0 auto; }
  .vs-panel .vs-x { border-radius: 50%; background: var(--hover); }
  .vs-panel .vs-x:hover { background: var(--hover-2); color: var(--fg); }
  .vs-panel .vs-back > svg, .vs-panel .vs-x > svg { width: 14px; height: 14px; }
  .vs-panel > .vs-body { padding: 0 4px; overflow-y: auto; }
  .vs-panel > .vs-body > hr { margin: 4px; }
  .vs-panel .mh { padding: 8px 8px 4px; }
  .vs-panel .vs-list { display: flex; flex-direction: column; }
  .vs-panel .mi > .vs-l { flex: 0 1 auto; min-width: 0; }
  .vs-panel .mi > .vs-v { margin-left: auto; padding-left: 12px; max-width: 55%; color: var(--faint); font-size: 12px; text-align: right; }
  .vs-panel .mi > .vs-v + .arr { margin-left: 6px; }
  .vs-panel .mi > .switch { margin-left: auto; width: 28px; height: 16px; }
  .vs-panel .mi > .switch::after { width: 12px; height: 12px; }
  .vs-panel .mi[aria-checked="true"] > .switch { background: var(--accent); }
  .vs-panel .mi[aria-checked="true"] > .switch::after { transform: translateX(12px); }
  .vs-panel .mi[aria-disabled="true"], .popover.ctx .mi[aria-disabled="true"] { opacity: .5; cursor: default; }
  .vs-panel .mi[aria-disabled="true"]:hover, .popover.ctx .mi[aria-disabled="true"]:hover { background: transparent; }

  /* identity: the layout glyph, then the name edited in place (the column menu's .mprop-n) */
  .vs-panel .vs-id { display: flex; align-items: center; gap: 6px; padding: 0 4px 6px; }
  .vs-panel .vs-type { flex: 0 0 auto; width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-1); box-shadow: inset 0 0 0 1px var(--border); color: var(--muted); }
  .vs-panel .vs-type:hover { background: var(--hover); color: var(--fg); }
  .vs-panel .vs-type:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  .vs-panel .vs-namebox { position: relative; flex: 1 1 auto; min-width: 0; display: flex; }
  .vs-panel .vs-name { flex: 1 1 auto; min-width: 0; height: 28px; padding: 0 26px 0 7px; border: 1px solid transparent; border-radius: var(--r-1); background: var(--hover); font: inherit; color: var(--fg); }
  .vs-panel .vs-name:focus { background: var(--bg); border-color: var(--accent); outline: none; }
  .vs-panel .vs-name[readonly] { color: var(--muted); }
  .vs-panel .vs-info { position: absolute; right: 7px; top: 50%; transform: translateY(-50%); display: inline-flex; color: var(--faint); }
  .vs-panel .vs-info > svg { width: 14px; height: 14px; }
  .vs-panel .vs-lock { flex: 0 0 auto; display: inline-flex; color: var(--muted); }
  .vs-panel .vs-lock > svg { width: 15px; height: 15px; }

  /* Layout: the catalogue as tiles, then that layout's own options */
  .vs-panel .vs-types { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; padding: 2px 4px 4px; }
  .vs-panel .vs-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px; min-width: 0; height: 58px; padding: 6px 4px; border-radius: var(--r-2); box-shadow: inset 0 0 0 1px var(--border); color: var(--muted); font-size: 12px; }
  .vs-panel .vs-tile > svg { width: 18px; height: 18px; }
  .vs-panel .vs-tile > span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .vs-panel .vs-tile:hover { background: var(--hover); color: var(--fg); }
  .vs-panel .vs-tile[aria-checked="true"] { box-shadow: inset 0 0 0 2px var(--accent); color: var(--fg); font-weight: 500; }
  .vs-panel .vs-tile[aria-disabled="true"]:not([aria-checked="true"]) { opacity: .5; cursor: default; }
  .vs-panel .vs-tile[aria-disabled="true"]:hover { background: transparent; }
  .vs-panel .vs-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
  .vs-panel .vs-opts > .segment { margin: 0 4px 6px; }
  .vs-panel .vs-om { padding: 2px 4px 6px; }
  .vs-panel .vs-hint { margin: 0; padding: 0 8px 6px; color: var(--faint); font-size: 12px; }
  .vs-panel .vs-field { display: flex; align-items: center; gap: 8px; min-height: 32px; padding: 0 4px; font-size: 13px; }
  .vs-panel .vs-field > span { flex: 0 0 84px; color: var(--muted); font-size: 12px; }
  .vs-panel .vs-field > x-select, .vs-panel .vs-field > select { flex: 1 1 auto; min-width: 0; }
  .vs-panel .vs-fs { min-width: 0; margin: 0; padding: 0; border: 0; }
  .vs-panel .vs-opts .vb-foot, .vs-panel .vs-body > .vb-body, .vs-panel .vs-fs > .vb-body { margin: 0 4px; }
  .vs-panel .vs-body > .vb-body, .vs-panel .vs-fs > .vb-body { padding-bottom: 4px; }

  /* property rows: Property visibility and Edit properties draw the same row */
  .vs-panel .vs-q { display: block; width: calc(100% - 8px); height: 28px; margin: 0 4px 4px; }
  .vs-panel .vs-sec { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-right: 4px; }
  .vs-panel .vs-sec > .ghost.xs { margin: 4px 0 0; align-self: center; height: 22px; }
  .vs-panel .vs-flist { display: flex; flex-direction: column; }
  .vs-panel .vs-frow { display: flex; align-items: center; gap: 6px; height: var(--menu-item-h); padding: 0 2px; border-radius: var(--r-1); font-size: 13px; color: var(--fg); }
  .vs-panel .vs-frow:hover { background: var(--hover); }
  .vs-panel .vs-frow[data-dragging] { background: var(--selected); }
  .vs-panel .vs-frow > .vs-ft { width: 15px; height: 15px; flex: 0 0 auto; color: var(--faint); }
  .vs-panel .vs-frow > .vs-fn { flex: 1 1 auto; min-width: 0; }
  .vs-panel .vs-grip-sp { flex: 0 0 18px; width: 18px; height: 24px; }   /* the room a handle takes, where there is none */
  .vs-panel .vs-grip { opacity: 0; }
  .vs-panel .vs-frow:hover > .vs-grip, .vs-panel .vs-grip:focus-visible { opacity: 1; }
  .vs-panel .vs-grip[aria-disabled="true"] { cursor: default; }
  .vs-panel .vs-eye, .vs-panel .vs-more { color: var(--faint); }
  .vs-panel .vs-eye[aria-pressed="true"] { color: var(--muted); }
  .vs-panel .vs-eye:hover:not([aria-disabled="true"]), .vs-panel .vs-more:hover { color: var(--fg); background: var(--hover-2); }
  .vs-panel .vs-eye[aria-disabled="true"] { opacity: .45; cursor: default; }
  .vs-panel .vs-eye > svg, .vs-panel .vs-more > svg { width: 14px; height: 14px; }
  .vs-panel .vs-grip:focus-visible, .vs-panel .vs-eye:focus-visible, .vs-panel .vs-more:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
  .vs-panel .vs-fname { flex: 1 1 auto; min-width: 0; height: 24px; padding: 0 6px; border: 1px solid transparent; border-radius: var(--r-1); background: transparent; font: inherit; color: var(--fg); }
  .vs-panel .vs-fname:hover:not([readonly]) { background: var(--hover); }
  .vs-panel .vs-fname:focus { background: var(--bg); border-color: var(--accent); outline: none; }
  .vs-panel .vs-newfield { padding: 0 4px 6px; }

  /* a page's note: why its controls are off, or that what it shows is this reader's alone */
  .vs-panel .vs-note { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 6px 8px; margin: 0 4px 8px; padding: 7px 8px; border-radius: var(--r-2); background: var(--hover); color: var(--muted); font-size: 12px; line-height: 1.4; }
  .vs-panel .vs-note > svg { flex: 0 0 auto; width: 14px; height: 14px; margin-top: 1px; }
  .vs-panel .vs-note > span { flex: 1 1 160px; min-width: 0; }
  .vs-panel .vs-note > .ghost.xs { margin: 0; height: 22px; align-self: center; }

  /* the bar: a locked database's badge by the view name */
  x-viewbar .tabs a .lk { display: inline-flex; margin-left: 2px; color: var(--muted); }
  x-viewbar .tabs a .lk > svg { width: 12px; height: 12px; }
  x-hcell.addcol .icon-btn[aria-disabled="true"] { color: var(--faint); cursor: default; }
}

/* ---- secret fields: an API key or token typed outside a credential form ----
   Browsers offer saved logins on every type=password field and ignore autocomplete="off" there,
   so a secret that is not this account's own password is a text input carrying data-secret,
   masked here. app.js (noFill) turns a stray password field into one; fields.js adds the eye,
   which sets data-shown. Supported by Chrome, Safari and Firefox 114+. The placeholder stays
   readable: the property inherits, and a hint drawn as dots says nothing. */
@layer components {
  input[data-secret]:not([data-shown]) { -webkit-text-security: disc; }
  input[data-secret]::placeholder { -webkit-text-security: none; }
}

/* ---- project Members list (macros/members.html): a person's name opens their profile and
   activity; the empty-state line reads as a note, not a member row ---- */
@layer components {
  x-project .mlist li > span.ellip > a, x-drawer .mlist li > span.ellip > a { color: inherit; border-radius: var(--r-1); }
  x-project .mlist li > span.ellip > a:hover, x-drawer .mlist li > span.ellip > a:hover { text-decoration: underline; text-underline-offset: 2px; }
  x-project .mlist li > span.ellip > a:focus-visible, x-drawer .mlist li > span.ellip > a:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
  x-project .mlist li.muted, x-project .mlist li.faint, x-drawer .mlist li.muted, x-drawer .mlist li.faint { height: auto; font-size: 12px; }
}

/* ---- Lock database on the table settings page (table_settings.html): the field controls stay
   where they are, drawn off, and their tip says the database is locked ---- */
@layer components {
  x-settings .btn[aria-disabled="true"] { opacity: .55; cursor: default; }
  x-settings .btn[aria-disabled="true"]:hover { background: var(--bg); }
  x-settings .icon-btn[aria-disabled="true"] { color: var(--faint); cursor: default; }
  x-settings .icon-btn[aria-disabled="true"]:hover { background: transparent; }
  x-settings section > .note { margin-bottom: 12px; }
}

@layer components {
  /* date filter values: preset + calendar date, "between" pairs, and "relative to today" */
  .vb-rule > .vb-date, .vb-rule > .vb-rel { display: flex; align-items: center; gap: 6px; flex: 1 1 200px; min-width: 0; }
  .vb-date > input { flex: 1 1 120px; min-width: 110px; }
  .vb-rel > .vb-num { flex: 0 0 64px; width: 64px; }
  .vb-and { color: var(--faint); font-size: 12px; }
}

/* ---- Chart axis labels (view_chart.html, views.js): HTML over the canvas, one slot per bar, so a
   long category ends in an ellipsis and its full name is a tip ---- */
@layer components {
  x-chart { position: relative; }
  x-chart > .axis { position: absolute; left: 0; top: 0; width: 100%; height: 0; }
  x-chart > .axis > span { position: absolute; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: center; font-size: 12px; line-height: 16px; }
}

/* ---- Graph page (graph.html): the graph dialog's canvas, in the page instead of over it,
   filling what the top bar and the page's bottom padding leave ---- */
@layer components {
  x-graph[data-page] { position: static; z-index: auto; display: flex; height: calc(100vh - 92px); height: calc(100dvh - 92px); border-top: 1px solid var(--border); }
  x-graph[data-page] .gpanel { width: 100%; height: 100%; border-radius: 0; box-shadow: none; }
}

/* ---- Home (home.html): one centred grid. My work | Upcoming split the width in two, and the
   Spaces and Recently updated cards run on six columns with the same gap, so the halves' edges
   land on card edges and every section shares the page's left and right edge. Columns follow the
   page's own width (a container query), so an open or closed sidebar is accounted for. ---- */
@layer components {
  x-page.home { --home-gap: 16px; max-width: calc(1600px + var(--gx) * 2); container-type: inline-size; }
  x-page.home .home-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--home-gap); align-items: stretch; }
  x-page.home .home-grid > .card { display: flex; flex-direction: column; min-width: 0; }
  x-page.home .home-grid > .card > .empty-state { flex: 1; }
  x-page.home .spacegrid, x-page.home .home-recent { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--home-gap); }
  x-page.home .spacegrid > .scard, x-page.home .home-recent > x-recent { width: auto; min-width: 0; }
  @container (max-width: 899px) {
    x-page.home .home-grid { grid-template-columns: minmax(0, 1fr); }
    x-page.home .spacegrid, x-page.home .home-recent { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }
  @container (max-width: 519px) {
    x-page.home .spacegrid, x-page.home .home-recent { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
}

/* ---- Search filters (search.html): space, table and updated-day range under the search box, the
   same controls as the Activity filter bar ---- */
@layer components {
  .search-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: -8px 0 8px; }
  .search-filters > x-select { width: auto; min-width: 132px; max-width: 240px; }
  .search-filters > label { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
  .search-filters > label > x-datepicker { min-width: 112px; }
  .search-filters > label > input[type=date] { width: auto; }
  /* the form submits itself on change once scripting runs; Apply is the no-JS path */
  html[data-js] .search-filters > .sf-apply { display: none; }
  @media (max-width: 640px) { .search-filters > x-select { max-width: none; flex: 1 1 140px; } }
}

/* ---- Settings page (settings.html): one content column. Fields fill it, so each form's Save
   button (its right-aligned cluster) ends on the same edge as the fields it saves. In the settings
   overlay the root sits outside x-page, so only the field widths apply there. ---- */
@layer components {
  x-page > #settings-root { max-width: 720px; }
  #settings-root x-settings .stack > label { max-width: none; }
  #settings-root x-settings [role="group"] > h6.sec:first-child { margin-top: 0; }
}

/* ---- View toolbar (fragments/viewbar.html): tabs, "+ New view" and the tools on ONE row. What
   does not fit folds into the "N more" tab menu or the "⋯" tool menu (viewbar.js marks it
   data-ovf). The calendar's range switch and zone chips wrap below its nav instead of sliding
   under the grid, which a fixed 48px nav height let them do. ---- */
@layer components {
  /* "+ New view" follows the last tab; the tools keep the far end (margin-left:auto) */
  x-viewbar .tabs { flex: 0 1 auto; }
  x-viewbar [data-ovf] { display: none !important; }
  .cal-nav { height: auto; min-height: 48px; row-gap: 4px; }
  .cal-nav .cluster { flex-wrap: wrap; }
}

/* ---- Projects tree: project rows (layout.html pnode). A project row carries the same icon slot
   a folder row does and starts it where a folder's icon starts (the folder's 2px + 18px chevron,
   then its link's 4px), so a project's name lines up with a folder's name at every depth - at the
   root and inside a folder alike. ---- */
@layer components {
  x-sidebar .pnode > a.prow { padding-left: 24px; gap: 6px; }
}

/* ---- Admin > Danger: workspace content cards (admin.html). "Demo content" says whether the demo
   loader's content is present and offers load or remove; "Clear workspace content" sits above
   "Delete workspace". A running action marks its form aria-busy and its button carries the
   progress text (settings-modal.js). ---- */
@layer components {
  #admin-root [data-panel="danger"] > .card + .card { margin-top: 8px; }
  #admin-root .content-card > header { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
  #admin-root .content-card > header > h3 { margin: 0; }
  #admin-root .content-card > p { margin: 0; }
  #admin-root .content-card > form { margin-top: 10px; }
  #admin-root .content-card > form[aria-busy="true"],
  #admin-root .content-card > form[aria-busy="true"] .btn { cursor: progress; }
}
/* ---- Sidebar page tree (pagetree.js): in Knowledge and Notes a table row expands to its pages
   and a page to its sub-pages. As in Notion the chevron takes the row icon's place on hover (on a
   touch screen, always) and turns when open; a page dragged onto another outlines its new parent. ---- */
@layer components {
  x-sidebar .ptx { position: absolute; left: 6px; top: 50%; transform: translateY(-50%); width: 22px; height: 22px; opacity: 0; pointer-events: none; color: var(--muted); }
  x-sidebar .tnode:hover > .ptx, x-sidebar .pgnode:hover > .ptx, x-sidebar .ptx:focus-visible { opacity: 1; pointer-events: auto; }
  x-sidebar .tnode:hover:has(> .ptx) > a > :first-child, x-sidebar .pgnode:hover:has(> .ptx) > a > :first-child,
  x-sidebar .tnode:has(> .ptx:focus-visible) > a > :first-child, x-sidebar .pgnode:has(> .ptx:focus-visible) > a > :first-child { visibility: hidden; }
  x-sidebar .ptx svg { transition: transform var(--t); }
  x-sidebar .ptx[aria-expanded="true"] svg { transform: rotate(90deg); }
  x-sidebar .pgnode { position: relative; }
  x-sidebar .pgnode > a { position: relative; }
  x-sidebar .pgnode.dragging { opacity: .4; }
  x-sidebar .pgnode.dropping > a { background: var(--hover); box-shadow: inset 0 0 0 1.5px var(--accent); }
  @media (hover: none) {
    x-sidebar .ptx { opacity: 1; pointer-events: auto; }
    x-sidebar .tnode:has(> .ptx) > a > :first-child, x-sidebar .pgnode:has(> .ptx) > a > :first-child { visibility: hidden; }
  }
}
