/* ================= THE ALTERNATE UX — TASKS =================
   The context strip, toolbar, quick actions, view tabs, list, row, and task detail panel. The
   hierarchy is the point: a full-width summary across the top, the work itself in the middle,
   the one task being read on the left, utilities on the right. */

/* ---------- the context strip, across the whole page ----------
   A sibling of .a-main, laid out by this file alone. The three-column grid inside .a-main is
   shared with notes/calendar and its tracks are counted by altGridTracks() — a strip declared
   as a fourth child would land in an implicit track. */
.a-context{ flex:0 0 auto; min-width:0; padding:var(--a-3) var(--a-4) 0; }
/* The column is the width it is given — without min-width:0 a flex/grid child sizes by its
   content, so six stat cards once grew a 320px track to 347px and the page scrolled sideways
   for no visible reason. */
.a-left > *,.a-analytics,.a-actions-card{ min-width:0; max-width:100%; }
/* A column of sections: the header row that folds it away, then the regions, which run ACROSS —
   this card spent its first life in a 320px rail where six figures had to be drawn 3x2. */
/* Ground/edge/radius come from `.a-card` (alt-components.css, added by altRenderAnalytics()) —
   not restated here. Tightened to match team_board's card: --a-3 padding, --a-2 header-to-body
   gap (was --a-4/--a-3) — measured 195px → 162px at 1440 desktop. Only the outer padding moved;
   `.a-glance .a-stats`'s own tile gap is untouched. Pinned in alt-experience.test.js. */
.a-analytics{ display:flex; flex-direction:column; align-items:stretch; gap:var(--a-2);
  padding:var(--a-3); }
.a-analytics > .a-sec-h h2{ margin:0; font:inherit; }
/* Three regions across: what the list amounts to, how it splits by status, which tags are in
   play. The first region is sized to content (700px ceiling), not a fractional share — a share
   put the sixth tile on a second row at some widths and not others. 700, not 600, because at
   600 the six tiles wrap "Done this week" and grow 72px tall against the 62 every other page
   uses for this component. */
.a-glance{
  display:grid; min-width:0; align-items:start; gap:var(--a-4) var(--a-5);
  grid-template-columns:minmax(0,700px) minmax(0,1fr) minmax(0,1fr);
}
.a-glance-part{ min-width:0; display:flex; flex-direction:column; gap:var(--a-2); }
.a-glance-part > .a-sec-h{ margin:0; }
/* The "…" beside a glance label is label-sized, not toolbar-sized — `.a-btn.icon.ghost.sm` is
   built for a control strip; at a 10px heading's own size it would read as a button with a
   caption. */
/* `.a-btn.` is in the selector on purpose — `.a-btn.icon`/`.a-btn.sm` are two-class rules a
   single-class selector loses to; the first version measured 18x32 (width took, height did not). */
.alt-app .a-btn.a-sec-h-more{
  width:18px; height:18px; min-height:0; padding:0; flex:0 0 auto; border-radius:5px;
}
.alt-app .a-btn.a-sec-h-more > svg{ width:13px; height:13px; }
/* `.a-stats`/`.a-stat` moved to alt-components.css — drawn by Tasks, Notes, Calendar and Admin;
   a fourth copy here would be the drift that move was meant to stop. */
.a-glance .a-stats{ grid-template-columns:repeat(auto-fit, minmax(92px, 1fr)); gap:var(--a-2); }
/* 8px gap (not 21px) matches the OTHER two columns' own h3-to-tile rhythm, and matches
   team_board.html's `.at-part` for the same column shape (alt-team.css). The border removal is
   the same deliberate match — alt-team.css:278 already ships gap:--a-2/no top padding/no top
   border for this exact component, not a side effect of the padding change. Pinned
   value-for-value in tasks-glance-panel.test.js. */
.a-dist{
  flex:0 0 auto; min-width:0; display:flex; flex-direction:column; gap:var(--a-2);
}
.a-dist-chips{ display:flex; align-items:center; gap:7px; flex-wrap:wrap; }
/* TWO ROWS OF CHIPS, AND THEN A COUNT. A reader with nine statuses and eleven tags got five rows
   of pills above their own task list — the card stopped being a summary and became a legend. The
   overflow is a control, so nothing is hidden, only folded. */
.a-dist-chips.clipped{ max-height:60px; overflow:hidden; }
.a-dist-more{
  background:none; border:0; padding:2px 4px; cursor:pointer; border-radius:var(--a-r-sm);
  color:var(--a-blue-text); font:500 12px/1.2 var(--a-body);
}
.a-dist-more:hover{ text-decoration:underline; }
.a-dist-more:focus-visible{ outline:2px solid var(--a-ring); outline-offset:1px; }
.a-sec-h{ margin-bottom:2px; }

/* ---------- THE STRIP WAS GROWING AS THE WINDOW SHRANK ----------

   MEASURED, AND IT IS THE WRONG WAY ROUND. #altContext came to 183px at 1920 and 273px at 1024,
   because three regions fell to two rows and then to three — and at 1024x768 that was most of the
   574px of chrome above a task list which computed to ZERO height, with the first row at y=849 in
   a 768px window. The page was a full screen of controls with no tasks on it.

   SO AT 1280 AND BELOW THE STRIP IS ONE ROW. The four figures the wireframe shows — Open, Due
   today, Overdue, This week — the heading, and "More". Starred, Done this week and both chip
   regions are behind that one control (altWireStripMore in JS/alt/alt-tasks.js), offering exactly
   the same filters the tiles and the chips do, so nothing is removed and one press still reaches
   any of them. 1280 is ALT_NARROW_MAX in that file; the two must stay the same number. */
@media (max-width:1280px){
  .a-context{ padding:var(--a-2) var(--a-4) 0; }
  .a-analytics{
    flex-direction:row; align-items:center; flex-wrap:nowrap;
    gap:var(--a-3); padding:var(--a-2) var(--a-3);
  }
  .a-analytics > .a-sec-h{ flex:0 0 auto; margin:0; }
  .a-analytics > .a-glance{ flex:1 1 auto; }
  .a-glance{ display:flex; align-items:center; gap:var(--a-2); }
  /* "Your work" is what the card is already called at the head of the row. */
  .a-glance-part{ flex:1 1 auto; }
  .a-glance-part > .a-sec-h{ display:none; }
  .a-glance .a-stats{ display:flex; gap:var(--a-2); }
  /* THE TILE LIES DOWN. A figure over a caption is 62px of a row that has to be one row; side by
     side it is 30, and the baseline they share is what keeps four of them reading as a set. */
  /* THE BASELINE IS RIGHT HERE and is not the defect it is in a fixed-height tile: this row is
     shrink-to-fit (`min-height:0`), so there is no spare box for the pair to sit at the top of,
     and it measures level. 3px rather than 5 only pays back the height the numeral's honest
     line box added above; the row is the 29px it has always been. */
  .a-stat{
    flex:1 1 0; flex-direction:row; align-items:baseline; gap:6px;
    min-height:0; padding:3px 9px;
  }
  .a-stat b{ font-size:16px; }
  .a-stat span{ white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  /* The two figures and the two chip regions the row cannot hold. `display:none` rather than
     visibility, so nothing here is left in the tab order pointing at something off screen. */
  .a-stat[data-stat="starred"],.a-stat[data-stat="donewk"],
  .a-glance-part[data-fold]{ display:none; }
}
/* ABOVE THAT WIDTH THERE IS ROOM FOR ALL OF IT, so the one control that exists only to make room
   is not drawn — and not focusable either. */
@media (min-width:1281px){
  #altStripMore{ display:none; }
}
@media (max-width:820px){
  .a-context{ padding-left:var(--a-3); padding-right:var(--a-3); }
  /* On a phone the row is allowed to become two: there is no list beside it competing for the
     height, because below 1024 the regions stack and the page scrolls. */
  .a-analytics{ flex-wrap:wrap; }
  .a-glance .a-stats{ flex-wrap:wrap; }
  .a-glance .a-stats > .a-stat{ flex:1 1 120px; }
}

/* ---------- actions row ---------- */
.a-actions{ display:flex; align-items:center; gap:var(--a-2); flex-wrap:wrap; padding:var(--a-3);
  background:var(--a-panel); border:1px solid var(--a-line-soft); border-radius:var(--a-r-lg); }
.a-actions .a-search{ flex:1 1 240px; max-width:420px; }
/* ---------- ROW 2 — THE QUICK-FILTERS STRIP ("Refined Proposal 3", 2026-09-11 rebuild) ----------
   TASKS-TOOLBAR-CONTRACT.md's Row 2: a quiet inline label, never a button, then a fixed run of
   toggle chips — Starred / On a board / Not on a board by default. The customization feature
   (`settings.altUx.tasks.quickActions`) survives per the contract's addendum Decision 2, so
   `#altQuickActions` can still render up to 16 entries if the reader chose them; only the
   ARRANGEMENT changed, from a strip mixing filters/creates/navigation with a "Choose these…"
   button in the row itself, to a quiet secondary strip whose configuration moved into
   "Filters & more" (`#altMoreFiltersBtn`, Row 1). `#altQuickToggle`'s static markup — the
   "Hide/Show quick actions" button — is UNSTYLED here on purpose: it is contract-moved inside
   that same menu, so the button in `tasks.html` needs to come out of this row (reported to the
   integrator; nothing in this file targets it any more).

   IT WEARS THE TOOLBAR'S CLOTHES, LITERALLY THIS TIME. Row 1 and Row 2 are two sibling DOM
   nodes, not two children of one wrapper, so "one compact block, not three stacked bars" is
   built the same way `.a-actions`'s own card is — background, edge and radius — split across
   the two (soon three, with the footer) siblings: `#altControls` owns the top corners and no
   bottom edge, this row owns neither, and `.a-toolbar-hint` below owns the bottom corners.

   THIS COMMENT WAS WRONG ABOUT WHY IT WOULD READ AS ONE CARD, and the owner's screenshot proved
   it: three visible bands, full-width seams between them, the middle one reading a different
   tone from its neighbours. Measured on the rendered page (both themes, signed in): the three
   regions' `background-color` are IDENTICAL and the touching edges already carry NO border
   (`#altControls` has `border-bottom:0`, this rule has `border-top:0`) — so nothing here was
   drawing a line. What was: `#altControls`/`#altQuickStrip`/`.a-toolbar-hint` are siblings of
   `.a-centre`, and `.a-left,.a-centre,.a-right{display:flex;flex-direction:column;gap:var(--a-3)}`
   (alt-shell.css, shared, not this file's to touch) puts a flat 12px `gap` between EVERY child of
   that column — `#altTabs`→`#altControls` too, correctly, but also `#altControls`→`#altQuickStrip`
   and `#altQuickStrip`→`.a-toolbar-hint`, which this file never asked for. That 12px gap is
   `.a-centre`'s own transparent background showing through, full width, between two boxes whose
   independent left/right borders resume at each one's own top-left/top-right corner — which is
   exactly "a full-width horizontal rule" and exactly why the panel between two such gaps reads as
   sitting apart rather than differently coloured; the colour was never different.

   THE FIX IS A NEGATIVE MARGIN, NOT A NEW DIVIDER. `margin-top:calc(var(--a-3) * -1)` on this rule
   and on `.a-toolbar-hint` cancels exactly the parent's own `gap` for these two seams only — every
   OTHER gap in the column (above `#altControls`, below `.a-toolbar-hint`) is untouched, because
   only these two elements carry the override. `#altControls` needs no matching rule: it is not
   pulling itself up, its two followers are. The three regions now abut with zero space between
   them, so the "minimal separation between rows" the mock asks for comes from each row's own
   padding (`--a-2`/`--a-3` top and bottom, declared where each region sets it) rather than from a
   rule or a gap — spacing, not a seam, per the instruction this rewrite was written against. */
.a-quick-strip{
  display:flex; align-items:center; gap:var(--a-2); flex-wrap:wrap; flex:0 0 auto; min-width:0;
  background:var(--a-panel); border:1px solid var(--a-line-soft); border-top:0;
  /* CANCELS `.a-centre`'s OWN `gap:var(--a-3)` FOR THIS ONE SEAM. See the comment above this
     rule for why a gap, not a colour or a border, was what read as a horizontal rule here. */
  margin-top:calc(var(--a-3) * -1);
  padding:6px var(--a-4);   /* tightened with #altControls above, 2026-09-13 */
}
.a-quick-strip .a-actions{
  padding:0; background:none; border:0; border-radius:0; flex:1 1 auto; min-width:0;
}
/* THE LABEL IS TEXT, NOT A CONTROL — no button semantics, no focus stop, no hover. The bolt is
   decorative (the words already say "Quick filters"), so it is `aria-hidden` like every other
   glyph beside a label in this file. */
.a-qf-label{
  display:inline-flex; align-items:center; gap:5px; flex:0 0 auto; white-space:nowrap;
  font-size:11px; font-weight:700; letter-spacing:.02em; color:var(--a-dim);
}
.a-qf-label > svg{ width:13px; height:13px; flex:0 0 auto; color:var(--a-gold); }
#altQuickActions{
  display:flex; align-items:center; gap:var(--a-2); flex-wrap:wrap; min-width:0;
}

/* ---------- THE TAB ROW'S RIGHT-HAND END ----------
   `.a-tabs-strip` holds the tab buttons `altRenderTabs()` used to draw straight into `#altTabs`;
   it exists only so `.a-tabs-end` (the density control, Refresh and "More" — see that function's
   own header) can sit beside it as a second flex child pushed right by the shared primitive's own
   `margin-left:auto`, exactly the arrangement `.a-tabs-end` already provides on other pages. */
