| /* Sidebar — SideNav shell, session rows, footer update chip. |
| * Session rows are Astryx SideNavItem; this file only owns product-only chrome. */ |
| .maka-session-panel { |
| min-width: 0; |
| min-height: 0; |
| height: 100%; |
| } |
| |
| /* |
| * Astryx 0.2.0 ResizeHandle: when pillPlacement is not "center", hitAreaOffsetX |
| * applies translateY(-50%) without a matching top: 50%. The grab zone then only |
| * covers the top half of the handle, so a pointer drag at the vertical center |
| * (where the pill sits) hits the handle root — which has no pointerdown — and |
| * no-ops. SideNav uses pillPlacement="end" (sub-pixel X bias) and mounts the |
| * handle as a sibling of <nav.maka-session-panel>, not a descendant — target the |
| * handle test id. Remove once Astryx fixes hitAreaOffsetX. |
| */ |
| [data-testid="astryx-sidenav-resize-handle"] > div:not(.astryx-resize-handle-pill) { |
| /* !important: Astryx StyleX injects the bad transform unlayered, which |
| otherwise beats every rule in @layer maka.legacy. */ |
| transform: none !important; |
| } |
| |
| .maka-session-list { |
| min-width: 0; |
| max-width: 100%; |
| width: 100%; |
| box-sizing: border-box; |
| } |
| |
| /* |
| * One type size for the whole rail. SideNavSection draws its title from the |
| * `supporting` tier (12px), one step below the session rows it labels; against |
| * Maka's 14px body that reads as a caption rather than a peer of the list, and |
| * CJK loses more apparent size at 12px than Latin does. Put 会话 / 最近 / 置顶 |
| * on the rows' 14px and let weight and color carry the hierarchy instead — the |
| * title is already semibold against the rows' medium, and secondary against |
| * their primary foreground. |
| * |
| * Rebinding Astryx's own tier variables, rather than pinning font-size on the |
| * title span: the size still flows through Astryx's rule, so title and subtitle |
| * stay in step and an upgrade that restructures the header keeps working. |
| * |
| * Bound on the header, NOT on the section root. SideNavSection wraps the whole |
| * list body — every row, badge, and pill — in the same element as its title |
| * (session-history-list.tsx), and custom properties inherit, so a rebind on the |
| * root reaches all of it: measured live, the project session-count Badge went |
| * 12px → 14px, and `.maka-list-row-stale-pill` would have taken a 17.14px line |
| * box on its 12px font. The header is SideNavSection's first child and holds |
| * exactly the title and subtitle. |
| * |
| * Both halves of the tier move together. Size alone would leave the supporting |
| * leading multiplier on a larger font and land the line box at 23.33px, off the |
| * theme's 4px grid. |
| */ |
| .maka-session-panel .astryx-side-nav-section > :first-child { |
| --text-supporting-size: var(--text-label-size); |
| --text-supporting-leading: var(--text-label-leading); |
| } |
| |
| .maka-session-group { |
| min-width: 0; |
| } |
| |
| /* |
| * The rail's two hairlines: nav chrome above the history, footer below it. Both |
| * are drawn the same way, on the sticky shell that owns the zone rather than as |
| * an element inside it, so they are the same 1px at the same alpha and both run |
| * the full panel width. One custom property carries the line so "the same" is a |
| * fact about the code rather than something a test has to keep checking; the |
| * collapsed state then hides both by retuning that one value. |
| * |
| * Astryx 0.2.0 has no seam for this — SideNav's five zone wrappers carry no |
| * border and no `hasDivider`, and they are the only elements in its tree that |
| * `themeProps()` never labels, so the product both draws the line and reaches |
| * the zone by structure. |
| * |
| * The top one used to be an Astryx <Divider> placed as the last child of |
| * `topContent`, which made it a different line in every respect: --color-border |
| * is twice the alpha of the footer's rule, and the divider sat inside the |
| * sticky shell's 8px inline padding, so it stopped 8px short at each end |
| * (measured x=8 w=244 against the footer's x=0 w=260). Read together, one was a |
| * separator and the other a box edge. Drawing it as this zone's border-bottom |
| * also drops an element and a component from the tree, and the sticky padding |
| * that the footer rule already relies on becomes the breathing room the divider |
| * needed a margin for. |
| * |
| * The footer half additionally equalizes padding: Astryx defaults are |
| * asymmetric (spacing-1 top / spacing-2 bottom) and the section adds another |
| * paddingBlock, so Settings sat tight under the line and airy above the window |
| * edge. |
| */ |
| .maka-session-panel { |
| --maka-rail-hairline: oklch(from var(--foreground) l c h / 0.05); |
| } |
| |
| /* Continuous Collapse: the hairlines separate the history column from the |
| * chrome above and the footer below. At 48px there is no column left to |
| * separate — they read as orphan rules floating on a rail that is otherwise |
| * ink-only. Retuning the shared value rather than nulling each border keeps the |
| * two lines a single decision in the collapsed state too. */ |
| .appFrame[data-sidebar-state="collapsed"] .maka-session-panel { |
| --maka-rail-hairline: transparent; |
| } |
| |
| .astryx-side-nav.maka-session-panel > div:has(.maka-session-panel-top) { |
| border-bottom: var(--border-width-hairline) solid var(--maka-rail-hairline); |
| } |
| |
| .astryx-side-nav.maka-session-panel > div:has(> .maka-session-panel-footer) { |
| /* !important: StyleX stickyBottom is unlayered. */ |
| padding-block: var(--space-2) !important; |
| gap: 0 !important; |
| border-top: var(--border-width-hairline) solid var(--maka-rail-hairline); |
| background: transparent; |
| } |
| |
| /* Empty footerRow still mounts when hasButton:false; hide so it cannot |
| * reserve flex gap under Settings. */ |
| .astryx-side-nav.maka-session-panel > div:has(> .maka-session-panel-footer) > div:empty { |
| display: none; |
| } |
| |
| /* Both nav groups are SideNavSections, so both bring the section's own |
| * paddingBlock; the sticky zone shells above already own the rail's clearance, |
| * and leaving the section copy in place makes the two hairlines sit at |
| * different distances from the rows they separate (measured 9px vs 13px). |
| * !important: SideNavSection paddingBlock is StyleX/unlayered. */ |
| .maka-session-panel-top, |
| .maka-session-panel-footer { |
| padding: 0 !important; |
| } |
| |
| .maka-session-panel-footer { |
| border-top: 0 !important; |
| background: transparent; |
| } |
| |
| .maka-session-panel-footer .maka-sidebar-update-button { |
| margin-block-start: var(--space-1); |
| } |
| |
| /* #1879: this rule used to force `height: 34px` onto an Astryx Button. It is a |
| `<Button size="md">` now (session-sidebar-nav.tsx), so the 32px comes from |
| the component's own `--size-element-md` — the same token the 32px nav rows |
| it stacks under already read. Overriding a component's size from product CSS |
| is the drift the control ruler exists to end; declaring no height here is |
| what makes the two agree by derivation instead of by coincidence. */ |
| .maka-sidebar-update-button { |
| font: var(--maka-text-heading-4); |
| position: relative; |
| min-width: 0; |
| display: inline-grid; |
| grid-template-columns: auto; |
| align-items: center; |
| gap: var(--space-1); |
| /* Astryx Button reads `--_button-radius` for its own shape (Carousel and |
| Thumbnail set it the same way); declaring `border-radius` here would be a |
| product rule racing the component again. */ |
| --_button-radius: var(--radius-pill); |
| padding: 0 var(--space-3); |
| /* `background-color`, not the `background` shorthand — here and in EVERY |
| state rule below. The shorthand also resets `background-image`, which is |
| where Button's ghost variant keeps its hover and pressed overlays, so a |
| single shorthand anywhere in this file cancels the `variant` the component |
| was given. Product CSS is in the last cascade layer, so it wins that reset |
| regardless of specificity; fixing only the base rule left the overlays |
| dead on hover and in both download states, which is where they are most |
| visible. `border: 0` and `box-shadow: none` used to sit here too; both |
| restated what Button already computes. */ |
| background-color: var(--control); |
| color: var(--control-foreground); |
| overflow: hidden; |
| -webkit-app-region: no-drag; |
| transition: |
| background-color var(--duration-base) var(--ease-out-strong), |
| transform var(--duration-quick) var(--ease-out-strong); |
| } |
| |
| .maka-sidebar-update-button > span:not(.maka-sidebar-update-progress) { |
| position: relative; |
| } |
| |
| .maka-sidebar-update-button[data-update-state="downloading"] { |
| cursor: default; |
| background-color: oklch(from var(--control) calc(l + 0.04) calc(c * 0.68) h); |
| opacity: 1; |
| } |
| |
| .maka-sidebar-update-button[data-update-state="downloaded"] { |
| background-color: var(--control); |
| } |
| |
| .maka-sidebar-update-progress { |
| position: absolute; |
| inset: 0; |
| transform: scaleX(var(--maka-update-progress, 0)); |
| transform-origin: left center; |
| background-color: oklch(from var(--control) calc(l - 0.08) c h); |
| transition: transform var(--duration-base) var(--ease-out-strong); |
| } |
| |
| .maka-sidebar-update-button:hover { |
| background-color: oklch(from var(--control) calc(l - 0.04) c h); |
| } |
| |
| .maka-sidebar-update-button:disabled:hover { |
| background-color: oklch(from var(--control) calc(l + 0.04) calc(c * 0.68) h); |
| } |
| |
| .maka-sidebar-update-button:focus-visible { |
| outline: var(--focus-ring-width) solid var(--focus-ring); |
| outline-offset: var(--focus-ring-offset); |
| } |
| |
| .maka-session-row { |
| min-width: 0; |
| -webkit-app-region: no-drag; |
| } |
| |
| /* SideNavItem needs a truthy child to retain its disclosure control. Collapsed |
| * session trees provide this sentinel instead of mounting every Swarm child. */ |
| .maka-session-lazy-children-sentinel { |
| display: none; |
| } |
| |
| /* |
| * Dim only this row's SideNavItem. Child combinators stop before [role=group] |
| * nests, so a stale parent never mutes healthy subagent rows underneath. |
| * DOM: .maka-session-row > SideNavItem root > .astryx-side-nav-item |
| * (leaf: button; collapsible parent: split-action row that may host the |
| * primary control with aria-current). |
| */ |
| .maka-session-row[data-stale="true"] > div > .astryx-side-nav-item { |
| opacity: var(--opacity-muted); |
| } |
| |
| .maka-session-row[data-stale="true"] > div > .astryx-side-nav-item[aria-current="page"], |
| .maka-session-row[data-stale="true"] > div > .astryx-side-nav-item:has(> [aria-current="page"]) { |
| opacity: 1; |
| } |
| |
| .maka-session-row[data-subagent="true"] .astryx-side-nav-item { |
| color: var(--foreground-secondary); |
| } |
| |
| /* |
| * Project groups are a section label + peer sessions, not a deep tree. |
| * Astryx SideNavItem always pads children with spacing-6 (24px); that is the |
| * shell-side-nav workspace pattern, but it wastes a full icon column in a |
| * narrow session rail. Zero only the project item's own nest so sessions share |
| * the time-sort left edge. Do not use a descendant selector — that would also |
| * punch through subagent trees under session rows inside the project. |
| * DOM: .maka-project-row > SideNavItem root > [role=group] > childrenInner |
| */ |
| .maka-project-row > div > [role="group"] > div { |
| /* !important: StyleX childrenInner paddingInlineStart is unlayered. */ |
| padding-inline-start: 0 !important; |
| } |
| |
| .maka-session-row-end, |
| .maka-project-item-end { |
| display: inline-flex; |
| align-items: center; |
| justify-content: flex-end; |
| gap: var(--space-1); |
| flex-shrink: 0; |
| } |
| |
| /* Fixed trailing column so StatusDot ↔ MoreMenu swaps do not reflow the label |
| * (hover used to steal ~28px and shove the title left). */ |
| .maka-session-row-trailing { |
| display: inline-flex; |
| align-items: center; |
| justify-content: center; |
| flex: 0 0 auto; |
| width: var(--h-control-sm, 24px); |
| min-height: var(--h-control-sm, 24px); |
| } |
| |
| .maka-session-row-trailing-spacer { |
| display: block; |
| width: 8px; |
| height: 8px; |
| } |
| |
| .maka-session-worktree-icon { |
| flex: 0 0 auto; |
| color: var(--muted-foreground); |
| } |
| |
| .maka-session-row--editing { |
| padding-inline: var(--space-2); |
| padding-block: var(--space-1); |
| } |
| |
| .maka-session-rename-input { |
| font: var(--maka-text-heading-4); |
| width: 100%; |
| min-width: 0; |
| border: 0; |
| border-bottom: var(--border-width-hairline) solid oklch(from var(--focus-ring) l c h / 0.4); |
| background: transparent; |
| color: var(--foreground); |
| outline: 0; |
| padding: 1px 0; |
| } |
| |
| .maka-session-rename-input:focus { |
| border-bottom-color: var(--focus-ring); |
| } |
| |
| /* #1879: an Astryx `Badge variant="yellow"` now. Box, radius, padding and |
| caption type all come from the component (20px off `--spacing-5`), so the |
| only thing product CSS still owns is that it must not be squeezed by the |
| row's flex layout. */ |
| .maka-list-row-stale-pill { |
| flex-shrink: 0; |
| } |
| |
| /* ⌘N hint on the 新任务 row — quiet text, no chip chrome. */ |
| /* #1879: no chrome, but still a box, and it had no height of its own — |
| measured, its own leading at 40px took it from 20px to 40px and pushed the |
| 32px nav row with it. Pinned to `--h-control-xs` (20px), which is what the |
| supporting leading already resolves to, so nothing moves today. */ |
| .maka-nav-kbd { |
| /* A <kbd> composes the mono variant of every role (maka-tokens.css anchors |
| the role table on the code group too), and this hint has always opted out |
| — it read `font-family: inherit` before the roles landed. Naming the |
| family axis re-composes the role the element already carries, so the |
| opt-out stays one declaration instead of reopening the triplet. */ |
| --maka-font-family: var(--font-family-body); |
| font: var(--maka-text-supporting); |
| height: var(--h-control-xs); |
| display: inline-flex; |
| align-items: center; |
| margin-left: auto; |
| padding: 0; |
| border: 0; |
| border-radius: 0; |
| background: transparent; |
| box-shadow: none; |
| color: var(--muted-foreground); |
| letter-spacing: var(--tracking-wide); |
| white-space: nowrap; |
| } |