.a-tabs-strip{ display:flex; align-items:center; gap:2px; flex-wrap:wrap; min-width:0; }
/* THE TAB ROW GREW A SECOND JOB and needs the same control height the toolbar below it uses, so
   the density segment, Refresh and More do not read as a different row wearing the tab strip's
   clothes. */
#altTabs .a-tabs-end .a-btn.sm{ height:var(--a-ctl); }
/* ---------- AND THE CONTROLS NEEDED AIR ABOVE THE RULE ----------
   REPORTED AS "the horizontal bar is too tight to the views", and measured before it was
   touched: the density segment cleared `.a-tabs`' bottom border by FIVE pixels, because the
   shared strip is sized by its 38px tab buttons and a 30px control centred in that leaves four
   above and four below plus the 1px rule. Five pixels reads as a control resting ON the line
   rather than sitting in a row above it.

   WHY NOT `padding-bottom` ON `.a-tabs`, WHICH IS THE OBVIOUS FIX AND IS WRONG. The chosen tab
   marks itself with `border-bottom:2px` on the BUTTON, and that stripe is only read as "this
   tab" because it lands exactly on the strip's own rule and interrupts it. Padding the strip
   moves the rule down and leaves the stripe floating in the gap, which turns the one component
   that must look attached into one that looks broken. So the tabs keep reaching the border and
   only the right-hand group moves.

   HOW: the group's own margins make it the tallest child, so the ROW grows rather than the
   controls being squeezed upward into the header — five pixels of new air below without taking
   the four that were already above. `.a-tabs-strip` then has to be stretched and bottom-aligned,
   because the shared parent centres its children and a centred 38px strip in a 43px row would
   lift every tab — and its stripe — off the rule, which is the exact defect the paragraph above
   refuses. Scoped to `#altTabs`: okrs.html, team_board.html and the admin console draw this same
   component with no segmented control in the end group, so they have no crowding to fix and are
   deliberately left alone. */
#altTabs .a-tabs-strip{ align-self:stretch; align-items:flex-end; }
/* LONGHAND, DELIBERATELY — the shorthand this replaced set an implied `margin-left:0` and beat
   the shared `.a-tabs-end{ margin-left:auto }` from alt-components.css:910 on specificity alone
   (an id plus a class outweighs a class alone, regardless of cascade order), which is what
   pulled the density/Refresh/More group off the far right and hard against the last tab.
   Reported and CHOSEN, of three options shown:
   same row, pushed to the far right — which is exactly the arrangement `margin-left:auto`
   already gives every OTHER host of `.a-tabs-end`. Only the two verticals this rule exists for
   are restated; `margin-right` is left unset rather than pinned to 0, so it cannot acquire the
   same kind of override again by habit. */
#altTabs .a-tabs-end{ margin-top:4px; margin-bottom:9px; }
@media (max-width:639px){
  /* SAME REASONING AS THE TOOLBAR'S OWN RULE BELOW, RELOCATED WITH THE CONTROL: "Comfy" and
     "Compact" have no icons, so the segmented pair cannot shed its word the way every other
     control on this row does. Density stays reachable — the Sort menu's own block, and Settings
     — so nothing is lost, only folded off a row that has no room left for two unabbreviated
     words. */
  #altTabs .a-seg-ctl{ display:none; }
}

/* ---------- A SPLIT BUTTON: ONE ACTION ON THE FACE, A MENU BEHIND THE CHEVRON ----------
   Built from the same `.a-btn` primitive twice, with the seam between them removed rather than
   inventing a fifth button vocabulary: same fill, same border, same height, one shared radius on
   the outside edges only. `altAddSplitHtml()` in JS/alt/alt-tasks.js is the only caller. */
.a-btn-split{ display:inline-flex; align-items:stretch; }
.a-btn-split > .a-btn{ border-radius:0; }
.a-btn-split > .a-btn:first-child{ border-radius:var(--a-r-sm) 0 0 var(--a-r-sm); }
/* NO SEAM COLOUR OF ITS OWN. A literal rgba divider on top of `--a-blue-fill` is a colour this
   file would own outside the token set, and `.a-btn.primary:hover`'s existing brightness filter
   already marks which half the pointer is over; the shared radius doing the rest is enough to
   read the two as one control. */
.a-btn-split > .a-btn:last-child{ border-radius:0 var(--a-r-sm) var(--a-r-sm) 0; padding:0 6px; }
.a-btn-split > .a-btn.icon{ width:auto; }

/* ---------- ROW 1 — ADD · JUMP · ARRANGE, ONE ROW WHERE IT FITS, WRAPPING WHERE IT DOES NOT ----

   MARKUP CONTRACT (TASKS-TOOLBAR-CONTRACT.md, styled against by LANE CSS 2026-09-11; report a
   mismatch to the integrator rather than guessing around it):
     #altControls (.a-toolbar)
       .a-tb-row                                  -- wide only, ≥1025px; the line-break child
         #altToolbarBody.a-tb-fold                -- 2026-09-14: the part the fold hides
           .a-btn-split                           -- #altAddTask + #altAddTaskMenuBtn, unchanged
           .a-tb-dates[role=group]                -- 4x button.a-chip.a-tb-date[data-jump]
                                                       the current one carries aria-current="true"
           #altGroupMenuBtn.a-btn.sm              -- svg + .a-lbl "Group:" + .a-val "By date"
           #altSortMenuBtn.a-btn.sm               -- svg + .a-lbl "Sort:" + .a-val "Smart"
           .a-tabs-end                            -- pushes its child right (shared primitive)
             #altMoreFiltersBtn.a-btn.sm          -- svg + .a-lbl "Filter…" (whole label, one
                                                       span — 2026-09-19, owner request; was
                                                       "Filters" in the span plus a bare "& more"
                                                       text node beside it) + .n badge
         #altToolbarToggle.a-btn.ghost.sm         -- the fold itself; OUTSIDE the wrapper, so it
                                                       survives its own press. Word + .cv chevron
     #altControls.a-tb-compact                    -- ≤1024px; no .a-tb-row child, same two parts:
       #altToolbarBody.a-tb-fold holding .a-btn-split, #altJumpMenuBtn.a-btn.sm (icon + "Today" +
       chevron, replaces the 4 chips), #altGroupMenuBtn / #altSortMenuBtn / #altMoreFiltersBtn
       (icon-only, same ids); then #altToolbarToggle beside it

   Assignee, Status, Tags and Board are GONE from this row entirely (contract: all four fold into
   "Filters & more" unconditionally, not just when compact) — so is the "Jump to" caption and the
   old `.a-tgroup`/`.a-vrule` separators that ran between the old row's groups. Nothing here still
   targets `.a-field.inline`, `.a-tgroup` or `.a-vrule`; if compact markup still emits them, that
   is a mismatch to report, not a selector this file silently keeps alive for.

   `.a-tb-row` IS STILL THE LINE BREAK, same primitive as before the rebuild: `.a-toolbar`
   (#altControls) is `display:flex;flex-wrap:wrap` (CSS/alt/alt-components.css, shared — the rule
   moved out of alt-shell.css and this sentence still named the old home) and stays that way at
   every width from 2026-09-17: the `flex-wrap:nowrap` this file used to add back at 1499 and
   below is what made a row too narrow for its contents OVERLAP them instead of wrapping. See
   the tight-width block further down. A child given `flex:1 1 100%` always starts a new line inside a
   wrapping flex container. Below ALT_CONTROLS_COMPACT_MAX (1024, JS/alt/alt-tasks.js) the compact
   render never emits a `.a-tb-row` at all, which is why every rule below is scoped to the class
   rather than to `#altControls` directly.

   THE CARD. `#altControls`, `#altQuickStrip` and `.a-toolbar-hint` are three sibling regions that
   read as one block — see the Row-2 comment above for why the seam is split this way instead of
   wrapping all three in a fourth element neither JS lane's markup contract asked for. */
#altControls{
  background:var(--a-panel); border:1px solid var(--a-line-soft); border-bottom:0;
  border-radius:var(--a-r-lg) var(--a-r-lg) 0 0;
  /* VERTICAL PADDING TIGHTENED 2026-09-13, owner's request — the three stacked rows read
     as one block and the block was taller than the controls in it needed. Only the
     VERTICAL step comes down (--a-3 12px -> --a-2 8px); the horizontal gutter stays at
     --a-4 because it is what lines this card's edges up with Work at a Glance above it
     and the list below, and narrowing it would break that alignment to save nothing. */
  padding:var(--a-2) var(--a-4);
}
#altControls .a-tb-row{ flex:1 1 100%; display:flex; align-items:center; gap:var(--a-2); flex-wrap:wrap; min-width:0; }
#altControls .a-btn.sm,#altQuickStrip .a-btn.sm{ height:var(--a-ctl); }

/* ---------- THE FOLD: WHAT GOES, AND WHAT STAYS BEHIND (owner, 2026-09-14) ----------

   The Hide/Show control moved out of the tab row and into this card's own first row, at the far
   right — the owner sent the position on a screenshot and asked for "the standard show hide
   behavior found in the work at glance section above", which is a fold that lives in the header
   OF the thing it folds. A control inside what it hides cannot hide itself, so `#altToolbarBody`
   is the wrapper holding everything in row 1 EXCEPT the toggle, and that is what JS marks
   `hidden` (altApplyToolbarOpen()). What is left is a slim bar reading Show — the same thing
   Work at a Glance leaves behind.

   `flex:1 1 auto` IS WHAT KEEPS THE OLD RIGHT-ALIGNMENT WORKING. `.a-tabs-end` inside it still
   carries `margin-left:auto`, so "Filters & more" is still thrown at the right; the wrapper
   simply ends where the toggle begins. The toggle's own `margin-left:auto` is for the folded
   state, when the wrapper is gone and there is nothing left to push it. */
#altControls .a-tb-fold{
  display:flex; align-items:center; gap:var(--a-2); flex-wrap:wrap; flex:1 1 auto; min-width:0;
}
#altToolbarToggle{ flex:0 0 auto; margin-left:auto; }
/* `.a-tb-shut` IS GONE (2026-09-14, second pass). It closed off #altControls when a fold left
   that bar alone with nothing under it. Folding now HIDES #altControls outright and moves the
   toggle down into the quick-action row, so the bar is never alone — there is no case left for
   the class. `.a-quick-strip.solo` at the foot of this file is what draws the card now. */
/* THE COMPACT ROW HAS NO `.a-tb-row` CHILD to hang a rule on, so the class the render functions
   toggle on `#altControls` itself (see altRenderControlsWide()/altRenderControlsCompact()) is
   the signal instead. */
/* WRAPS RATHER THAN OVERLAPS, for the identical reason the 1499 block above does — this tier
   had the same `nowrap` over the same non-shrinking children, so at a width its contents cannot
   fit into they overflowed onto #altToolbarToggle instead of moving down. At 390px the row is
   Add, Today, Group, Sort, Filters, Clear and Hide, every one already icon-only; where that
   fits, this changes nothing, and where it does not, the reader gets a second line instead of
   two controls sharing the same pixels. */
#altControls.a-tb-compact{ flex-wrap:wrap; padding:var(--a-2) var(--a-4); }
#altControls.a-tb-compact > *{ flex:0 0 auto; }
/* AND THE FOLD WRAPPER IS THE ONE CHILD THAT MUST GROW, so it has to come AFTER the blanket
   `> *{flex:0 0 auto}` above — the two selectors have identical specificity and source order is
   what decides it. Without this line the compact row's wrapper shrank to its content and the
   Hide control sat immediately beside "Filters & more" in the middle of the bar instead of at
   the card's right edge. `nowrap` because this shape is one line by contract; see the wide
   `.a-tb-fold` rule above for what the wrapper is and why it exists. */
/* AND THE WRAPPER TOO, or the fold is a single unbreakable line inside a container that is
   allowed to wrap — which is the overflow again, one level in. */
#altControls.a-tb-compact > .a-tb-fold{ flex:1 1 auto; flex-wrap:wrap; gap:var(--a-1); }
#altControls.a-tb-compact .a-tabs-end{ margin-left:auto; gap:var(--a-1); }

/* ---------- THE DATE-CHIP GROUP ----------
   Four equal-weight chips, tight together as one decision asked four ways — same job `.a-tgroup`
   did for three of them before the rebuild, renamed because it is no longer three chips beside a
   caption, it is all four with no caption at all ("Jump to" is gone per the contract). */
.a-tb-dates{ display:inline-flex; align-items:center; gap:var(--a-1); flex:0 0 auto; min-width:0; }

/* ---------- THE RAISED-CHIP PRESSED STATE — three signals, none of them hue ----------
   Same shape as `.a-theme-seg-b[aria-pressed="true"]` / `.a-search-scope-b[aria-pressed="true"]`
   (alt-shell.css): a surface of its own, a control-grade edge and an elevation, so which chip is
   current never depends on colour alone. NOT folded into `.a-chip.on` — that class already means
   something elsewhere in the suite (a blue wash with no border/shadow change, used by tag and
   status filter chips) and is not this contract's to redefine; scoping to this toolbar keeps the
   two states from fighting if a future page reuses `.a-chip.on` differently than this one reuses
   `[aria-current]`/`[aria-pressed]`.

   `aria-current="true"` FOR THE DATE CHIPS, `aria-pressed="true"` FOR THE QUICK-FILTER TOGGLES —
   deliberately two different attributes for the same visual state, because they are two different
   kinds of control: a date chip navigates (altRevealBucket(), never more than one "current"
   section at a time — the current-page-in-a-set semantics `aria-current` exists for), a
   quick-filter chip is a real toggle that narrows the list (altApplyQuick(), and can be off, one
   on, or several on at once — `aria-pressed` semantics). Same look, honest semantics either way. */
#altControls .a-chip,
#altQuickStrip .a-chip{ height:24px; }         /* the shared 22px chip sits under this page's 24px pointer-target floor */
#altControls .a-chip[aria-current="true"],
#altQuickStrip .a-chip[aria-pressed="true"]{
  background:var(--a-float); color:var(--a-blue-text); font-weight:700;
  border-color:var(--a-line-strong); box-shadow:var(--a-shadow-sm);
}

/* ---------- EVERY OTHER ROW-1 CONTROL READS AS THE SAME QUIET CHIP FAMILY ----------
   `#altGroupMenuBtn`, `#altSortMenuBtn`, `#altMoreFiltersBtn` and compact's `#altJumpMenuBtn` stay
   `.a-btn.sm` — the menu-trigger primitive, unchanged, so alt-layers.js's existing anchor/roving-
   focus wiring keeps working with no markup change asked of LANE JS beyond dropping the old
   wide-row-2 buttons. What changes here is only their FACE within this row: pill radius and a
   transparent, bordered ground instead of the raised default, so a menu trigger and a chip read
   as one family exactly the way the contract's "quiet chip of equal weight" asks — the primary
   Add-task button is the only filled control left on the row.

   DESCENDANT, NOT CHILD, AND `:not(.primary)` CARRIES THE WHOLE EXCLUSION. `#altMoreFiltersBtn`
   sits one level deeper than Group/Sort — inside `.a-tabs-end`, per the markup contract above —
   so a `>` combinator here silently never reached it (caught in this file's own fixture probe:
   the Filters & more chip measured as the RAISED `.a-btn` default, not the quiet face, at every
   width). `:not(.primary)` is what keeps this rule from also flattening `#altAddTask`/
   `#altAddTaskMenuBtn` — both `.a-btn.primary.sm` — into the same quiet face; a `>` restriction
   was never what protected the primary button; the class was. */
/* `:not(.ghost)` ON ALL THREE — MEASURED, NOT ANTICIPATED (2026-09-14). These rules restyle
   EVERY button in the row into the quiet outlined pill the toolbar is drawn from, and that was
   right while every button in the row was a pill. #altToolbarToggle is not: it is a `.ghost`
   disclosure, the exact treatment the owner asked for twice by name ("the standard show hide
   behavior found in the work at glance section"), and these rules gave it a border, a pill
   radius and a background the moment it moved in here. `.ghost` is already the class that MEANS
   "no border, no fill", so excluding it is the rule saying what it always meant rather than an
   id exception that the next ghost control in this row would not get.

   THE `[aria-expanded="true"]` ONE IS THE ONE THAT ACTUALLY MISLED. Measured on the moved
   control before this fix: `background: color(srgb 0.12 0.19 0.28)`, `border-color: #4e71a5`,
   `color: #70a4f8` — the lit "my menu is open" signal, painted on a control whose menu does not
   exist. `aria-expanded` means two different things on the two kinds of button in this row: on
   #altGroupMenuBtn it says a popup is on screen, on a disclosure it says the block below is
   showing, which is its RESTING state. A fold that looks pressed whenever it is doing nothing is
   the same class of defect as a control that looks present and is inert. */
/* AND THE THIRD SELECTOR IN EACH OF THE THREE RULES BELOW IS THE CLUSTER ITSELF, NOT A HOST
   (2026-09-21). `#altFilterChips` is the `.a-tabs-end` span holding "Filter…" and "Clear
   filters", and since the owner's "when hidden the panel shall remain the same just with these
   buttons visible" it PARKS IN A DIFFERENT PARENT when the block is folded — altParkControl()
   moves it into `#altQuickStrip`, the same gesture #altToolbarToggle already made. Every rule
   scoped to `#altControls …` stops matching the moment that happens, which would have shipped
   the exact defect CLAUDE.md 4d/4h describe: two controls, correctly rendered, wearing nothing.

   SO THE FACE IS WRITTEN AGAINST THE CLUSTER AND TRAVELS WITH IT. One declaration block per
   question, three selectors — never a second copy of these colours under a `.a-quick-strip`
   prefix, which is how the two states would drift apart. The same reasoning applies to the
   word-shedding and padding rules in the `max-width:1499px` block further down; both are
   restated there against `#altFilterChips` for the same reason and with the same values, which
   is what makes "position them the same way" true by construction rather than by coincidence. */
#altFilterChips .a-btn.sm:not(.primary):not(.ghost),
#altControls .a-tb-row .a-btn.sm:not(.primary):not(.ghost),
#altControls.a-tb-compact .a-btn.sm:not(.primary):not(.ghost){
  background:transparent; border-color:var(--a-line-soft); border-radius:var(--a-r-pill);
  color:var(--a-dim);
}
#altFilterChips .a-btn.sm:not(.primary):not(.ghost):hover,
#altControls .a-tb-row .a-btn.sm:not(.primary):not(.ghost):hover,
#altControls.a-tb-compact .a-btn.sm:not(.primary):not(.ghost):hover{ background:var(--a-raised); color:var(--a-text); border-color:var(--a-line-strong); }
/* THE OPEN MENU IS THE SAME RAISED SIGNAL AS A PRESSED CHIP — the trigger IS the current
   selection while its menu is up, same reasoning as the date/quick-filter chips above. */
#altFilterChips .a-btn.sm:not(.primary):not(.ghost)[aria-expanded="true"],
#altControls .a-tb-row .a-btn.sm:not(.primary):not(.ghost)[aria-expanded="true"],
#altControls.a-tb-compact .a-btn.sm:not(.primary):not(.ghost)[aria-expanded="true"]{
  background:var(--a-float); color:var(--a-blue-text);
  border-color:var(--a-line-strong); box-shadow:var(--a-shadow-sm);
}

/* ---------- THE MASTER FOLD'S FIT IN THIS CLUSTER (owner, 2026-09-23) ----------

   `.a-tasks-fold` is the shared expand/collapse-all toggle — altFoldAllEl() in
   JS/alt/alt-view-controls.js, inserted as the first child of #altFilterChips by
   altSyncFoldAll() — wearing a class of THIS page's, which is what the component's `cls` option
   is for. Its behaviour and its lit blue wash are declared once, in CSS/alt/alt-components.css,
   because twelve surfaces must light it identically. Only its FIT belongs here, and only the two
   declarations this row actually needs:

   THE PILL, because its two neighbours are pills. `#altFilterChips .a-btn.sm:not(...):not(.ghost)`
   above rounds "Filter…" and "Clear filters" to `--a-r-pill`, and excludes this one by
   construction — the component's compact form is `.ghost`. Left at `.a-btn`'s own `--a-r-sm` the
   lit wash would paint a rounded square between two pills, which reads as a control from another
   row rather than as the third member of this cluster.

   THE PADDING, AND IT IS A DEFECT PREVENTED RATHER THAN A PREFERENCE. At ≤1499px this file sets
   `padding:0 8px` on every `.a-btn.sm` in the row AND, separately, on every one in the parked
   cluster. Both are id-scoped, so both beat `.a-btn.icon{padding:0}` on specificity: the box
   stays 32px wide, the content box drops to 14px, and the 15px glyph
   (`.a-btn.icon.sm > svg`, `flex:0 0 auto`) overflows it. That is the same arithmetic residue
   alt-components.css's own note records paying for once, arriving from the other direction — a
   rule written for a labelled control reaching a control with no word in it. Restated for the
   cluster as well as the row, for the reason every other rule in this file is: #altFilterChips
   parks in #altQuickStrip when the reader hides the toolbar, and a rule scoped to #altControls
   stops matching the moment it does.

   NO HEIGHT OR WIDTH OF ITS OWN, deliberately. `#altControls .a-btn.sm` / `#altQuickStrip
   .a-btn.sm` already put every control in this row at `--a-ctl`, and `.a-btn.icon{width:var(--a-ctl)}`
   squares it — so it is 32x32 beside 32px-tall neighbours in both parked states with nothing
   declared here. A restatement would be a third answer waiting to disagree with those two.

   AND `.sm` IS IN THE SELECTOR FOR ARITHMETIC, NOT DECORATION. `#altFilterChips .a-btn.sm` is
   (1,2,0) and so is `#altFilterChips .a-btn.a-tasks-fold` — equal specificity, and the ≤1499px
   block sits LATER in this file, so without the third class the padding rule this one exists to
   overrule would win on source order alone. Measured the same way the note above it was. */
#altFilterChips .a-btn.sm.a-tasks-fold,
#altControls .a-btn.sm.a-tasks-fold{ border-radius:var(--a-r-pill); padding:0; }

/* ---------- THE ROW SHEDS WORDS BEFORE IT SHEDS CONTROLS ----------
   1499 IS WHERE THE SHELL ALREADY NARROWS THE RAILS, and it is the same squeeze: at 1440 the
   centre column is 620px and the full row needed three lines of it. Measured, not guessed, before
   the rebuild — reconfirm once LANE JS's markup lands, because the row carries far less now
   (Assignee/Status/Tags/Board are gone) and this tier may no longer be reachable at all; kept
   defensively rather than deleted; an unreachable media query costs nothing and a reachable-again
   one after a future addition is not rediscovered by guessing. This only ever answers for the WIDE
   toolbar (1025–1499): at 1024 and below the compact render has already replaced the row with one
   built icon-first from the start, so there is nothing left here for the compact class to
   override. Date-chip words are NOT shed here — "Today"/"Tomorrow"/"This Week"/"Next Week" ARE
   the content, there is no icon that means the same thing, and the compact tier is what turns
   the whole group into one "Today ▾" menu when there truly is no room. */
@media (max-width:1499px){
  /* The value is the part that changes and the icon says which control it belongs to, so
     "Group:", "Sort:" and "Filter…" (renamed from "Filters", 2026-09-19) go and their current
     value (or count) stays. Unlike Group/Sort, "Filter…" is the WHOLE visible label now — no
     `.a-val` of its own, so hiding `.a-lbl` here leaves only the icon and the `.n` count badge,
     nothing in between. */
  #altGroupMenuBtn .a-lbl,#altSortMenuBtn .a-lbl,#altMoreFiltersBtn .a-lbl{ display:none; }
}

/* ---------- AND AT 1499 AND BELOW THE ROW SHEDS WORDS — AND WRAPS WHEN THAT IS NOT ENOUGH ----

   THE TWO `flex-wrap:nowrap` DECLARATIONS THAT USED TO BE HERE ARE THE DEFECT THE OWNER
   REPORTED, and they are gone: "the section should create another row instead of colliding and
   overlapping with the buttons/options when the width is too small to keep 2 rows."

   WHAT ACTUALLY HAPPENED, because "it overlapped" usually means something left the flow and
   here nothing did. The block below still sets `flex:0 0 auto` on every control — shrink:0, so
   none of them may narrow. With `nowrap` on top of that, a container too small for its contents
   has no legal way to make them fit, so they OVERFLOW its right edge. `.a-tb-fold` is
   `flex:1 1 auto; min-width:0`, so its BOX shrinks to whatever is left beside #altToolbarToggle
   while its CONTENTS keep their full width and spill straight over the toggle. `.a-tabs-end` is
   the fold's last child, which is why "Filters & more" is the thing that lands on "Hide".

   AND THE QUERY CANNOT SEE THE WIDTH IT IS RULING ON. `max-width:1499px` is the WINDOW. This
   toolbar lives in the centre COLUMN, which is the window minus the details pane and the utility
   rail — roughly 600px of a 1440px window with both open. So the one-row guarantee was being
   made for a width that does not exist whenever the reader has their panels open, which is
   exactly the arrangement in the screenshot.

   THE JUSTIFICATION FOR nowrap HAD ALSO EXPIRED. Its comment said the row must be one row
   "whatever the reader's tag names happen to measure" — written when Status, Tags and Board
   chips stood in this row. The 2026-09-11 rebuild moved all three into the "Filters & more"
   menu (altMoreFiltersMenu()), so the row's content is now a fixed set of short controls and
   there is no reader-supplied string left in it to measure. What the declaration still did was
   convert "does not fit" from a wrap into a collision.

   SO: SHED WORDS FIRST, WRAP SECOND, NEVER OVERLAP. The `.a-lbl`/`.a-val` rule below is the
   first line of defence and is untouched — at widths where hiding the words is enough, this row
   is still one row and nothing about it moves. When even that does not fit, the base
   `flex-wrap:wrap` on `.a-tb-row` and `.a-tb-fold` (stated once, near the top of this section)
   now applies, and a control that will not fit moves to a second line instead of being drawn on
   top of its neighbour. `flex:0 0 auto` STAYS, and that is the pairing that makes wrapping the
   only outcome: a shrinkable child would squash to an unreadable stub before it ever wrapped.

   THE LINES DO NOT NEED A ROW-GAP OF THEIR OWN. Both containers already declare `gap:var(--a-2)`,
   which in flex is both axes — so the second line is 8px below the first, the same distance the
   controls sit apart along it.

   1499 is ALT_TIGHT_MAX in JS/alt/alt-tasks.js; the two must stay the same number. */
@media (max-width:1499px){
  #altControls .a-tb-row > .a-btn,#altControls .a-btn-split,
  #altControls .a-tabs-end,#altControls .a-tabs-end .a-btn{ flex:0 0 auto; }
  #altControls .a-lbl,#altControls .a-val{ display:none; }
  #altControls .a-btn.sm{ padding:0 8px; }
  #altControls .a-tabs-end{ gap:var(--a-1); }
  /* THE SAME FOUR, AGAINST THE CLUSTER RATHER THAN ITS HOST — see the note above the quiet-pill
     rules. Folded, `#altFilterChips` is a child of `#altQuickStrip` and none of the four above
     reach it, so the chips would come back with their words ("Filter…", "Clear filters"), a
     wider pad and an 8px inner gap while the open row shows them icon-only and tight — two
     different widths for the same pair, which is precisely what "position them the same way"
     forbids. Identical values, deliberately: this is the same decision restated for a second
     parent, not a second decision. */
  #altFilterChips,#altFilterChips .a-btn{ flex:0 0 auto; }
  #altFilterChips .a-lbl,#altFilterChips .a-val{ display:none; }
  #altFilterChips .a-btn.sm{ padding:0 8px; }
  #altFilterChips{ gap:var(--a-1); }
  /* AND THE FOLD CONTROL KEEPS THE ROW'S TIGHTER PAD WHEREVER IT IS PARKED. `#altControls
     .a-btn.sm{padding:0 8px}` above is the toolbar tightening this tier applies to every control
     in the row, and #altToolbarToggle is one of them — until it is parked in #altQuickStrip,
     where that selector stops reaching it and the shared `.a-btn.sm{padding:0 9px}` takes over.
     MEASURED, not anticipated: the same button came out 64.7px wide open and 72.4px folded at
     1440, and since it is what the chips are pushed up against, 2px of that landed straight in
     the chips' x-position. Exactly the same host-scoping miss the cluster rules above exist for,
     found by measuring the thing this change is about. */
  #altQuickStrip > #altToolbarToggle{ padding:0 8px; }
}

/* ---------- ROW 2 NARROWS BY WRAPPING, NOT BY SHEDDING ----------
   Three fixed toggle chips plus a short label is little enough content that a second line inside
   the strip is cheap and never surprising — unlike Row 1, there is no menu to fold an overflowing
   chip into, and the contract names no fallback for Row 2. Wrapping keeps every chip a real,
   labelled, keyboard-reachable button at every width, which is the same reasoning the "shed words
   before controls" comment above gives for Row 1 — here there are no words left to shed first. */
@media (max-width:479px){
  .a-quick-strip{ row-gap:var(--a-1); }
}

/* ---------- THE FOOTER — ONE MUTED HINT LINE BELOW BOTH ROWS ----------
   New element, contract §"FOOTER": folds the old bare "Double click for full detail" line (still
   removed from `altRenderList()` by LANE JS, not duplicated) into one sentence with a leading
   icon. `tasks.html` has no host for this yet — reported to the integrator as
   `<div class="a-toolbar-hint" id="altToolbarHint">` between `#altQuickStrip` and `#altList`, the
   third and final sibling completing the one-block card Row 1/Row 2 start above — see the seam
   comment on `.a-quick-strip` for why this one also needs `margin-top` rather than relying on the
   siblings simply touching: `.a-centre{gap:var(--a-3)}` (alt-shell.css) puts the same 12px between
   THIS element and `#altQuickStrip` that it put between Row 1 and Row 2, and it reads exactly the
   same way — a full-width band of the page's own ground between two independently-bordered boxes
   — so it needs the identical cancellation, not a new one. This is meant to read as the card's
   LAST LINE, set off from Row 2 by spacing and its own smaller, quieter type — never a rule. */
.a-toolbar-hint{
  display:flex; align-items:center; gap:6px; flex:0 0 auto; min-width:0;
  background:var(--a-panel); border:1px solid var(--a-line-soft); border-top:0;
  border-radius:0 0 var(--a-r-lg) var(--a-r-lg);
  /* CANCELS `.a-centre`'s OWN `gap:var(--a-3)` FOR THIS SEAM TOO — same fix, same reason, as
     `.a-quick-strip`'s own `margin-top` above. */
  margin-top:calc(var(--a-3) * -1);
  padding:6px var(--a-4);   /* tightened with #altControls above, 2026-09-13 */
  font-size:11px; color:var(--a-faint); line-height:1.4;
}
.a-toolbar-hint > svg{ width:13px; height:13px; flex:0 0 auto; color:var(--a-faint); }

/* ---------- AN INLINE SVG WITH NO SIZE IS NOT AN ICON ----------
   altIcon() emits `<svg viewBox="0 0 24 24">` with no width and no height, so its rendered size
   is whatever CSS gives it — and where nothing did, it came out 0×0. Measured, not noticed: the
   plus on Add task, the group and sort icons, the magnifier in the filter box and EVERY group's
   disclosure chevron were all in the DOM, correct, and painting nothing at all. An icon set
   that is uniformly invisible looks exactly like a design that has no icons, which is why this
   survived several passes by eye.

   THE SHARED GAP WENT HOME. `.a-btn.icon.sm > svg` now lives with the primitive in
   CSS/alt/alt-components.css, so this file no longer answers for icon geometry — it had been
   answering for it, which is why the same Refresh control was 32×32 with a 15px glyph here and
   32×26 with a 12px glyph on the Calendar. What remains below is the two wrapped glyphs that
   carry their own deliberate size, plus the row rule above: a LABELLED `.a-btn.sm` raised to
   --a-ctl so the toolbar has one height and one middle. That row rule is this page's decision
   about its own row and is NOT a fact about icons — deleting it as "duplication" drops six
   labelled controls off that middle, which was measured before it was kept. */
.a-group-h .cv svg,.a-disc-h .cv svg{ width:14px; height:14px; }
.a-add-row .a-btn svg{ width:14px; height:14px; flex:0 0 auto; }

/* `.a-tabs` / `.a-tab` / `.a-tabs-end` MOVED TO alt-components.css. A tab strip has no page
   knowledge — no id in any of its selectors — and alt-okrs.css:37 already lists it among the
   primitives that "exist already and are EXTENDED here", which was only true on a page that
   happened to load THIS file. The admin console needs one too. */

/* ---------- the list ---------- */
/* THE LIST SCROLLS, NOT THE PAGE — so the tabs, the toolbar and the footer stay where the
   reader put them while the work moves under them. */
.a-list{ display:flex; flex-direction:column; flex:1 1 auto; min-height:0; overflow-y:auto; }
/* AND IT CAN NEVER BE NOTHING. `min-height:0` is what lets a flex child scroll instead of pushing
   its siblings off the page — and it is also what let this one be given zero: measured at
   1024x768, #altList computed to 0 and the first task row sat at y=849 in a 768px window. The
   regions above it are bounded now, each in its own rule above; this is the floor underneath all
   of them, so whatever is added to the chrome in future takes its space from the chrome and not
   from the reason the page exists. Roughly four rows. */
#altList{ min-height:200px; }
.a-group-h{
  display:flex; align-items:center; gap:9px; padding:12px 4px 7px; cursor:pointer;
  background:none; border:none; color:inherit; font:inherit; text-align:left; width:100%;
}
.a-group-h .cv{ transition:transform var(--a-quick) var(--a-ease); color:var(--a-faint); display:flex; }
.a-group-h[aria-expanded="false"] .cv{ transform:rotate(-90deg); }
.a-group-h b{ font-size:13px; font-weight:700; }
.a-group-h .n{ font-size:11px; color:var(--a-faint); background:var(--a-raised);
  border-radius:var(--a-r-pill); padding:1px 7px; font-variant-numeric:tabular-nums; }

/* THE OVERDUE HEADING IS RED, AND IT IS THE SAME RED AS EVERYTHING ELSE THAT MEANS LATE.

   Asked for by the product owner, 2026-09-25: "the overdue group should have a red header the
   same color as the overdue color within the chips at the top."

   `--a-red` IS THAT COLOUR, TAKEN FROM THE TOKEN RATHER THAN MATCHED BY EYE. The strip's
   Overdue tile is `.a-stat.warn b { color:var(--a-red) }` in alt-components.css, and a row's
   own late due date is `.a-row-due.late { color:var(--a-red) }` thirty lines below here. So the
   heading, the tile and the date now say "late" in one colour that changes in one place — and
   because it is a token it follows the theme, which a hex copied out of a screenshot would not.

   THE SELECTOR KEYS OFF `data-zone`, WHICH BOTH BUILDERS ALREADY SET. `altRenderList()`'s group
   builder and the drag-zone builder each do `wrap.dataset.zone = g.key` and each emit the label
   into `.lb`, so one rule covers both paths and neither needed a new class. `overdue` is an
   ALT_BUCKETS key, not a label, so this does not break if the wording ever changes.

   ONLY THE LABEL. The count chip beside it keeps the neutral treatment every other group's
   count has: a red pill next to a red word reads as an error badge rather than as a heading,
   and the owner asked for a red header rather than a red alarm. The chevron stays `--a-faint`
   for the same reason — it is a control affordance shared with every other group, and colouring
   it would say the CONTROL is the thing that is late. */
.a-group[data-zone="overdue"] > .a-group-h .lb{ color:var(--a-red); }
/* THE SAME CHIP AS EVERY OTHER LABEL ON THE ROW. It was a gold block with its own padding and
   its own margin, so one row in ten was taller than the rest and shouted louder than the status
   it sat beside. It is a fact about where the task came from, which is chip-sized. */
.a-note-line{
  display:inline-flex; align-items:center; gap:5px; padding:0 8px; height:20px;
  border-radius:var(--a-r-pill); border:1px solid var(--a-line-strong);
  background:none; color:var(--a-dim); font-size:11px; font-weight:500;
  cursor:pointer; white-space:nowrap;
}
.a-note-line:hover{ border-color:var(--a-blue); color:var(--a-blue-text); }
.a-note-line:focus-visible{ outline:2px solid var(--a-ring); outline-offset:1px; }

/* ---------- THE ROW: THREE LINES, AND NEVER A FOURTH ----------

   WHAT A ROW HAS TO ANSWER. What is this · what is it about · where does it live and who is on
   it. A list of titles alone is a list of filenames — two tasks called "Follow up with Kate" are
   two different jobs, and the sentence underneath is what separates them.

   THREE IS THE CEILING, and it is a hard one: the title, one ellipsed line of the description,
   and the facts. A row that can become four lines is a list where no two rows are the same
   height, which is the thing that stops a list scanning — the defect the Notes list already had
   and was fixed for. Every line below is single-line by construction, not by hoping the content
   is short.

   THE CONTROLS ALIGN TO THE FIRST LINE, not to the middle of a variable-height row: the
   checkbox, the date, the avatar and the star belong to the title, and centring them meant they
   drifted down as a description appeared. */
.a-row{
  display:flex; align-items:flex-start; gap:10px; min-height:var(--a-row);
  padding:7px 10px 7px 8px;
  border:1px solid transparent; border-left:3px solid transparent; border-radius:var(--a-r);
  background:var(--a-panel); margin-bottom:6px; cursor:pointer; position:relative;
}
/* 3px is the optical offset that lines a 19px control up with a 14px/1.35 first line. */
.a-row > .a-check,.a-row > .a-row-due,.a-row > .a-assign-badge,.a-row > .a-av,.a-row > .a-star,.a-row > .a-more{
  margin-top:3px;
}
.a-row:hover{ border-color:var(--a-line); background:var(--a-raised); }
/* ---------- A ROW ARRIVING BECAUSE THE READER NARROWED THE LIST ----------

   THE PRIMITIVE IS `.card.card-enter` IN CSS/components.css AND IT COULD NEVER REACH THIS PAGE.
   Nothing in the suite draws a `.card` — the rows are `.a-row` — so `altAnimateFilterOnce()` and
   `altApplyFilterEntrance()` in JS/alt/alt-tasks.js were arming a class that matched no rule.
   The feature existed, the class landed on the element, and not one pixel moved. That is the
   worst shape a defect can take, because everything about it looks finished.

   THE ANIMATION IS THE SHARED ONE, NOT A COPY OF IT. `@keyframes cardIn` is declared at the TOP
   LEVEL of CSS/components.css — verified at brace depth 0, so it is document-global rather than
   scoped to the `.card` rule it sits beside — and every suite page loads that file. So this rule
   names the existing keyframe and adds nothing: the 4px rise and the fade have one definition,
   and retuning them retunes both applications. A second `@keyframes cardIn` here would be one
   animation with two bodies to keep in step, which is the drift this file is careful about.

   `--dur-quick` AND `--ease-out`, which is what the classic rule uses and what the design system
   gives "a card arriving" (§2b). The per-item delay is NOT here: it is `motionStaggerMs(i)`,
   written inline by altApplyFilterEntrance(), because a capped stagger is arithmetic over the
   tokens and JS/core/motion.js is the only place timing is computed.

   IT RUNS ON A FILTER CHANGE AND NOWHERE ELSE. altRenderList() reads and clears the flag at the
   top before any early return, so a save, a boot, a poll or a re-render paints the rows where
   they already are. `both` fill so a row is at opacity 0 during its delay and stays where it
   lands.

   THE @media BLOCK IS NOT REDUNDANT, AND THIS IS THE ONE PLACE IN MY WORK WHERE THE TOKEN IS NOT
   ENOUGH. Zeroing `--dur-quick` would settle the DURATION, but the DELAY is an inline style
   written by script, and an inline style beats a media-query rule that is not `!important`.
   `motionStaggerMs()` already returns 0 under the preference, so today the two agree — this is
   what keeps them agreeing if that ever changes, and it is exactly why the classic rule carries
   the same pair. 1ms rather than 0s, matching `.card.card-enter`, which is also the contract
   altApplyFilterEntrance()'s own comment was written against. With `both` at 1ms the row still
   ends at opacity 1: the travel goes, the content never does. */
.a-row.card-enter{ animation:cardIn var(--dur-quick) var(--ease-out) both; }
@media (prefers-reduced-motion: reduce){
  .a-row.card-enter{ animation-duration:1ms !important; animation-delay:0ms !important; }
}
.a-row:focus-visible{ outline:2px solid var(--a-ring); outline-offset:1px; }
.a-row.sel{ border-color:var(--a-blue); background:var(--a-blue-soft); }
/* ---------- THE ROW THAT WAS JUST CREATED ----------
   A new task is placed by its DATE, so it often lands below the fold — altFlashRow() (alt-tasks.js)
   brings it to the reader with a single pulse, deliberately not a selected state (a row still
   ringed a minute later stops meaning "this is the one you just made"). Animates `box-shadow`,
   the one property `.a-row.sel` isn't already using, so it composes with selection instead of
   fighting it — a shadow rather than a border keeps the row's size so the list does not shift.
   `--dur-flash` is the shared token the team board reads too. */
@keyframes altRowNew{
  0%   { box-shadow:0 0 0 2px var(--a-blue); }
  70%  { box-shadow:0 0 0 2px var(--a-blue); }
  100% { box-shadow:0 0 0 2px transparent; }
}
.a-row.is-new{ animation:altRowNew var(--dur-flash) var(--ease-out) 1; }
/* Somebody who asked for less motion asked not to be animated at, NOT to be left hunting for
   the row they just made — so the pulse becomes a plain ring, and altApplyRowFlash()'s timer
   backstop is what takes it away again, because `animation:none` fires no animationend. */
@media (prefers-reduced-motion: reduce){
  .a-row.is-new{ animation:none; box-shadow:0 0 0 2px var(--a-blue); }
}
.a-row.done .a-row-t{ text-decoration:line-through; color:var(--a-faint); }
.a-row.readonly{ opacity:.85; }
/* The left edge carries the row's status colour — the wireframe's coloured rule. */
.a-row.k-active{ border-left-color:var(--a-blue); }
.a-row.k-blocked{ border-left-color:var(--red); }
.a-row.k-hold{ border-left-color:var(--yellow); }
.a-row.k-monitor{ border-left-color:var(--purple); }
.a-row.k-complete{ border-left-color:var(--green); }
.a-row.k-todo{ border-left-color:var(--a-line-strong); }
.a-check{
  width:19px; height:19px; flex:0 0 auto; border-radius:50%; cursor:pointer;
  border:2px solid var(--a-line-strong); background:transparent; padding:0;
  display:inline-flex; align-items:center; justify-content:center; color:transparent;
}
.a-check:hover{ border-color:var(--a-green); }
.a-check.on{ background:var(--green); border-color:var(--green); color:#fff; }
.a-check:focus-visible{ outline:2px solid var(--a-ring); outline-offset:2px; }
.a-row-t{ flex:1 1 auto; min-width:0; font-size:14px; line-height:1.35; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
/* One line of what the task says. `min-width:0` is load-bearing on a flex child — without it the
   box is sized by its text and the ellipsis never happens. */
.a-row-desc{
  min-width:0; max-width:100%; font-size:12px; line-height:1.4; color:var(--a-dim);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.a-row.done .a-row-desc{ color:var(--a-faint); }
/* NOWRAP, AND IT CLIPS. Wrapping would make this the fourth and fifth lines of the row. What
   does not fit is still on the task, one click away, and the order is fixed so what gets clipped
   is always the least important end. */
.a-row-meta{
  display:flex; align-items:center; gap:6px; flex-wrap:nowrap;
  min-width:0; max-width:100%; overflow:hidden;
}
.a-row-meta > *{ flex:0 0 auto; }
/* Its own box so COMPACT can keep the tags and drop the rest — see the density block in
   alt-shell.css. Compact is a density, not a smaller amount of truth about a task. */
.a-row-tags{ display:flex; align-items:center; gap:6px; min-width:0; overflow:hidden; }
.a-chip.quiet{ color:var(--a-dim); }
/* ---------- WHY THIS ROW IS IN WATCHING — THE ONE CHIP THAT IS A SENTENCE ----------
   Every other `.a-chip` on the row is a NOUN (a status, a tag, a board) — this one is a SENTENCE
   from a closed set of three (altWatchReasonLabel(), alt-tasks.js), so the usual 170px noun cap
   truncated away the word that carries its meaning. 212px clears the widest of the three labels
   across all ten application fonts (sys_design-system.md §1e). `flex:0 1 auto; min-width:0` lets
   it alone absorb row overflow (the strip is otherwise `nowrap`/`flex:0 0 auto`), turned into an
   ellipsis by `.a-chip .lb` instead of a hard cut — same shape as `.completed-row .cmeta` in
   CSS/components.css. No Compact exemption: unlike the repeat/reminder/comment chips, this one
   doesn't name an ongoing commitment. A 88px floor keeps the three labels tellable apart even
   while shrinking; below that the row's own clip takes over instead. */
.a-chip-watchreason{ max-width:212px; flex:0 1 auto; min-width:88px; }
/* The recurrence marker. `.a-chip` is inline-flex and gives a direct `<svg>` child no size
   (altIcon() emits a viewBox with no width/height) — sized here, 12px for this pill's scale. */
.a-chip-rep > svg{ width:12px; height:12px; flex:0 0 auto; }
/* Compact keeps this one marker (glyph only, label dropped) — a repeat says the row will come
   BACK, which a density cannot make less true, unlike a tag or a date. */
body.a-compact .a-row-meta > .a-chip-rep{ display:inline-flex; }
body.a-compact .a-chip-rep .l{ display:none; }
/* The reminder marker — same three rules as the repeat marker, for the same reason: a reminder
   says this row will email somebody, so Compact keeps the glyph and drops the word. */
.a-chip-rem > svg{ width:12px; height:12px; flex:0 0 auto; }
body.a-compact .a-row-meta > .a-chip-rem{ display:inline-flex; }
body.a-compact .a-chip-rem .l{ display:none; }
/* The comment count — same hook, one fewer moving part: it was always icon+bare-number
   (altIcon('comment') + the count, alt-tasks.js), so there's no label to hide in Compact. An
   unread reply is a fact about the task, not a decoration Compact may drop. */
.a-chip-cm > svg{ width:12px; height:12px; flex:0 0 auto; }
body.a-compact .a-row-meta > .a-chip-cm{ display:inline-flex; }
/* The envelope chip — "this task came from an email" (alt-tasks.js's altTaskRow()). Same sizing
   fix as its neighbours above. NOT exempted from Compact, unlike the other three: it states a
   fact about arrival, the same kind of fact as a tag or board name, which Compact already drops. */
.a-chip-eml > svg{ width:12px; height:12px; flex:0 0 auto; }
.a-chip.okr{ border-color:var(--a-purple, var(--purple)); color:var(--a-text); font-weight:600; }
/* ---------- THE ACTION ZONE IS THE SAME WIDTH ON EVERY ROW ----------
   Each of these is a fixed track, not a box sized by its own content — a row with a date and an
   avatar once left its title 60px short of the row above it, so no two titles ended in the same
   place. `flex:0 0 <w>` on all four; the avatar's slot is drawn even unassigned, since a column
   that only sometimes exists moves everything beside it. */
/* The date is a <button> now but keeps its old track — the button reset (font/padding/border/
   background) is what stops titles starting in different places; it reads as text until pointed
   at, like `.a-star`/`.a-more` one track over. alt-notes.js/alt-team-board.js draw the same class
   as a <span>; the hover/focus rules are scoped to `button.a-row-due` so neither is affected. */
/* 84px, left-aligned: measured against the widest real string ("Wed, Sep 30" needs 73px) plus an
   11px slack for a wider glyph or fallback font — sizing to the exact measured width with nothing
   to spare has already ellipsed a date column once elsewhere. Left, not right, because right
   alignment put every date's edge in a different place and read as ragged in a fixed track;
   asked for directly: "make sure the left of the date all aligns left". */
.a-row-due{ flex:0 0 84px; font-size:12px; color:var(--a-dim); white-space:nowrap;
  min-width:84px; text-align:left; overflow:hidden; text-overflow:ellipsis; }
button.a-row-due{ font:inherit; font-size:12px; padding:0; border:none; background:none;
  cursor:pointer; border-radius:var(--a-r-sm); }
button.a-row-due:hover{ color:var(--a-blue-text); text-decoration:underline; }
button.a-row-due:focus-visible{ outline:2px solid var(--a-ring); outline-offset:1px; }
.a-row-due.late{ color:var(--a-red); font-weight:600; }
/* The date field the row's "Pick a date…" opens, drawn over the pill it came from. Fixed,
   because the list scrolls inside a box with overflow hidden and anything positioned inside a
   clipped ancestor is clipped with it. Its z-index is above the menu it replaces. */
.a-due-pick{
  position:fixed; z-index:520; height:24px; padding:1px 4px; font:inherit; font-size:12px;
  color:var(--a-text); background:var(--a-panel); border:1px solid var(--a-blue);
  border-radius:var(--a-r-sm); box-shadow:var(--a-shadow-lg);
}
/* ---------- THE "ASSIGNED BY SOMEONE ELSE" BADGE — BETWEEN THE DATE AND THE AVATAR ----------
   Owner's own placement: "put the icon between the date and the assigned-to chip." A fixed
   track like its neighbours, so this badge's presence never shifts the avatar after it. Built by
   taskAssignedBadgeEl() (JS/components/task-row.js) — never returns null; `.none` is
   `visibility:hidden`, not removed, so the track and the columns after it never move. */
.a-row > .a-assign-badge{
  flex:0 0 20px; display:inline-flex; align-items:center; justify-content:center;
  color:var(--a-dim);
}
.a-assign-badge.none{ visibility:hidden; }
/* Same zero-size defect as `.a-more`/`.a-chip-rep`/`.a-chip-rem` svgs — 14px, between `.a-more`'s
   15 and a chip's 12, since this is a bare glyph with no pill around it. */
.a-assign-badge > svg{ width:14px; height:14px; flex:0 0 auto; }
.a-row > .a-av{ flex:0 0 24px; }
.a-av.none{ visibility:hidden; }
.a-star{ background:none; border:none; cursor:pointer; color:var(--a-line-strong); padding:2px;
  display:inline-flex; flex:0 0 22px; justify-content:center; border-radius:var(--a-r-sm); }
.a-star.on{ color:var(--a-gold); }
.a-star:hover{ color:var(--a-gold); }
.a-star:focus-visible{ outline:2px solid var(--a-ring); outline-offset:1px; }
.a-more{ background:none; border:none; cursor:pointer; color:var(--a-faint); padding:2px 4px;
  display:inline-flex; flex:0 0 26px; justify-content:center; border-radius:var(--a-r-sm); }
.a-more:hover{ color:var(--a-text); background:var(--a-raised); }
/* ---------- THE ADD ROW, DECLARED ONCE ----------
   `+ Add task` sat off-centre because two different components (the board's <button>, the task
   list's <div> wrapping two `.a-btn ghost sm`) wore this one class and it was declared twice,
   the second overriding both with asymmetric padding. One declaration now, `8px 12px`, symmetric
   vertically by construction. */
.a-add-row{
  display:flex; align-items:center; gap:8px; padding:8px 12px; margin-bottom:6px;
  border:1px dashed var(--a-line); border-radius:var(--a-r); color:var(--a-faint);
  background:none; font:inherit; font-size:13px; cursor:pointer; width:100%; text-align:left;
}
.a-add-row:hover{ border-color:var(--a-blue); color:var(--a-blue-text); }
.a-add-live{ display:flex; align-items:center; gap:8px; margin-bottom:6px; flex-wrap:wrap; }
.a-add-live .a-input{ flex:1 1 auto; border-color:var(--a-blue); }
.a-list-foot{
  display:flex; align-items:center; gap:10px; padding:10px 4px 0; margin-top:4px;
  border-top:1px solid var(--a-line-soft); font-size:12px; color:var(--a-faint);
}
.a-list-foot .a-bar{ flex:0 0 120px; }
/* THE "N/M today" TEXT, MADE INTO A BUTTON — altRenderListFoot() (JS/alt/alt-tasks.js). Reset
   to plain text sitting in its row rather than restyled as a chip: the owner pointed at the
   EXISTING figure, and the only thing that changed about it is that it now does something.
   `font-family` is left alone on purpose — `.a-mono` (CSS/alt/alt-components.css) still owns it,
   and setting it again here would only ever fight that rule for no reason. */
.a-list-foot-done{
  background:none; border:none; padding:0; margin:0; font-size:inherit; color:inherit;
  cursor:pointer; border-radius:4px;
}
.a-list-foot-done:hover{ color:var(--a-text); text-decoration:underline; }
.a-list-foot-done:focus-visible{ outline:2px solid var(--a-ring); outline-offset:2px; }

/* ---------- the left column: one task, and the whole height of the page ----------
   The column is the panel now — it used to stack three cards and scroll as a column, so the
   drawer grew to its own content and nested a scrollbar inside a scrollbar. With one child, the
   panel fills the column and its BODY scrolls instead. By id, because `.a-left` is also the
   notes page's groups-and-list column, which is still a stack that scrolls together. */
#altLeft{ overflow:hidden; }
#altLeft > .a-drawer{ flex:1 1 auto; min-height:0; }

/* ---------- task details drawer ---------- */
.a-drawer{ display:flex; flex-direction:column; min-height:0; background:var(--a-panel);
  border:1px solid var(--a-line-soft); border-radius:var(--a-r-lg); overflow:hidden; }
.a-drawer-h{ display:flex; align-items:center; gap:8px; padding:10px 12px;
  border-bottom:1px solid var(--a-line-soft); background:var(--a-float); flex:0 0 auto; }
/* ---------- THE ACTIONS ROW SITS ABOVE THE TITLE ----------
   `.stack` rather than a change to `.a-drawer-h` itself — the EMPTY state's header is still one
   row, and turning the shared rule into a column would stack those two for no reason. The title
   keeps the panel's full width; six icon buttons sharing its line would ellipsis a long name. */
.a-drawer-h.stack{ flex-direction:column; align-items:stretch; gap:8px; }
.a-drawer-h-acts{ display:flex; align-items:center; gap:2px; }
/* This row's glyphs are smaller than the top bar's — a row decision, not a redefinition of
   `.a-btn.icon` (alt-components.css draws the same boundary around `#altControls .a-btn.sm`).
   22px, not the top bar's 30: eight icon-only actions packed above a title read oversized at 30,
   and 22 is lighter without dropping to the toolbar's other 15px tier. The button box (32px) is
   untouched, so the hit target doesn't move, only the glyph. Covers the watch/mail pair too —
   `#dWatchActions` shares this row's classes (JS/alt/alt-drawer.js). */
.a-drawer-h-acts .a-btn.icon > svg{ width:22px; height:22px; flex:0 0 auto; }
/* Two groups: star/complete/delete on the left, the watch pair and more/expand/close on the
   right, pushed apart by the right group's own `margin-left:auto` (replacing a now-removed empty
   spacer span). `#dWatchActions` is always emitted, even empty, so this holds either way. */
.a-drawer-h-acts > .ph-right{ margin-left:auto; }
/* ---------- THE SAVE STATE, ON ITS OWN LINE UNDER THE TITLE ----------
   PRODUCT OWNER: "move the status update saving the task just under the task title and above
   the tabs. this way it is not cut off and the user can see it more directly." `#dSaveNote` is
   the last child of `.a-drawer-h.stack`, between the title and the tabs — moved out of the icon
   row because sharing it meant "All changes saved · 5:53 PM" got whatever width was left over
   and ellipsised on a narrow column. Left-aligned (text length changes as it goes idle → Saving…
   → Saved, so centring would slide under the reader's eye) and takes no space until `:empty` no
   longer matches. The ellipsis is a guard against a future longer string, not the normal case. */
.a-drawer-h.stack > .save-status{
  min-width:0; margin:0; text-align:left;
  font-size:12px; line-height:1.3; color:var(--a-dim);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.a-drawer-h.stack > .save-status:empty{ display:none; }
/* The component writes into a child span when showing dots (JS/components/processing.js), so
   the ellipsis must apply inside it too — same rule CSS/components.css states elsewhere. */
.a-drawer-h.stack > .save-status .proc{ overflow:hidden; text-overflow:ellipsis; max-width:100%; }
/* Restated rather than inherited: CSS/components.css's `.cfg-status.ok/.err` carry equal cascade
   weight but load before this stylesheet, so without this a settled save rendered dim here while
   green elsewhere. Same tokens, just restated to win the load order. */
.a-drawer-h.stack > .save-status.ok{ color:var(--green-text); }
.a-drawer-h.stack > .save-status.err{ color:var(--red-text); }
/* Keyed off `aria-pressed`, not a `.on` class — state can't be visually true and semantically
   false, and `.a-btn.on` is the toolbar's solid-blue toggle, wrong for a star. Fills gold/green,
   the same colours the row's own star and completion already use. */
.a-drawer-h-acts #dStar[aria-pressed="true"]{ color:var(--a-gold); }
.a-drawer-h-acts #dComplete[aria-pressed="true"]{ color:var(--green); }
/* Delete is quiet until pointed at — `.a-btn.danger`'s red border (alt-components.css) would
   otherwise paint a permanent alarm in every task's header for no reason. */
.a-drawer-h-acts .a-btn.danger{ color:var(--a-faint); border-color:transparent; background:transparent; }
.a-drawer-h-acts .a-btn.danger:hover,
.a-drawer-h-acts .a-btn.danger:focus-visible{ color:var(--a-red); background:var(--a-red-soft); }
/* The empty state's header says what the panel is, so an empty column reads as a panel waiting
   rather than as something that failed to draw. */
.a-drawer-h-t{ flex:1 1 auto; min-width:0; font-family:var(--a-display); font-size:13px;
  font-weight:600; color:var(--a-dim); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* ---------- THEY ARE TABS, SO THEY LOOK LIKE TABS ----------
   A tab strip with a rule under it and the active tab sitting ON that rule says "there is more
   behind these", rather than reading as a segmented control. Padding matches the header above —
   fixing "the details button is too close to the edge" (3px of tray vs 12px of everything else). */
/* It scrolls sideways: measured at 390px, five of nine tabs sat past the strip's right edge with
   no way to reach them (`overflow-x:visible`, `scrollLeft` pinned, card `overflow-x:hidden`) —
   the strip is their only route in. Same answer the OKR drawer already gives (alt-okrs.css
   `.a-okr-drawer-h .a-tabs`): the scrollbar is hidden (a thin bar under tabs reads as a fault,
   not an affordance) and a mask fades the edge to signal "more this way" instead. `nowrap` stays,
   since a second row would move the card's body down and read as two groups of tabs; keyboard
   Tab still reaches every button and the strip scrolls to follow focus. */
.a-drawer-tabs{
  display:flex; gap:2px; padding:0 12px; flex:0 0 auto;
  background:var(--a-float); border-bottom:1px solid var(--a-line);
  flex-wrap:nowrap; overflow-x:auto; overscroll-behavior-x:contain; scrollbar-width:none;
}
.a-drawer-tabs::-webkit-scrollbar{ display:none; }
/* Without this the buttons shrink to fit instead of overflowing, and the labels truncate — the
   same width problem wearing different clothes. */
.a-drawer-tabs > button{ flex:0 0 auto; }
.a-drawer-tabs{
  padding-right:var(--a-5);
  -webkit-mask-image:linear-gradient(to right, #000 calc(100% - 28px), transparent);
  mask-image:linear-gradient(to right, #000 calc(100% - 28px), transparent);
}
@media print{
  .a-drawer-tabs{ -webkit-mask-image:none; mask-image:none; }
}
.a-drawer-tabs button{
  position:relative; height:34px; padding:0 12px; border:0; background:none;
  color:var(--a-dim); font:inherit; font-size:13px; font-weight:600;
  cursor:pointer; white-space:nowrap; border-radius:var(--a-r-sm) var(--a-r-sm) 0 0;
}
.a-drawer-tabs button:hover{ color:var(--a-text); background:var(--a-raised); }
.a-drawer-tabs button:focus-visible{ outline:2px solid var(--a-ring); outline-offset:-2px; }
/* The active tab is blue AND underlined: colour alone is never the signal, and the rule joining
   it to the panel below is what makes the pair read as one surface. */
.a-drawer-tabs button[aria-selected="true"]{ color:var(--a-blue-text); background:var(--a-panel); }
.a-drawer-tabs button[aria-selected="true"]::after{
  content:''; position:absolute; left:0; right:0; bottom:-1px; height:2px;
  background:var(--a-blue); border-radius:2px 2px 0 0;
}
.a-drawer-b{ flex:1 1 auto; min-height:0; overflow:auto; padding:var(--a-3) 12px var(--a-4);
  display:flex; flex-direction:column; gap:var(--a-3); }
/* Matched to `.a-note-title` (alt-notes.css): 19px/600/1.3 on `var(--a-display)`. Border is
   `--border-strong` (3.00, WCAG 1.4.11), not `--a-line` — this is `role="textbox"`, a control,
   same as its two title-field siblings. Single row, always: `white-space:nowrap` makes it
   structural rather than a hope, since this `contenteditable` div (unlike an `<input>`) would
   otherwise wrap. Overflow scrolls (`overflow-x:auto`), never clips or ellipses, so nothing
   typed is ever unreachable; the scrollbar is hidden the same way `.a-drawer-tabs` hides its own. */
.a-drawer-title{
  /* 19px -> 17px, PRODUCT OWNER: "reduce the font by 2 pts, its just slightly too big for the
     edit panel." Does not touch the single-row contract above — smaller only ever means more of
     a long title fits before it scrolls. Do not restore to 19px without asking. */
  width:100%; font-family:var(--a-display); font-size:17px; font-weight:600; line-height:1.3;
  background:var(--a-bg); border:1px solid var(--a-line-strong); border-radius:var(--a-r-sm);
  color:var(--a-text); padding:8px 10px;
  white-space:nowrap; overflow-x:auto; overflow-y:hidden; scrollbar-width:none;
}
.a-drawer-title::-webkit-scrollbar{ display:none; }
.a-two{ display:grid; grid-template-columns:1fr 1fr; gap:10px; }
.a-three{ display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; }
.a-disc{ border-top:1px solid var(--a-line-soft); padding-top:10px; }
.a-disc-h{
  display:flex; align-items:center; gap:7px; width:100%; padding:0 0 8px; background:none;
  border:none; color:var(--a-dim); font:inherit; font-size:10px; font-weight:700;
  letter-spacing:.09em; text-transform:uppercase; cursor:pointer; text-align:left;
}
.a-disc-h .cv{ transition:transform var(--a-quick) var(--a-ease); display:flex; }
.a-disc-h[aria-expanded="false"] .cv{ transform:rotate(-90deg); }
.a-disc-h .sum{ margin-left:auto; text-transform:none; letter-spacing:0; font-weight:500;
  color:var(--a-dim); font-size:11px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:55%; }
.a-disc-b{ display:flex; flex-direction:column; gap:10px; padding-bottom:4px; }
.a-disc[data-open="false"] .a-disc-b{ display:none; }

/* ---------- THE FOLLOW-UP ROW COLLAPSES WHEN IT HAS NOTHING TO SHOW ----------
   PRODUCT OWNER: "Remove the follow up email label. Just having the draft email follow up is
   sufficient." `#dFollowupField` can end up empty two ordinary ways (the card adopted its button
   onto a saved-message card, or no assistant is configured and `.ai-unavailable` hides it) — one
   `:has()` selector covers both without the drawer needing to be told which happened, same
   approach as `#followupField:has(...)` in CSS/task-editor-panel.css. */
#dFollowupField:not(:has(button:not(.ai-unavailable))){ display:none; }
.a-rte{
  min-height:120px; max-height:340px; overflow:auto; padding:10px;
  background:var(--a-bg); border:1px solid var(--a-line); border-radius:var(--a-r-sm);
  font-size:13px; line-height:1.55; color:var(--a-text);
}
.a-rte:focus{ outline:none; border-color:var(--a-blue); }
.a-drawer-f{ flex:0 0 auto; padding:8px 12px; border-top:1px solid var(--a-line-soft);
  display:flex; align-items:center; gap:8px; font-size:11px; color:var(--a-faint); }

/* The repeat selector and its "i", on one line: the control
   takes the room, the affordance stays its own width, `.a-btn.icon.sm` lines up with the
   select's height and clears the 24px pointer floor. */
.a-recur-row{ display:flex; align-items:center; gap:6px; }
.a-recur-row .a-select{ flex:1 1 auto; min-width:0; }
.a-recur-row .a-btn{ flex:0 0 auto; color:var(--a-faint); }
.a-recur-row .a-btn:hover,
.a-recur-row .a-btn[aria-expanded="true"]{ color:var(--a-blue-text); background:var(--a-raised); }

/* A description bubble, not a menu and not a dialog — wears `.a-menu`'s float treatment with two
   differences: `position:fixed` (placed from the anchor's own rect; absolute would clip inside
   the drawer's scroller), and no authored z-index (openPopover() writes layerNextZ() inline,
   the only answer that knows what this opens on top of — the `.a-due-pick` finding repeated). */
.a-info-pop{
  /* `width`, not `max-width` — a fixed element with `width:auto` is shrink-to-fit against its
     STATIC position, which at 390px rendered this as a 110px column 568px tall; an explicit
     width is the same number at every viewport and every stage of placement. */
  position:fixed; width:min(320px, 92vw); padding:10px 12px;
  background:var(--a-float); border:1px solid var(--a-line-strong); border-radius:var(--a-r);
  box-shadow:var(--a-shadow);
  font-size:13px; line-height:1.5; color:var(--a-text);
}
.a-tagpick{ display:flex; flex-wrap:wrap; gap:5px; }
.a-tagpick .a-chip{ cursor:pointer; }
.a-attach{ display:flex; flex-direction:column; gap:6px; }
/* The conversation is styled in alt-conversation.css, not here — this file declared
   `.a-comments`/`.a-comment` twice, disagreeing with itself, and notes.html inherited whichever
   copy won. One component, one home, prefixed `.alt-app` there. */

/* ---------- pieces the row and the drawer name ---------- */
.a-row-main{ flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:3px; }
/* The title is a button and must not look like one — it SELECTS on a single click like the rest
   of the row and no longer opens anything on its own (see the row's `dblclick` listener in
   alt-tasks.js), so the old hover underline read as a link to somewhere else and fired on every
   row the pointer passed over. `.a-row:hover` above is the row's real affordance now. */
button.a-row-t{
  background:none; border:0; padding:0; margin:0; text-align:left; color:inherit; font:inherit;
  cursor:pointer; width:100%;
}
button.a-row-t:focus-visible{ outline:2px solid var(--a-ring); outline-offset:2px; border-radius:3px; }
.a-empty-a{ display:flex; gap:var(--a-2); justify-content:center; margin-top:12px; }
/* --a-blue-text, not --a-blue. The fill colour is for a shape; on a panel at 11px it measures
   4.05:1 against the surface behind it, under the 4.5 the design system requires for text.
   The text variant exists for exactly this and measures 5.93. */
.a-chip.unread{ border-color:var(--a-blue); color:var(--a-blue-text); font-weight:600; }
/* Plain background first — dropped, the attachment drop zone gives no drag-over feedback
   at all. --a-blue-soft is the same tint at a fixed alpha. */
.a-attach.over{ border-color:var(--a-blue); background:var(--a-blue-soft); background:color-mix(in srgb, var(--a-blue) 10%, transparent); }

/* ---------- a group in the list ---------- */
.a-group{ display:flex; flex-direction:column; gap:2px; }
.a-group + .a-group{ margin-top:6px; }
/* ---------- A GROUP WITH NOTHING IN IT IS A DROP TARGET AND NOTHING ELSE ----------
   "Overdue 0"/"No date 0" each drew a full header and affordance above a list with no room left
   — a group exists so there's somewhere to drop into, which only matters while dragging.
   `a-dragging-on` goes on the body at dragstart, before the first dragover can fire. */
.a-group.vacant{ display:none; }
body.a-dragging-on .a-group.vacant{ display:flex; }
body.a-dragging-on .a-group.vacant .a-group-h{ padding:5px 4px; color:var(--a-faint); }
body.a-dragging-on .a-group.vacant .a-group-h b,
body.a-dragging-on .a-group.vacant .a-group-h .lb{ font-size:12px; font-weight:600; }
.a-seg-ctl{ display:inline-flex; gap:2px; padding:2px; border-radius:var(--a-r);
  background:var(--a-raised); border:1px solid var(--a-line-soft); }
.a-tab.sm{ height:26px; padding:0 9px; font-size:12px; }
/* ---------- AND THE CHOSEN HALF HAS TO LOOK CHOSEN ----------
   `.a-seg-ctl` had no active-button rule at all — `.a-tab` only lights on
   `[aria-selected="true"]`, but both segmented controls here mark current with `.on`, so the
   halves rendered identically. A raised chip, not the tab's underline: this is a segmented
   control inside a tray, not a tab strip. */
.a-seg-ctl > .a-tab{ height:24px; border-bottom:none; border-radius:calc(var(--a-r) - 2px); }
.a-seg-ctl > .a-tab:hover{ color:var(--a-text); background:var(--a-panel); }
.a-seg-ctl > .a-tab.on{ color:var(--a-text); background:var(--a-panel);
  box-shadow:0 1px 2px rgba(0,0,0,.10); font-weight:600; }
.a-seg-ctl > .a-tab:focus-visible{ outline:2px solid var(--a-ring); outline-offset:-2px; }
.a-btn .n{ margin-left:5px; font:600 10px/1 var(--a-mono); opacity:.8; }
/* An empty group or section says so, quietly, and is still a drop target. */
.a-col-empty{ padding:8px 6px; text-align:center; }
/* The composer row: the primary way to add on the left, the others behind one control. The box
   itself is declared once, above — this block is deliberately only the composer's additions. */
/* Hidden means unclickable — an invisible button inside a row that's now a whole hit target
   would be a trap. Hover and keyboard focus both reveal it and hand its clicks back together. */
.a-add-more{ opacity:0; pointer-events:none; transition:opacity var(--a-quick) var(--a-ease); }
.a-add-row:hover .a-add-more,.a-add-more:focus-visible{ opacity:1; pointer-events:auto; }
.a-add-live .a-input:first-child{ flex:1 1 200px; min-width:140px; }

/* ---------- the conversation, in this design's clothes ----------
   It was the canonical comment markup with none of this design's typography on it: a wall of
   body-sized text with no separation between one person's remark and the next. */
.a-conv{ display:flex; flex-direction:column; gap:var(--a-3); min-height:0; }
.a-conv .a-composer{
  margin-top:var(--a-2); padding-top:var(--a-3); border-top:1px solid var(--a-line-soft);
}

/* ---------- where it lives ----------
   The smallest thing on the tab, set at the smallest size. It was `.a-mono` at the inherited
   body size, which made three dates the loudest text on the panel. */
.a-meta{ display:flex; flex-direction:column; gap:3px; }
.a-meta-row{ display:flex; align-items:baseline; gap:8px; font-size:12px; }
.a-meta-row .k{ flex:0 0 88px; color:var(--a-faint); }
.a-meta-row .v{
  flex:1 1 auto; min-width:0; color:var(--a-dim);
  font-family:var(--a-mono); font-size:11px; overflow-wrap:anywhere;
}
@media (prefers-reduced-motion: no-preference){
  .a-analytics{ transition:outline-color var(--a-quick) var(--a-ease); }
}

/* ================= MOTION: THE MICRO RESPONSE =================
   Parity with the classic application's `.micro` primitive (CSS/components.css: transform on
   --ease-move, colour/opacity linear, all on --dur-micro) — the token is shared, the selectors
   are this page's, since nothing in JS/alt/ emits the `micro` class itself. `--dur-micro`
   (140ms), not `--a-quick`: past ~150ms a hover reads as lag, which is why it skipped the +200ms
   the travel durations took (sys_design-system.md §2b) — a disclosure or a hover-revealed
   control like `.a-add-more` is travel, not response, and keeps `--a-quick`. No layout property
   is in this list — only what actually changes. Reduced motion is answered at the token
   (alt-tokens.css zeroes `--dur-micro` on `.alt-app`), so no @media block is needed here. */
.a-row,
.a-check,
.a-note-line,
.a-add-row,
button.a-row-due,
.a-star,
.a-more,
.a-drawer-tabs button,
.a-drawer-h-acts .a-btn.danger{
  transition:background-color var(--dur-micro, 140ms) linear,
             border-color     var(--dur-micro, 140ms) linear,
             color            var(--dur-micro, 140ms) linear,
             opacity          var(--dur-micro, 140ms) linear;
}

/* ---------- THE SECOND FIGURE ON A TAB ----------
   `.a-tab .n` is the total (alt-components.css); this is the overdue count beside it, a badge of
   its own rather than a colour on the total, so a total turning amber never implies "wrong"
   rather than "how much". The tab's aria-label carries the word "late" too, not colour alone. */
.a-tab .n.late{
  margin-left:4px; padding:0 5px; border-radius:9px;
  font-size:10px; font-weight:700; letter-spacing:.2px;
  color:var(--a-amber); background:var(--a-amber-soft);
}

/* ---------- THE EMAILED TAB'S ATTENTION STATE ----------
   PRODUCT OWNER: "The system shall color the tab to 'Yellow' with the count so it will draw the
   user's attention to review the emails inbound that need to be accepted or rejected." `.attn`
   is added by `tabsHtml` (alt-tasks.js) only once the emailed count is known and > 0. Tokens,
   not a hardcoded yellow: `--a-amber`/`--a-amber-soft` are the same pair `.n.late` and `.a-heavy`
   use, since plain `--yellow` reads ~3.1:1 as text (below the AA floor). Not colour alone — the
   badge keeps its own wash and the aria-label prepends "Needs review: ". */
.a-tab.attn,
.a-tab.attn:hover{ color:var(--a-amber); }
.a-tab.attn .n{
  padding:0 5px; border-radius:9px;
  font-size:10px; font-weight:700; letter-spacing:.2px;
  color:var(--a-amber); background:var(--a-amber-soft);
}

/* ================= THE HEAVY DAY ================= */
/* A day with more on it than the reader said they wanted, said where the day is — see
   `tasks.heavyDayThreshold`. Tokens, not a hardcoded amber: --a-amber/--a-amber-soft measure
   correctly in both themes where a mid-tone accent picked for one panel would not. Not colour
   alone — the ⚠ and the sentence carry it; the wash is a third signal, not the only one. */
.a-heavy{
  display:flex; align-items:flex-start; gap:6px;
  margin:2px 4px 6px; padding:6px 10px;
  font-size:12px; line-height:1.45; color:var(--a-amber);
  background:var(--a-amber-soft); border:1px solid var(--a-amber-soft);
  border-radius:var(--a-r);
}
.a-heavy .m{ flex:1 1 auto; min-width:0; }
/* The mark is decoration for a reader who can see it and noise for one who cannot — the
   sentence beside it already says "more than you asked for". */
.a-heavy .i{ flex:0 0 auto; }
/* AT THE HEAD OF THE LIST rather than inside a group, which is where it goes when the reader
   has grouped by something that has no Today in it. Same box, more room around it. */
.a-list > .a-heavy{ margin:0 0 8px; }

/* The double-click hint moved into `.a-toolbar-hint` above the list (TASKS-TOOLBAR-CONTRACT.md's
   footer) — the line inside the list (`.a-list > .a-list-hint`) is retired, not duplicated; LANE
   JS drops the matching element in the same change. */

/* ================= THE PRINTED TASK PACKET =================
   JS/features/task-print.js stages `.a-note-print.a-task-print` as a direct child of <body>
   and JS/features/note-print.js's notePrintNow() prints it. Everything below is @media print
   and has no effect on screen — the packet is `hidden` until printed.
   Not alt-notes.css's rules: that file dresses `.a-note-print` for notes.html, which tasks.html
   does not load. The two documents share a printer and a shape; the vocabulary (`a-np-*`) is
   per document — a third document would move these to alt-components.css instead. */
@media print{
  /* The application comes off — notePrintNow() also hides these; this is the belt to that pair
     of braces, catching anything the shell adds later that the JS list does not know about. */
  .alt-app .a-top,
  .alt-app .a-page,
  .alt-app .a-status,
  .alt-app .a-scrim,
  .alt-app .a-menu,
  .alt-app .a-info-pop,
  .alt-app .a-grip,
  .alt-app .a-vgrip,
  .alt-app .modal-overlay,
  .alt-app .session-boot{ display:none !important; }

  /* The shell is the viewport on screen and must not be on paper: a fixed height with hidden
     overflow prints exactly one screenful and throws the rest away. */
  .alt-app{
    height:auto; min-height:0; max-height:none; overflow:visible; display:block;
    background:#fff; color:#000;
  }

  /* Deliberately not var(--a-body) — the same decision alt-notes.css's `.a-note-print` rules
     (serving JS/features/note-print.js) and JS/features/board-export.js make; classic_tasks.html's
     own printNote() made the same call before it retired with that page. A packet is a document
     sent to other people, not carrying the sender's chosen face. */
  .alt-app .a-task-print{
    display:block; background:#fff; color:#000;
    font-family:-apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
    font-size:11pt; line-height:1.45;
  }
  .alt-app .a-task-print *{ box-sizing:border-box; }

  .alt-app .a-task-print .a-tp-title{ font-size:19pt; font-weight:700; margin:0 0 4pt; color:#000; }
  /* IS IT DONE, WHOSE IS IT, WHEN IS IT WANTED — the line somebody reads before anything else,
     so it is not small print. */
  .alt-app .a-task-print .a-tp-meta{ font-size:10pt; font-weight:600; color:#000; margin:0 0 6pt; }

  .alt-app .a-task-print .a-tp-facts{
    margin:0 0 8pt; padding:0; break-inside:avoid; page-break-inside:avoid;
  }
  .alt-app .a-task-print .a-tp-fact{ display:flex; gap:6pt; font-size:9pt; margin:0 0 1pt; }
  .alt-app .a-task-print .a-tp-fact dt{ flex:0 0 84pt; font-weight:700; color:#333; margin:0; }
  .alt-app .a-task-print .a-tp-fact dd{ flex:1 1 auto; min-width:0; margin:0; color:#000;
    overflow-wrap:anywhere; }

  .alt-app .a-task-print .a-tp-tags{ margin:0 0 6pt; }
  .alt-app .a-task-print .a-tp-tag{
    display:inline-block; font-size:9pt; color:#000;
    border:1px solid #999; border-radius:9pt; padding:1pt 6pt; margin:0 4pt 3pt 0;
  }
  /* The dot keeps the tag's own colour where a colour printer is in use, and the LABEL beside
     it is what carries the meaning everywhere else. */
  .alt-app .a-task-print .a-tp-dot{
    display:inline-block; width:6pt; height:6pt; border-radius:50%;
    border:1px solid #666; margin-right:4pt; vertical-align:baseline;
    -webkit-print-color-adjust:exact; print-color-adjust:exact;
  }

  .alt-app .a-task-print .a-tp-sec{ margin:14pt 0 0; }
  /* A SECTION SHORT ENOUGH TO FIT ON A PAGE SHOULD NOT BE SPLIT ACROSS TWO. The description
     and a note's pages are deliberately NOT in this class: a rule the browser cannot honour is
     answered by breaking wherever it likes, which is worse than asking for nothing. */
  .alt-app .a-task-print .a-tp-keep{ break-inside:avoid; page-break-inside:avoid; }
  .alt-app .a-task-print .a-tp-h{
    font-size:9pt; font-weight:700; text-transform:uppercase; letter-spacing:.4pt;
    color:#333; margin:0 0 5pt; padding-bottom:3pt; border-bottom:1px solid #999;
    break-after:avoid; page-break-after:avoid;
  }
  .alt-app .a-task-print .a-tp-summary{
    font-size:10pt; border-left:3px solid #999; padding:4pt 8pt; color:#000; margin:0;
  }
  .alt-app .a-task-print .a-tp-note{ font-size:8.5pt; color:#333; margin:4pt 0 0; }

  .alt-app .a-task-print .a-tp-body{ font-size:10pt; color:#000; }
  .alt-app .a-task-print .a-tp-body img{ max-width:100%; }
  .alt-app .a-task-print .a-tp-body ul,
  .alt-app .a-task-print .a-tp-body ol{ margin:4pt 0 4pt 18pt; padding:0; }
  .alt-app .a-task-print .a-tp-body a{ color:#000; text-decoration:underline; }
  .alt-app .a-task-print .a-tp-body table{ width:100%; border-collapse:collapse; font-size:9pt; }
  .alt-app .a-task-print .a-tp-body td,
  .alt-app .a-task-print .a-tp-body th{ border:1px solid #ccc; padding:2pt 4pt; text-align:left; }
  /* The editor's highlight classes survive sanitizeRichHtml() and therefore reach paper. On
     screen they are a wash of colour; here they are a rule under the phrase, because a pale
     background prints as nothing on most printers. */
  .alt-app .a-task-print .a-tp-body mark{ background:none; color:#000; border-bottom:1px solid #000; }

  .alt-app .a-task-print .a-tp-okr{ margin:0 0 5pt; break-inside:avoid; page-break-inside:avoid; }
  .alt-app .a-task-print .a-tp-okr-o{ font-size:11pt; font-weight:700; color:#000; margin:0; }
  .alt-app .a-task-print .a-tp-okr-m{ font-size:8.5pt; color:#333; margin:0; }
  .alt-app .a-task-print .a-tp-okr-k{ font-size:10pt; color:#000; margin:1pt 0 0; }

  .alt-app .a-task-print .a-tp-note-doc{ margin:0 0 10pt; }
  .alt-app .a-task-print .a-tp-page{ margin:0 0 8pt; }
  .alt-app .a-task-print .a-tp-page-h{ break-after:avoid; page-break-after:avoid; margin:0 0 3pt; }
  .alt-app .a-task-print .a-tp-page-h h3{ display:inline; font-size:12pt; font-weight:700; margin:0; color:#000; }
  .alt-app .a-task-print .a-tp-page-h h4{ display:inline; font-size:10.5pt; font-weight:700; margin:0; color:#000; }
  .alt-app .a-task-print .a-tp-page-d{ font-size:9pt; color:#333; margin-left:6pt; }

  .alt-app .a-task-print .a-tp-cat{ break-inside:avoid; page-break-inside:avoid; margin:0 0 6pt; }
  .alt-app .a-task-print .a-tp-cat-h{
    font-size:10pt; font-weight:700; margin:0 0 3pt; color:#000;
    break-after:avoid; page-break-after:avoid;
  }
  .alt-app .a-task-print .a-tp-list,
  .alt-app .a-task-print .a-tp-files{ list-style:none; margin:0; padding:0; }
  .alt-app .a-task-print .a-tp-files li{ font-size:10pt; color:#000; margin:0 0 2pt; }
  .alt-app .a-task-print .a-tp-item{
    display:flex; align-items:flex-start; gap:6pt; font-size:10pt; margin:0 0 2pt; color:#000;
    break-inside:avoid; page-break-inside:avoid;
  }
  .alt-app .a-task-print .a-tp-box{
    flex:0 0 auto; width:8pt; height:8pt; border:1px solid #000; border-radius:1pt; margin-top:2pt;
  }
  .alt-app .a-task-print .a-tp-item-t{ flex:1 1 auto; min-width:0; }
  /* DONE IS A RULE THROUGH THE TEXT AND A FILLED BOX — two signals, neither of them colour. */
  .alt-app .a-task-print .a-tp-item.done .a-tp-box{
    background:#000; -webkit-print-color-adjust:exact; print-color-adjust:exact;
  }
  .alt-app .a-task-print .a-tp-item.done .a-tp-item-t{ text-decoration:line-through; }

  .alt-app .a-task-print .a-tp-comment{ break-inside:avoid; page-break-inside:avoid; margin:0 0 6pt; }
  .alt-app .a-task-print .a-tp-comment-h{
    font-size:9pt; font-weight:700; color:#000; margin:0;
    break-after:avoid; page-break-after:avoid;
  }
  .alt-app .a-task-print .a-tp-comment-b{ font-size:10pt; color:#000; margin:1pt 0 0; }

  .alt-app .a-task-print .a-tp-foot{
    margin-top:16pt; padding-top:4pt; border-top:1px solid #ccc;
    font-size:8.5pt; color:#333;
  }
}

/* ---------- FOCUSED, ON THE MOMENTUM ROW ----------
   Right-aligned without the band learning about it: `margin-left:auto` on this one control
   claims the space to the right edge, the same trick `.a-tabs-end` uses one row down. The `on`
   state is the suite's own `.a-btn.on` (alt-components.css), so it follows every theme for free. */
/* Scoped to the momentum band by id, not the shared `.a-band` class — that rule also reached
   team_board.html's `#altTeamCtx` and turned `.at-ctx` into a shrink-to-fit flex item instead of
   a full-width block, wrapping its own controls onto a second line. `#altBand` says what was
   always meant: this page's band alone. */
.alt-app #altBand{ display:flex; align-items:center; gap:var(--a-2); }
.alt-app .a-focused-btn{ margin-left:auto; flex:0 0 auto; }

/* The quick-actions row is the card's last line — folding (Hide, or Focused) folds the controls
   row and the hint either side of it and keeps this one, so Hide stays reachable rather than
   leaving an empty "Show >" bar (JS/alt/alt-tasks.js's altApplyToolbarOpen()). `.solo` is the
   whole card when #altControls is hidden: its own top edge, both radii, no seam-closing margin. */
.alt-app .a-quick-strip.solo{
  border-top:1px solid var(--a-line-soft);
  border-radius:var(--a-r-lg);
  margin-top:0;
}
/* The toggle, once moved in here — `.a-actions` beside it is `flex:1 1 auto` so it's already
   pushed right; `margin-left:auto` is the belt for when no chips are configured to do that. */
.alt-app .a-quick-strip > #altToolbarToggle{ flex:0 0 auto; margin-left:auto; }
/* The filter chips park here too — `#altFilterChips` already carries `margin-left:auto`
   (`.a-tabs-end`), so with the toggle's own auto margin also in force the free space would split
   between them. Zeroing the toggle's margin here (adjacent-sibling, only while chips are parked)
   leaves one auto margin pushing the pair right as a group. */
.alt-app .a-quick-strip > #altFilterChips + #altToolbarToggle{ margin-left:0; }
/* The parked cluster is a row, not a wrapping one — it holds exactly two controls side by side;
   the STRIP around it is what wraps when the window runs out of room. */
.alt-app .a-quick-strip > #altFilterChips{ flex:0 0 auto; }

/* ---------- 12. THE FOLD KEEPS THE FIGURES ----------
   PRODUCT OWNER: "hiding the work at a glance shall always display the 4 tiles and hide should
   be on the RIGHT side of the 4 tiles." Folding used to hide the whole band body, costing the
   reader the counts along with the detail. `data-fold` already drew the right line — "Your
   work" carries none, "By status"/"By tag" both do, matching what the narrow-row block and
   alt-minimal.css already treat as detail — so the fold reuses that distinction. */
.a-glance.is-folded > .a-glance-part[data-fold]{ display:none; }

/* ---------- FOLDED IS A ONE-ROW LAYOUT, AND THE CONTROL SITS AFTER THE FIGURES ----------
   PRODUCT OWNER: "when you hide, the section should be one row instead of keeping its size and
   move the hide to the right most area of the section." Hiding the detail alone wasn't enough —
   `.a-analytics` is a flex column, so the header still sat stacked above the tiles. Folded and
   Minimalist share this block rather than drifting as two descriptions of one arrangement.
   `display:contents` on the header wrapper is load-bearing: `.a-panel-actions` is a grandchild
   of this row, and `order` can't move it past a sibling of its own parent — dissolving the
   wrapper promotes its children so the actions can be ordered last. */
.a-analytics.is-folded,
body.a-minimal .a-analytics{
  flex-direction:row; align-items:center; flex-wrap:nowrap; gap:var(--a-3);
}
.a-analytics.is-folded > .a-sec-h,
body.a-minimal .a-analytics > .a-sec-h{ display:contents; }
.a-analytics.is-folded > .a-sec-h > .a-panel-ico,
.a-analytics.is-folded > .a-sec-h > h2,
body.a-minimal .a-analytics > .a-sec-h > .a-panel-ico,
body.a-minimal .a-analytics > .a-sec-h > h2{ order:0; flex:0 0 auto; }
.a-analytics.is-folded > .a-glance,
body.a-minimal .a-analytics > .a-glance{ order:1; flex:1 1 auto; min-width:0; }
.a-analytics.is-folded > .a-sec-h > .a-panel-actions,
body.a-minimal .a-analytics > .a-sec-h > .a-panel-actions{ order:2; margin-left:auto; flex:0 0 auto; }

/* The figures are a row while folded, not the auto-fit grid the open card uses — a grid inside a
   single-row section would keep reserving tile-sized columns and give back none of the height. */
.a-analytics.is-folded .a-glance{ display:flex; align-items:center; gap:var(--a-2); }
.a-analytics.is-folded .a-glance-part{ flex:1 1 auto; min-width:0; }
.a-analytics.is-folded .a-glance-part > .a-sec-h{ display:none; }
.a-analytics.is-folded .a-glance .a-stats{ display:flex; gap:var(--a-2); }
.a-analytics.is-folded .a-stat{
  flex:1 1 0; flex-direction:row; align-items:baseline; gap:6px; min-height:0; padding:3px 9px;
}

/* ================= NOTHING HERE YET — WHAT THE FIRST-RUN CARD REPLACES =================
   PRODUCT OWNER: "when a user has not tasks, create a notice in the main tasks area that there
   are no tasks, click here to add your first task ... It should hide all the panels by default
   when there is not tasks, and have a create your first task in the same style as 'Create
   organization'."
   The card itself is not drawn here — JS/components/first-run-card.js renders it, dressed by the
   same `.ofr-stage`/`.ofr-card` the Organization-creation state uses. This page owns only WHAT
   DISAPPEARS: the component toggles one body class and leaves the meaning to the host, the same
   contract team_board.html has with `ofr-board-hidden`. One rule hides the three panels inside
   #altMain (tab row, utilities rail, task drawer); #altContext (a sibling of #altMain) and
   #altBand need naming separately — #altBand goes too since neither the momentum count nor the
   Focused toggle survives having no tasks to focus. CSS only, never a JS-set `.hidden`, so this
   feature's markup is never mistaken by its real owner for an attribute it set itself. */
/* `body.alt-app.frc-first-run`, not `body.frc-first-run` — `.alt-app #altBand{display:flex}`
   above is (0,1,1), the same specificity a bare class selector would have, so without the extra
   class this would win only by being appended last, one reorder away from the band reappearing
   over the card. */
/* Scoped to this page's #altMain specifically — `#altMain` is shared by notes.html, calendar.html
   and team_board.html too, all bare `alt-app`, so an unscoped rule collapsed the notes card to
   0x0 the moment notes.html entered its own first-run state. Fixed in the selector (an id beats
   a class-only override) via `a-main-tasks`, the page class this page alone lacked. */
/* #altDidYouKnow goes too, per the same "centered middle screen" request — kept at first as the
   one thing worth saying on an empty page, until measurement showed it sits 255px tall above the
   card, pushing the card 214px below the viewport's middle. */
body.alt-app.frc-first-run #altBand,
body.alt-app.frc-first-run #altContext,
body.alt-app.frc-first-run #altDidYouKnow,
body.alt-app.frc-first-run #altMain.a-main-tasks{
  display:none;
}

/* The host costs nothing until the card is in it — `#altFirstRun` is an empty div, `display:none`
   on every ordinary load. It cannot disagree with the card: firstRunCardShow() sets
   `stage.hidden` and toggles the body class in the same statement pair. `flex:1 1 auto` on both
   so the card sits in the middle of the space #altMain gave up, not pinned under the topbar. */
#altFirstRun{ display:none; }
body.frc-first-run #altFirstRun{
  display:flex; flex:1 1 auto; min-height:0; min-width:0;
}
/* min-height:0 defeats `.ofr-stage`'s own min(60vh,520px) floor — right for a stage inside a
   page's flow, wrong for one that IS the page, where the floor made the stage taller than its
   496px slot and the card centred in the cap instead of the real space. */
body.frc-first-run #altFirstRun > .ofr-stage{ flex:1 1 auto; min-width:0; min-height:0; }
