/* ================= THE ALTERNATE UX — THE TEAM BOARD =================
   This page's own chrome: context strip, glance figures, assignee strip, toolbar, density
   rules, and the hosted #taskModal/#adminModal dress. The kanban itself is
   CSS/alt/alt-team-kanban.css + alt-team-kanban-compact.css (section 4, below).
   Read alt-tokens.css and alt-components.css first — a new primitive here likely duplicates
   one there. `alt-responsive.css` loads AFTER this file and owns every width from 1920 to 320.
   No authored z-index on a layer — every overlay is JS/alt/alt-layers.js's; the four z-index
   values here are a tooltip (`--z-float`) and a sticky column header.
   `at-` is this page's own prefix; `a-` names (`.a-btn`, `.a-chip`, `.a-stat`…) are the shared
   experience's, extended here, never redefined — except `.a-seg > span.k-x0…k-x5`, a lane
   colour keyed by POSITION so a seventh configured lane still reads distinct from the sixth. */

/* ================= 0 · THE PAGE STANDS DOWN — TWO CAUSES, ONE LOOK =================
   PRODUCT OWNER: "the no board access looks good. However, it should hide all of the controls
   for the team view. It should just display the notice. Once they have been added to the
   board, all the board controls would be visible per the normal experience."
   SAME DAY, HAVING SEEN THAT SHIP: "the initial load flashes the team board controls but then
   flashes and loaded the notice. The board should not load until the full content and
   configuration has loaded so it just loads once. It also has Team and the utility rail which
   both shouldn't be visible until the org owner grants the user access to boards. It should
   just be the message with the top universal navigation visible."
   Two classes, same look: `a-tb-no-access` (the gate saying no, with a notice under it) and
   `a-tb-settling` (nothing to say yet, temporary) — both written by
   altTBApplyNoAccessChrome() (JS/alt/alt-team-board.js) off the same two functions that decide
   whether the card is drawn. A class on <body> composes with Focused mode's own `.hidden`;
   a script-set `.hidden` here would fight it. Four ids, not `#altMain`: this notice draws
   INTO #altTeamView, inside #altMain, so the grid stays and the toolbar is named separately.
   The rail's own track is JS's to empty (altTeamApplyLayout(), JS/alt/alt-team-rail.js) —
   display:none here would leave its 312px track blank rather than gone.
   Specificity (0,2,1) beats `.a-band` (alt-shell.css) and `.alt-app #altTeamToolbar`
   (alt-team-kanban.css) without `!important`. */
body.a-tb-no-access #altTeamGlance,
body.a-tb-no-access #altTeamPeople,
body.a-tb-no-access #altTeamToolbar,
body.a-tb-settling #altTeamGlance,
body.a-tb-settling #altTeamPeople,
body.a-tb-settling #altTeamToolbar{
  display:none;
}

/* ---------- THE TEAM SELECT GOES TOO, AND THAT REVERSES A RULING RECORDED HERE ----------
   READ THIS BEFORE RESTORING THE EXEMPTION. A first ruling carried a `:not(.at-ctx-team)`
   exemption over `.at-ctx`'s direct children, so a reader denied on team A could still reach
   `#altTeamSel` — the only team switcher this page's chrome offered. The owner then looked at
   the live page and overruled himself the same day: "It also has Team and the utility rail
   which both shouldn't be visible until the org owner grants the user access to boards. It
   should just be the message with the top universal navigation visible." The exemption is
   gone and `#altTeamCtx` hides wholesale again — safe only because the route the first ruling
   protected moved to `#altTeamBtn` in the shell (a "Switch to" button per team), outside this
   page's chrome and not hidden by either class here. If that door ever closes, reconsider this
   with the owner first. `#altTeamBanner` needed no separate selector either way: it is a
   sibling of `.at-ctx`, so hiding the host already took it. */
body.a-tb-no-access #altTeamCtx,
body.a-tb-settling #altTeamCtx{
  display:none;
}

/* ================= 1 · THE CONTEXT BAR =================
   One row of labelled controls — every control wears a caption (even a blank one, for baseline
   alignment), because "which of these two dropdowns is the team" was the classic board's own
   unlabelled failure. Flex, not grid: the row has to survive a long team name, a long board
   name and a search box taking whatever is left, which a grid would need a breakpoint per
   column to do. */
/* ---------- the pin: lying flat when it holds nothing, upright when it holds ----------
   Same behaviour as okrs.html's `.okr-pin-btn` (CSS/okr.css) — one attribute drives both the
   angle and the accent, so they can never disagree. A quarter turn, not a tilt: the two states
   must be told apart across the room, not by comparing angles. `--a-quick` drops for reduced
   motion. */
.alt-app .at-ctx-pin[aria-pressed="true"]{
  border-color:var(--a-blue); color:var(--a-blue-text); background:var(--a-blue-soft);
}
.alt-app .at-ctx-pin svg{
  transform:rotate(-90deg); transition:transform var(--a-quick) var(--a-ease);
}
.alt-app .at-ctx-pin[aria-pressed="true"] svg{ transform:rotate(0deg); }
@media (prefers-reduced-motion: reduce){
  .alt-app .at-ctx-pin svg{ transition:none; }
}

/* ---------- the pin, in the actions group ----------
   In flow, beside Filters — not absolutely positioned in the band's corner as a prior deploy
   had it, which read as detached from the page and collided with the tab strip. No width or
   colour rule of its own: `.a-btn.icon.ghost` sizes it and `.tog.on` is the pressed ground
   every other toggle here already uses. */

.alt-app .at-ctx{
  display:flex; align-items:flex-end; gap:var(--a-3); flex-wrap:wrap; min-width:0;
}
/* EVERY FIELD SETS ITS OWN `flex`, AND THERE IS NO BLANKET DEFAULT ABOVE THEM. There was one —
   `.at-ctx .a-field{flex:0 0 auto}` — and at (0,3,0) it outranked every `.at-ctx-*` rule below
   it whatever the order, so not one of the widths on this page was doing anything: the row was
   laid out at its content widths, the search box never took the slack, and at 320 the tab track
   could not shrink and made the whole PAGE scroll sideways. A default that is more specific
   than the rules it is a default FOR is not a default. */
.alt-app .at-ctx-team{ flex:0 1 190px; min-width:130px; }
/* THE BOARD NAME IS THE ONE THING IN THIS ROW A READER MUST BE ABLE TO READ, and a fixed
   230px basis meant a board called anything longer than "CTO Office" was cut off by the native
   control with nothing to hover and no way to widen it. `flex:0 1 auto` lets the field take the
   width of its longest option — which is exactly what a select is sized by — and `max-width`
   is what stops one very long board name from eating the search box. Past that the name
   ELLIPSES rather than being sliced mid-glyph, and altTeamFillBoardSelect() puts the full name
   on the control's `title` so it is still readable. */
.alt-app .at-ctx-board{ flex:0 1 auto; min-width:200px; max-width:340px; }
/* Applies to both selects: a truncated option should end in an ellipsis, not a half letter. */
.alt-app .at-ctx-team .a-select,
.alt-app .at-ctx-board .a-select{ width:100%; text-overflow:ellipsis; }
.alt-app .at-ctx-group{ flex:0 1 170px; min-width:130px; }
/* NOT `.a-toolbar`. That component carries `padding:var(--a-2) 0` because it IS a row of its
   own; used inside a labelled field it made this one 65px against the 49px of the six beside
   it, so the two buttons sat 16px lower than every other control in the strip. Measured. */
.alt-app .at-ctx-btns{ display:flex; align-items:center; gap:var(--a-2); min-width:0; }
.alt-app .at-ctx-mine,.alt-app .at-ctx-acts{ flex:0 0 auto; }
/* THE VIEW FIELD HUGS ITS OWN CONTENT, REVERTED THERE BY THE OWNER AFTER SEEING THE ALTERNATIVE:
   "change this so the buttons are together with standard padding move back to how it was before
   the design change for this group box." A prior pass made the field grow (`flex:1 1 340px`,
   `.at-tabs{justify-content:space-between}`) per an earlier ask that it be "as wide as the red
   box"; the result spread Board and Archived ~400px apart and stopped reading as one control —
   a segmented control's grouping IS its proximity. No `justify-content` override now: this page
   matches every other host of the shared `.at-tabs` primitive.
   Focused stays in `.at-ctx-btns` rather than beside `.at-tabs` itself — nesting a rigid control
   there was tried, measured broken below 1024px (a `min-width` floor can't save it; CSS resolves
   flex-wrap's line break from each item's BASIS before anything shrinks), and reverted.
   The ≤1023px rule below is deliberately unrelated: there the field takes the whole row because
   nothing fits beside it at that width — a different problem, not "restore consistency". */
.alt-app .at-ctx-view{ flex:0 0 auto; min-width:0; }

/* ---------- THE TWO FILTER CHIPS IN THE GLANCE HEADER ----------
   OWNER: "team_board: style the filters to look like [this]" (tasks.html's own pair) — a
   rounded pill, the glyph, the label, and the count as a small badge rather than run-in " · 2".
   Scoped by id, not by `.a-btn .n` globally — that selector is alt-tasks.css's own, which this
   page does not load, and a global rule here would reach every button on the board.
   The badge is `hidden` at zero, never rendered as "0" — the same contract `#altFilterCount2`
   keeps on tasks.html. */
.alt-app #altFiltersBtn,
.alt-app #altTeamClearFiltersBtn{ border-radius:var(--a-r-pill); }
.alt-app #altFiltersBtn .n,
.alt-app #altTeamClearFiltersBtn .n{
  margin-left:6px;
  padding:1px 7px;
  border-radius:var(--a-r-pill);
  background:var(--a-raised);
  font:600 10px/1.6 var(--a-mono);
  font-variant-numeric:tabular-nums;
  opacity:.85;
}
/* LIT STATE: the Filters chip takes `.tog.on` when something is filtering, which fills it — the
   badge sits ON that fill, so it borrows the button's own colour rather than keeping a raised
   grey block that would read as a hole punched in the pill. */
.alt-app #altFiltersBtn.on .n{ background:rgba(255,255,255,.22); color:inherit; opacity:1; }
/* ---------- THE VIEW FIELD ----------
   No wrapper row here any more — Focused moved to the actions cluster and its wrapper went
   with it. The lesson it earned: a rigid control beside `.at-tabs` cannot be made safe with a
   `min-width` floor and `flex-wrap:wrap`, because CSS resolves the line break from each item's
   flex BASIS before anything shrinks, and `.at-tabs` is `width:100%` below 1024 — so the rigid
   item is always pushed to its own line regardless of the floor. The fix was to drop the wrap
   and let the track's own scroller be the escape. Read this before putting a second control
   beside these tabs. */
/* Pushed to the trailing edge, so Filters and More sit where the wireframe puts them and the
   row reads left-to-right as scope, then view, then narrowing. */
.alt-app .at-ctx-acts{ margin-left:auto; }
/* A CAPTION THAT SAYS NOTHING STILL RESERVES ITS LINE. Without it the button under it sits a
   caption higher than the selects beside it, and the row reads as two rows that failed to
   line up. */
.alt-app .at-ctx .a-field > span:empty,
.alt-app .at-ctx-mine > span,
.alt-app .at-ctx-acts > span{ visibility:hidden; }
/* The roster button has no caption at all and must not be pulled up by the ones that do. */
.alt-app .at-ctx > .a-btn.icon{ flex:0 0 auto; align-self:flex-end; }

/* ---------- the view tabs ----------
   MOVED, 2026-09-05, TO CSS/alt/alt-components.css. `.at-tabs`/`.at-tab` is the boxed
   segmented track this page's View strip wears, and okrs.html's context bar was then asked
   for the same control — a page that does not load this sheet, so the strip shipped unstyled.
   The rules did not get COPIED there; they got moved, selectors byte-identical, which is why
   nothing in this file's cascade changed. Its responsive overrides went with it.
   WHAT STAYED HERE is `.at-ctx-*` — the LAYOUT of THIS page's context row, which is this
   page's business and nobody else's. */

/* ---------- the filter banner ----------
   A BOARD QUIETLY SHOWING A SUBSET IS THE THING TO MAKE LOUD. It sits under the row it
   explains, in the accent wash, and it carries the count so the sentence and the board cannot
   be read as describing different things. */
.alt-app .at-banner{
  display:flex; align-items:center; gap:var(--a-3); margin-top:var(--a-2);
  padding:7px var(--a-3); border-radius:var(--a-r-sm);
  background:var(--a-blue-soft); border:1px solid var(--a-blue);
  color:var(--a-blue-text); font-size:12px; line-height:1.5;
}
.alt-app .at-banner-t{ flex:1 1 auto; min-width:0; }
.alt-app .at-banner .a-btn{ flex:0 0 auto; }

/* ================= 1b · THE PANEL SHELL =================
   The box sections 2 and 3 both sit in — a caption and tiles floating free on the page ground
   used to leave nothing saying where either summary ended. Each is `.a-card` now (ground, edge,
   radius declared once in alt-components.css), never a second definition of the same look.
   The card is an INNER wrapper, not `.a-band` itself: `.a-band` carries the page gutter as
   padding, which alt-responsive.css narrows at 820px — painting the card directly onto it would
   convert that padding to a margin the width file could no longer reach. The `<section>` stays
   the landmark; the wrapper is a plain box announcing nothing. */
.alt-app .at-panel{ padding:var(--a-3); }
/* Compact is answered here, not in section 6's density block — the two specificities would tie
   otherwise, and this is the panel's own answer, not the band's gutter. Section 6 points back. */
.alt-app.a-compact .at-panel,
.alt-app[data-team-density="compact"] .at-panel{ padding:var(--a-2); }

/* The leading glyph is ornament — JS/alt/alt-team-context.js marks it `aria-hidden`, the title
   carries the meaning. `--a-blue-soft`/`--a-blue-text` is the same accent pair `.a-btn.tog.on`,
   `.a-stat.on` and `.at-person.on` already wear, with its contrast figures in CSS/tokens.css —
   not a fresh, unmeasured tint for a square whose whole job is to be quiet. */
.alt-app .at-panel-ico{
  flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center;
  width:22px; height:22px; border-radius:var(--a-r-sm);
  background:var(--a-blue-soft); color:var(--a-blue-text);
}
.alt-app .at-panel-ico svg{ width:14px; height:14px; display:block; }

/* The Hide/Show chevron has no rule of its own here — sized by the shared `.a-btn > .cv`
   (alt-components.css), the same wrapper `.a-w-fold .cv` (alt-rail.css) uses, which keeps it
   out of `.a-btn:not(.icon) > svg`'s reach. Swapped, never rotated (`chev`/`chevR`), and
   inherits currentColor rather than `--a-faint` since it sits inside a button, not beside a
   dim label. */

/* ================= 2 · TEAM AT A GLANCE =================
   Three regions, first sized for its content: five tiles need ~500px at minimum, and a
   fractional share gave a different answer at every width. A pixel ceiling answers the same
   everywhere it fits, handing the rest to the two chip regions that genuinely can take it. */
.alt-app .at-glance{
  display:grid; align-items:start; min-width:0;
  gap:var(--a-3) var(--a-5);
  grid-template-columns:minmax(0,560px) minmax(0,1.1fr) minmax(0,.9fr);
}
.alt-app .at-part{ min-width:0; display:flex; flex-direction:column; gap:var(--a-2); }
.alt-app .at-part > .a-sec-h{ margin:0 0 2px; }
/* The figures region has no heading of its own — the band's own title names it — so it starts
   level with the two that do. */
.alt-app .at-part-stats{ padding-top:15px; }
/* Five across where there is room, wrapping by measurement, not a hardcoded count — `.a-stats`
   is three fixed columns for the rail's narrow band, but a full-width strip should use its width.
   88px, not 96: five tiles at 96 needed 512px against a 480 ceiling below 1440, dropping the
   fifth tile to its own row; 472 fits every ceiling in this file. */
.alt-app .at-glance .a-stats{
  grid-template-columns:repeat(auto-fit, minmax(88px,1fr)); gap:var(--a-2);
}

/* THE FOLD HIDES ONLY THE DETAIL, NEVER THE FIGURES — PRODUCT OWNER: "when the panel is hidden,
   keep the board tiles visible... so they are still visible and interactive" (the same rule
   glance-fold-keeps-tiles.test.js already proves for tasks.html). `data-fold` marks the two
   breakdowns; "Key figures" carries none, so it stays on screen and built regardless of `open`.
   `display:none`, not a grid-column collapse — a hidden grid item reserves no empty track. */
.alt-app .at-glance.is-folded > .at-part[data-fold]{ display:none; }
/* The one surviving column takes the row, the same "figures span the row they head" idea
   `.at-part-stats{grid-column:1 / -1}` states for ≤1279px, made unconditional once folded —
   specificity wins regardless of which media query's grid-template-columns is active. */
.alt-app .at-glance.is-folded{ grid-template-columns:minmax(0,1fr); }
.alt-app .at-glance.is-folded > .at-part-stats{ padding-top:0; }

/* ---------- FOLDED IS ONE ROW, AND THE CONTROLS SIT AFTER THE FIGURES ----------
   PRODUCT OWNER: "hide should be only one row not two." `.at-panel` is a plain block, so the
   header sat stacked above the tile strip even with the breakdowns gone — folded, it is now one
   row: title, figures, cluster. Ported from tasks.html's `.a-analytics.is-folded`, same owner
   instruction, deliberately the same arrangement.
   `display:contents` on the header wrapper is load-bearing: `.at-ctx-btns` is a GRANDCHILD of
   the card, and `order` can't move an item past a sibling of its own parent, so dissolving
   `.at-band-h` promotes its children into the card's row where the cluster can be ordered last.
   Two of tasks.html's rules are deliberately absent: this band's figures column has no visible
   heading to hide, and once folded its row has exactly one child, so a `gap` would resolve to
   nothing. */
/* `flex-wrap:wrap`, departing from tasks.html's `nowrap` on purpose — this page has a recorded
   overflow incident (teamboard-responsive-overflow.test.js: team_board.html once ran 1325px
   past a 390px viewport) and a folded row holds two `flex:0 0 auto` groups that would overlap
   rather than wrap at `nowrap`. Costs nothing where it already fits. */
.alt-app .at-panel.is-folded{
  display:flex; flex-direction:row; align-items:center; flex-wrap:wrap; gap:var(--a-3);
}
.alt-app .at-panel.is-folded > .at-band-h{ display:contents; }
.alt-app .at-panel.is-folded > .at-band-h > .at-panel-ico,
.alt-app .at-panel.is-folded > .at-band-h > h2{ order:0; flex:0 0 auto; }
.alt-app .at-panel.is-folded > .at-glance{ order:1; flex:1 1 auto; min-width:0; }
/* NO `flex-wrap` HERE — the cluster KEEPS the wrap `.at-band-h > .at-ctx-btns` above gives it,
   for the reason stated in that rule's own comment: three buttons with long labels are the one
   place on this page a fixed-content group runs out of room, and taking the wrap away is the
   overflow defect again one level down. */
.alt-app .at-panel.is-folded > .at-band-h > .at-ctx-btns{
  order:2; margin-left:auto; flex:0 0 auto;
}
/* The figures are a row while folded, not the open card's auto-fit grid, which would keep
   reserving tile-sized columns. `.at-panel.is-folded` rather than `.at-glance.is-folded` alone,
   for the specificity to beat the three-class grid rule above. */
.alt-app .at-panel.is-folded .at-glance{ display:flex; align-items:center; }
.alt-app .at-panel.is-folded .at-part{ flex:1 1 auto; min-width:0; }
.alt-app .at-panel.is-folded .at-glance .a-stats{ display:flex; gap:var(--a-2); }
.alt-app .at-panel.is-folded .a-stat{
  flex:1 1 0; flex-direction:row; align-items:baseline; gap:6px; min-height:0; padding:3px 9px;
}

/* THE BAND HEADER carries the section name and its controls on one line. `.a-sec-h` is the
   shared uppercase label; this only says how its children divide the row. */
.alt-app .at-band-h{ margin-bottom:var(--a-2); gap:var(--a-3); flex-wrap:wrap; }
.alt-app .at-band-h h2{
  font-size:10px; font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  color:var(--a-dim); margin:0;
}
/* The controls in a band header sit at the trailing edge; whatever is first after the title
   claims the space between. */
.alt-app .at-band-h > .a-btn{ margin-left:auto; }
.alt-app .at-band-h > .at-due{ margin-left:var(--a-4); }
.alt-app .at-band-h > .at-due ~ .a-btn{ margin-left:0; }
/* THREE BUTTONS, ONE CLUSTER — three direct `.a-btn` children each pushing with their own
   `margin-left:auto` would each open a gap before themselves; built inside `.at-ctx-btns`
   instead (reused, not restated) so the WRAPPER is pushed once. Wraps rather than overflows,
   the escape teamboard-responsive-overflow.test.js exists for (this page once ran 1325px past a
   390px viewport) — scoped here since `.at-ctx-btns`'s other host never has three long labels. */
.alt-app .at-band-h > .at-ctx-btns{
  margin-left:auto; min-width:0; flex-wrap:wrap; justify-content:flex-end;
}
/* A plain count until a topic narrows the band, then "8 people · in Q1 Onsite" — reader-chosen
   text with no length limit. Truncates the same way `.at-person-n` does: min-width:0 so the
   flex item can shrink, ellipsis rather than wrap or overrun; the full phrase reaches `title`. */
.alt-app .at-count{
  font-size:11px; color:var(--a-faint); flex:0 1 auto; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.alt-app .at-band-h > .at-count{ margin-left:auto; }
.alt-app .at-band-h > .at-due ~ .at-count{ margin-left:auto; }

/* ---------- the status bar and its chips ----------
   A lane outside the six the product ships with still needs a colour. `.k-todo…k-complete`
   (alt-components.css) name the six by meaning; these six name POSITIONS, so a board configuring
   "Triage", "Design" and "QA" gets three distinguishable segments, not three identical blues. */
.alt-app .a-seg > span.k-x0{ background:#2564cf; }
.alt-app .a-seg > span.k-x1{ background:#107c41; }
.alt-app .a-seg > span.k-x2{ background:#ca5010; }
.alt-app .a-seg > span.k-x3{ background:#8764b8; }
.alt-app .a-seg > span.k-x4{ background:#0891b2; }
.alt-app .a-seg > span.k-x5{ background:#b5893a; }
/* The bar is a summary of a whole board and reads better a little taller than the rail's. */
.alt-app .at-part .a-seg{ height:10px; border-radius:5px; }
/* A chip with a count is two pieces of text, so the label elides, not the number — "Platform
   Road…" is useful, "Platform Roadmap 1" is not. ("Platform Roadmap" is a synthetic board name;
   nothing here measures the string — 190px is a fixed cap, not derived from it.) */
.alt-app .at-part .a-chip{ max-width:190px; }
/* `.a-chip .lb` truncation moved to alt-components.css — this page and alt-okrs.css had each
   re-derived it independently, which was the evidence it belonged in the shared file. Core rule 4. */
.alt-app .at-part .a-chip .n{ flex:0 0 auto; }
.alt-app .at-part .a-chip[disabled]{ opacity:.55; cursor:default; }
/* ONE ROW, THEN A CONTROL. 24px, not 51 — `button.a-chip{min-height:24px}` (alt-responsive.css,
   §18's floor) raised the chip after this ceiling was written for a smaller one, shaving 4px off
   a second row that should not have existed at all. A band summarising a board should not legend
   eight tags above the work it summarises; `+NN more` folds the rest in place, the same shape
   altClampChips() uses on tasks.html. */
.alt-app .at-part .a-dist-chips.clipped{ max-height:24px; }
/* The overflow control sits ON the chips' own line now — `.a-dist` is column-direction by
   default (alt-tasks.css), which cost two rows to show one. `.a-dist-inline` is scoped to the
   Tags region, whose `.a-dist` holds only chips and the control; Status keeps its column, since
   its proportion bar above the chips wants the full width. */
.alt-app .at-part .a-dist{ gap:var(--a-2); padding-top:0; border-top:0; }
.alt-app .at-part .a-dist.a-dist-inline{ flex-direction:row; align-items:flex-start; flex-wrap:nowrap; }
.alt-app .at-part .a-dist-inline > .a-dist-chips{ flex:1 1 auto; min-width:0; }
/* Never shrinks — "+11 more" elided to "+11 m" is a control that stops saying what it does. */
.alt-app .at-part .a-dist-inline > .a-dist-more-h{ flex:0 0 auto; }
/* One row is 26px on a phone — alt-responsive.css's §18 block raises `button.a-chip` to 26
   below 640; the ceiling follows the chip. */
@media (max-width:639px){
  .alt-app .at-part .a-dist-chips.clipped{ max-height:26px; }
}

/* ================= 3 · BY ASSIGNEE =================
   Wraps to the window's width and folds to one row. It was `overflow-x:auto` with scroll-snap —
   one line, scrolled sideways — on the argument that a comparison wants one line; the scroll
   itself was wrong, invisible until dragged, so a fourteen-person board showed seven cards with
   no evidence of the rest. Now the cards wrap and the band clips to the first row, with "+N more
   people" opening the rest in place — the same fold the tag chips above use. The ceiling is set
   in JS (altTeamClampPeople()), not here, because it must be the first row's MEASURED bottom,
   not a constant tuned for one density that is wrong for the other. */
.alt-app .at-people{
  display:flex; flex-wrap:wrap; gap:var(--a-2); min-width:0;
}
/* No `overflow-y` in the unclipped state: a scrollbar over a folded-open band is a second way to
   reach rows the "+N more" control has already brought into view. */
.alt-app .at-people.clipped{ overflow:hidden; }
/* Sits under the cards, not in the band header — it would read as a second action beside Hide. */
.alt-app .at-people-more{ display:flex; align-items:center; margin-top:var(--a-1); }
/* Nothing to fold is nothing to reserve space for — an empty host still carried its margin. */
.alt-app .at-people-more:empty{ display:none; }
.alt-app .at-person{
  flex:0 0 auto;
  display:flex; align-items:center; gap:var(--a-2);
  width:176px; min-height:52px; padding:7px 10px;
  border:1px solid var(--a-line-soft); border-radius:var(--a-r);
  background:var(--a-raised); color:inherit; font:inherit; text-align:left; cursor:pointer;
}
.alt-app .at-person:hover{ border-color:var(--a-line-strong); }
.alt-app .at-person:focus-visible{ outline:2px solid var(--a-ring); outline-offset:1px; }
/* The lit card's wash lifts the ground, so the caption comes up with it — `--a-faint` on the
   blue soft measures under the 4.5:1 floor, the same fix `.a-stat.on span` already uses. */
.alt-app .at-person.on{
  border-color:var(--a-blue); background:var(--a-blue-soft);
  box-shadow:0 0 0 1px var(--a-blue) inset;
}
.alt-app .at-person.on .at-person-n,
.alt-app .at-person.on .at-person-p{ color:var(--a-blue-text); }
.alt-app .at-person.on .at-person-s{ color:var(--a-dim); }
/* `.is-zero` no longer means "somebody with nothing yet" — idle roster members and an empty
   Unassigned pile were removed so they stop pushing working people off the scroller. The one
   carve-out left: a name the people filter is holding whose work nothing in view matches —
   quiet rather than disabled, since it must stay pressable to be cleared. Applied in JS, not off
   `[data-total="0"]`, because on-hold-only work also totals zero but renders at full opacity
   with "N on hold" instead — see altTeamRenderPeople(). */
.alt-app .at-person.is-zero{ opacity:.55; }
.alt-app .at-person.is-zero:hover{ opacity:.8; }
/* When there are no cards at all, the band states which of the two reasons rather than leaving
   a heading over a gap. */
.alt-app .at-people-none{
  margin:0; padding:6px 2px; font-size:12px; line-height:1.5;
  color:var(--a-faint); max-width:60ch;
}
.alt-app .at-person-t{ display:flex; flex-direction:column; gap:1px; min-width:0; }
.alt-app .at-person-n{
  font-size:12px; font-weight:600; color:var(--a-text); line-height:normal;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* The percentage is the figure on this card and wears the display face, like `.a-stat b`. */
.alt-app .at-person-p{
  font-family:var(--a-display); font-size:16px; font-weight:600; line-height:normal;
  color:var(--a-text);
}
/* `overflow`/`text-overflow` added alongside `.at-person-n`'s, since the on-hold suffix
   ("3 of 3 done · 2 on hold") can now run longer than "N of M done" ever did at the 152px
   compact-width card; clipping with an ellipsis beats the line spilling out of the card. */
.alt-app .at-person-s{
  font-size:11px; color:var(--a-faint); line-height:normal; white-space:nowrap;
  overflow:hidden; text-overflow:ellipsis;
}
/* Unassigned's avatar carries a dash rather than initials; the em dash needs no weight. */
.alt-app .at-person .a-av{ font-size:11px; }

/* ---------- the due-date window, in the assignee band's header ----------
   Lives with the people because that's the pair of questions asked together — who is carrying
   what, over what period — and it's the same filter the Filters menu edits. */
.alt-app .at-due{
  display:flex; align-items:center; gap:var(--a-2); flex-wrap:wrap; min-width:0;
  text-transform:none; letter-spacing:0;
}
.alt-app .at-due-win{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; min-width:0; }
.alt-app .at-due .a-input{
  height:26px; padding:0 6px; font-size:12px; line-height:normal; width:auto; min-width:0;
}
.alt-app .at-dash{ color:var(--a-faint); }
/* "Tasks with no due date are hidden while a range is set" — otherwise deduced from a card that
   is not there; `.warn` is for a range that cannot match anything. */
.alt-app .at-due-note{
  font-size:11px; color:var(--a-faint); line-height:normal;
  text-transform:none; letter-spacing:0; font-weight:400; min-width:0;
}
.alt-app .at-due-note.warn{ color:var(--a-red); font-weight:600; }
.alt-app .at-presets{ display:inline-flex; align-items:center; gap:4px; }
/* The switch and its word are one control — the `<label>` forwards a click anywhere in its box
   to the checkbox it wraps. Draws through the canonical `.pref-switch` (switchHtml(),
   JS/components/switch.js — Core rule 4), whose `opacity:0` native input paints no outline of
   its own; the visible ring is `.pref-switch input:focus-visible ~ .track`, confirmed with a
   real keyboard Tab. The hit-target floor is still the label, past the §18 24px floor already. */
.alt-app .at-any{
  display:inline-flex; align-items:center; gap:6px; cursor:pointer;
  font-size:11px; font-weight:600; color:var(--a-dim); line-height:normal;
  text-transform:none; letter-spacing:0;
  min-height:24px;
}
.alt-app .at-any:hover{ color:var(--a-text); }

/* ================= DENSITY =================
   One switch on <body>; compact takes height out of the two analytic bands, never removes a
   control. Two selectors for one state, temporarily: `body.a-compact` is the shared
   `settings.altUx.shared.density` switch; `[data-team-density]` is the board's OLD attribute,
   still written by the More menu (JS/alt/alt-team-context.js) from `teamboard.density`. When
   that menu moves to the shared key, delete every `[data-team-density]` selector here and in
   altTBSetDensity(). */
.alt-app.a-compact .a-band,
.alt-app[data-team-density="compact"] .a-band{ padding-top:var(--a-2); }
/* The two summary panels' own compact padding is in section 1b instead, beside the rule it
   tightens, at a specificity that cannot tie with the band rule above. */
.alt-app.a-compact .at-glance,
.alt-app[data-team-density="compact"] .at-glance{ gap:var(--a-2) var(--a-4); }
.alt-app.a-compact .a-stat,
.alt-app[data-team-density="compact"] .a-stat{ min-height:52px; padding:6px 10px; }
.alt-app.a-compact .a-stat b,
.alt-app[data-team-density="compact"] .a-stat b{ font-size:18px; }
.alt-app.a-compact .at-person,
.alt-app[data-team-density="compact"] .at-person{ min-height:44px; width:164px; padding:5px 9px; }
.alt-app.a-compact .at-person-p,
.alt-app[data-team-density="compact"] .at-person-p{ font-size:14px; }

/* ================= 4 · THE BOARD — MOVED =================
   The kanban is CSS/alt/alt-team-kanban.css + alt-team-kanban-compact.css, linked AFTER this
   file so a board rule here beats one there on source order, if it ever needs to. The lane
   canvas and the settings dialog were not the same work in one file. */

/* ================= 5 · THE TWO HOSTED DIALOGS =================
   `#taskModal` and `#adminModal` are classic_team_board.html's markup, copied character for
   character — the rules that dressed them lived in that page's own inline `<style>`, retired
   with it (2026-09-08). Ported, not rewritten: every rule below is that page's own, byte-for-byte,
   using CSS/tokens.css variables this page already loads — now that the classic page is gone,
   this is the only place the pairing is still defined.
   Scoped to the two ids, load-bearing: a bare `input, textarea, select` would beat `.a-input`
   (0,1,1 vs 0,1,0) and repaint every control on the page in the classic dialog's colours.
   `#altViewPane`/`#altViewTab` (JS/alt/alt-team-settings.js) are covered by construction — scoped
   by the dialog id, not a list of panes kept in step. */


/* ---------- shared form and button primitives ---------- */
.alt-app #taskModal input,
.alt-app #adminModal input,
.alt-app #taskModal textarea,
.alt-app #adminModal textarea,
.alt-app #taskModal select,
.alt-app #adminModal select{ font-family:inherit; }
.alt-app #taskModal input[type=text],
.alt-app #adminModal input[type=text],
.alt-app #taskModal input[type=email],
.alt-app #adminModal input[type=email],
.alt-app #taskModal input[type=password],
.alt-app #adminModal input[type=password],
.alt-app #taskModal input[type=date],
.alt-app #adminModal input[type=date],
.alt-app #taskModal input[type=number],
.alt-app #adminModal input[type=number],
.alt-app #taskModal input[type=tel],
.alt-app #adminModal input[type=tel],
.alt-app #taskModal input[type=search],
.alt-app #adminModal input[type=search],
.alt-app #taskModal input[type=url],
.alt-app #adminModal input[type=url],
.alt-app #taskModal input[type=time],
.alt-app #adminModal input[type=time],
.alt-app #taskModal input[type=datetime-local],
.alt-app #adminModal input[type=datetime-local],
.alt-app #taskModal textarea,
.alt-app #adminModal textarea,
.alt-app #taskModal select,
.alt-app #adminModal select{ background:var(--panel-2); color:var(--text); border:1px solid var(--border-strong); border-radius:var(--radius-sm); padding:8px 11px; font-size:13px; }
/* THE ONE PLACE THIS PORTED PADDING FIGHTS A SHARED COMPONENT'S OWN FIXED HEIGHT: the View
   pane's Bands card builds a real `.a-select` (32px, `height:var(--a-ctl)`) inside a dialog
   whose native controls get `padding:8px 11px` instead of that component's own `padding:0
   10px`. With `box-sizing:border-box` the padding alone leaves 14px for a 13px line — enough to
   clip a descender. `height:auto` is scoped to the two classes that carry the fixed height, so
   bare native controls are untouched. */
.alt-app #adminModal .a-select,
.alt-app #adminModal .a-input,
.alt-app #taskModal .a-select,
.alt-app #taskModal .a-input{ height:auto; }
.alt-app #taskModal input[type=text]:focus,
.alt-app #adminModal input[type=text]:focus,
.alt-app #taskModal input[type=email]:focus,
.alt-app #adminModal input[type=email]:focus,
.alt-app #taskModal input[type=password]:focus,
.alt-app #adminModal input[type=password]:focus,
.alt-app #taskModal input[type=date]:focus,
.alt-app #adminModal input[type=date]:focus,
.alt-app #taskModal input[type=number]:focus,
.alt-app #adminModal input[type=number]:focus,
.alt-app #taskModal input[type=tel]:focus,
.alt-app #adminModal input[type=tel]:focus,
.alt-app #taskModal input[type=search]:focus,
.alt-app #adminModal input[type=search]:focus,
.alt-app #taskModal input[type=url]:focus,
.alt-app #adminModal input[type=url]:focus,
.alt-app #taskModal input[type=time]:focus,
.alt-app #adminModal input[type=time]:focus,
.alt-app #taskModal input[type=datetime-local]:focus,
.alt-app #adminModal input[type=datetime-local]:focus,
.alt-app #taskModal textarea:focus,
.alt-app #adminModal textarea:focus,
.alt-app #taskModal select:focus,
.alt-app #adminModal select:focus{ border-color:var(--accent); }
.alt-app #taskModal input[type=checkbox],
.alt-app #adminModal input[type=checkbox],
.alt-app #taskModal input[type=radio],
.alt-app #adminModal input[type=radio]{ accent-color:var(--accent); }
.alt-app #taskModal textarea,
.alt-app #adminModal textarea{ resize:vertical; min-height:80px; font-family:inherit; }
.alt-app #taskModal .rich-text-field,
.alt-app #adminModal .rich-text-field{ background:var(--panel-2); color:var(--text); border:1px solid var(--border-strong); border-radius:var(--radius-sm); padding:7px 10px; font-size:13px; min-height:110px; max-height:320px; overflow-y:auto; line-height:1.5; }
/* ---------- HOW TALL THE DESCRIPTION IS ----------
   A fix ported from the classic board that the default experience never got: CSS/components.css
   sizes this box from the viewport (`clamp(160px, 38vh, 520px)`), but this file's own
   `(1,2,0)` rule beat it at `(1,0,0)`, so the dead flat 110/320 pair won here. 224px is the
   individual editor's own floor (`.fill-richtext`, alt-embed-task.css), so the two editors a
   reader moves between start from one number; the ceiling's floor is 224 too, since a max-height
   below the min-height can never reach it. `#taskModal` only — `#adminModal` has no
   `.rich-text-field` today, checked across all five modules that build its panes; a team
   description editor, if one is ever added, deserves its own deliberate floor rather than an
   inherited one.
   Retires `altTeamDescSize()` (JS/alt/alt-team-task.js) by being correct, not by racing it: that
   function defers to whatever floor the stylesheet actually resolves. */
.alt-app #taskModal .rich-text-field{
  min-height:clamp(224px, 38vh, 520px);
  max-height:clamp(224px, 46vh, 640px);
}
/* ---------- THE DESCRIPTION'S TOOL STRIP, AND THE ONE GAP IT WAS MISSING ----------
   `#altTaskDescTools` stacks the formatting bar and a `.control-row` ("Tidy formatting with
   AI"); neither carried a margin, so the gap measured 0px and the button read as part of the
   bar. `--a-2` (8px), on the row not the bar — the bar is `hidden` when unavailable, and a
   margin on a hidden element would describe a gap that only sometimes exists. */
.alt-app #taskModal #altTaskDescTools > .control-row{ margin-top:var(--a-2); }


/* ================= THE TASK'S CHECKLIST =================
   The `.tcl-*` component moved to CSS/checklist.css, unprefixed, so this dialog and
   classic_tasks.html's `#panel` shared one definition instead of two that drifted (they had
   already disagreed on tick size, category padding and the drag classes). classic_tasks.html is
   retired (2026-09-11); the other consumer of that shared definition is now tasks.html's own
   `#panel`. See CSS/checklist.css for the rules. */

/* The section body itself, not `.tcl-*` — CSS/checklist.css knows nothing of
   `#taskSecChecklist`, this dialog's own host; CSS/components.css turns the shared gap off for
   this pane, so this states its own spacing (host chrome, not component). */
.alt-app #taskModal #taskSecChecklist{ padding-bottom:var(--a-3); }

.alt-app #taskModal .rich-text-field:focus,
.alt-app #adminModal .rich-text-field:focus{ border-color:var(--accent); }
.alt-app #taskModal .rich-text-field[contenteditable="false"],
.alt-app #adminModal .rich-text-field[contenteditable="false"]{ opacity:.65; cursor:default; }
.alt-app #taskModal .rich-text-field > *:first-child,
.alt-app #adminModal .rich-text-field > *:first-child{ margin-top:0; }
.alt-app #taskModal .rich-text-field > *:last-child,
.alt-app #adminModal .rich-text-field > *:last-child{ margin-bottom:0; }
.alt-app #taskModal .rich-text-field p,
.alt-app #adminModal .rich-text-field p{ margin:0 0 8px; }
.alt-app #taskModal .rich-text-field ul,
.alt-app #adminModal .rich-text-field ul,
.alt-app #taskModal .rich-text-field ol,
.alt-app #adminModal .rich-text-field ol{ margin:0 0 8px; padding-left:22px; }
.alt-app #taskModal .rich-text-field li,
.alt-app #adminModal .rich-text-field li{ margin-bottom:3px; }
.alt-app #taskModal .rich-text-field h1,
.alt-app #adminModal .rich-text-field h1,
.alt-app #taskModal .rich-text-field h2,
.alt-app #adminModal .rich-text-field h2,
.alt-app #taskModal .rich-text-field h3,
.alt-app #adminModal .rich-text-field h3,
.alt-app #taskModal .rich-text-field h4,
.alt-app #adminModal .rich-text-field h4{ font-size:14px; font-weight:700; margin:10px 0 5px; }
.alt-app #taskModal .rich-text-field blockquote,
.alt-app #adminModal .rich-text-field blockquote{ margin:0 0 8px; padding-left:10px; border-left:2px solid var(--border); color:var(--text-dim); }
.alt-app #taskModal .rich-text-field table,
.alt-app #adminModal .rich-text-field table{ border-collapse:collapse; margin-bottom:8px; }
.alt-app #taskModal .rich-text-field td,
.alt-app #adminModal .rich-text-field td,
.alt-app #taskModal .rich-text-field th,
.alt-app #adminModal .rich-text-field th{ border:1px solid var(--border-soft); padding:3px 6px; }
.alt-app #taskModal .rich-text-field:empty::before,
.alt-app #adminModal .rich-text-field:empty::before{ content:attr(data-placeholder); color:var(--text-faint); }
.alt-app #taskModal select.board-switcher,
.alt-app #adminModal select.board-switcher{ flex:0 1 210px; min-width:140px; max-width:260px; font-weight:600; }
@media (max-width:1520px){
.alt-app #taskModal select.board-switcher,
.alt-app #adminModal select.board-switcher{ flex:0 1 190px; }
}
.alt-app #taskModal .settings-board-row select,
.alt-app #adminModal .settings-board-row select{ width:auto; min-width:180px; max-width:100%; }
.alt-app #taskModal .settings-board-row select:disabled,
.alt-app #adminModal .settings-board-row select:disabled{ opacity:.7; }
.alt-app #taskModal .assignee-note,
.alt-app #adminModal .assignee-note{ grid-column:2; font-size:11px; line-height:1.45; color:var(--text-dim); margin-top:4px; }
.alt-app #taskModal .assignee-note.err,
.alt-app #adminModal .assignee-note.err{ color:var(--red-text); }
.alt-app #taskModal .tag-chip-row,
.alt-app #adminModal .tag-chip-row{ display:flex; flex-wrap:wrap; gap:6px; }
.alt-app #taskModal .tag-pick,
.alt-app #adminModal .tag-pick{ display:inline-flex; align-items:center; gap:5px; padding:3px 9px; border-radius:999px; cursor:pointer; border:1px solid var(--border); background:var(--panel-2); font-size:12px; color:var(--text-dim); user-select:none; }
.alt-app #taskModal .tag-pick .dot,
.alt-app #adminModal .tag-pick .dot{ width:7px; height:7px; border-radius:50%; flex-shrink:0; }
.alt-app #taskModal .tag-pick-toggle,
.alt-app #adminModal .tag-pick-toggle{ background:transparent; border:1px dashed var(--border); border-radius:999px; padding:3px 10px; font-size:12px; color:var(--text-faint); }
.alt-app #taskModal .tag-pick-toggle:hover,
.alt-app #adminModal .tag-pick-toggle:hover{ border-color:var(--accent); color:var(--accent-text); }
.alt-app #taskModal .tag-pick.on,
.alt-app #adminModal .tag-pick.on{ color:var(--text); }
.alt-app #taskModal .tag-pick.disabled,
.alt-app #adminModal .tag-pick.disabled{ cursor:default; opacity:.55; }
.alt-app #taskModal .form-row,
.alt-app #adminModal .form-row{ display:flex; flex-direction:column; gap:7px; margin-bottom:14px; }
.alt-app #taskModal .form-row label,
.alt-app #adminModal .form-row label{ font-size:12px; color:var(--text-dim); font-weight:600; }
.alt-app #taskModal .form-row-inline,
.alt-app #adminModal .form-row-inline{ display:flex; gap:12px; }
.alt-app #taskModal .form-row-inline > .form-row,
.alt-app #adminModal .form-row-inline > .form-row{ flex:1; }
/* THE TITLE ROW — label and field on one line, scoped to `.form-row.title-field-row` (an extra
   class on ONE div), never a bare `.form-row` change — that's a shared primitive across many
   dialogs. Font, not border, is what moves: `--a-display` is the same token Notes' own title
   uses, so this title follows the same Application-font setting. The border is untouched —
   this is a plain bordered control, not a heading-style field like `.a-note-title`. */
/* The action row aligns to the field, not the label — `--tt-label-w` sets both the label's
   width and `#followupField`'s indent, by construction rather than a measured offset. */
.alt-app #taskModal{ --tt-label-w:40px; }
.alt-app #taskModal #followupField{ padding-left:calc(var(--tt-label-w) + 10px); }
.alt-app #taskModal .form-row.title-field-row{
  display:flex; flex-direction:row; align-items:center; gap:10px; flex-wrap:wrap;
}
.alt-app #taskModal .form-row.title-field-row label{
  flex:0 0 var(--tt-label-w);
}
.alt-app #taskModal .form-row.title-field-row input[type=text]{
  /* min-width:0 is load-bearing on a flex child holding free text — without it the input
     pushes the dialog wider instead of wrapping. Basis is 0%, not a pixel floor — measured at
     320px, `flex:1 1 200px` wrapped the row the owner said must never wrap, because CSS
     resolves the line-break from each item's flex BASIS before shrinking. `flex:1 1 0%` makes
     the hypothetical size 0, so the break never triggers on this field's own width. */
  flex:1 1 0%; min-width:0;
  font-family:var(--a-display); font-size:19px; font-weight:600; line-height:1.3;
}
.alt-app #taskModal .cfg-dot svg,
.alt-app #adminModal .cfg-dot svg{ display:block; }
.alt-app #taskModal .readonly-note,
.alt-app #adminModal .readonly-note{ background:var(--gray-soft); border-radius:var(--radius-sm); padding:8px 10px; font-size:12px; color:var(--text-dim); margin-bottom:12px; }
.alt-app #taskModal .person-row select,
.alt-app #adminModal .person-row select{ width:100%; min-width:0; padding:6px 8px; }
.alt-app #taskModal .add-row input,
.alt-app #adminModal .add-row input{ flex:1 1 140px; min-width:0; }
.alt-app #taskModal .lane-complete-toggle input,
.alt-app #adminModal .lane-complete-toggle input{ margin:0; cursor:pointer; }
.alt-app #taskModal .cfg-row input[type=text],
.alt-app #adminModal .cfg-row input[type=text]{ flex:1; background:var(--panel); border:1px solid var(--border-strong); border-radius:6px; color:var(--text); padding:5px 8px; font-size:13px; }
.alt-app #taskModal .cfg-row input[type=color],
.alt-app #adminModal .cfg-row input[type=color],
.alt-app #taskModal .add-row input[type=color],
.alt-app #adminModal .add-row input[type=color]{ width:28px; height:28px; padding:0; border:1px solid var(--border-strong); border-radius:6px; background:none; flex:0 0 auto; }
.alt-app #taskModal .add-row input[type=color],
.alt-app #adminModal .add-row input[type=color]{ width:32px; height:32px; }
.alt-app #taskModal .group-row input[type=text].group-name,
.alt-app #adminModal .group-row input[type=text].group-name{ width:100%; background:transparent; border:1px solid transparent; border-radius:6px; padding:3px 6px; margin-left:-6px; font-size:13px; font-weight:600; color:var(--text); }
.alt-app #taskModal .group-row input[type=text].group-name:hover,
.alt-app #adminModal .group-row input[type=text].group-name:hover{ background:var(--panel-2); border-color:var(--border); }
.alt-app #taskModal .group-row input[type=text].group-name:focus,
.alt-app #adminModal .group-row input[type=text].group-name:focus{ background:var(--panel-2); border-color:var(--accent); }
.alt-app #taskModal .cfg-status,
.alt-app #adminModal .cfg-status{ font-size:12px; color:var(--text-faint); margin-top:8px; min-height:1em; }
/* The one `.cfg-status` in this modal NOT stacked under a field — `#taskModalSave` sits inside
   a flex row (the tab row now), whose centring includes margins, so an inherited margin-top
   pulled its text off the centre line. `.cfg-status.save-status` reaches only that one element,
   by its own compound class, so every sibling instance keeps its 8px of daylight. Margin removed
   outright rather than cancelled with a negative one. */
.alt-app #taskModal .cfg-status.save-status{ margin-top:0; }
.alt-app #taskModal .cfg-status.ok,
.alt-app #adminModal .cfg-status.ok{ color:var(--green-text); }
.alt-app #taskModal .cfg-status.err,
.alt-app #adminModal .cfg-status.err{ color:var(--red-text); }
.alt-app #taskModal .add-row input,
.alt-app #adminModal .add-row input{ flex:1; }
.alt-app #taskModal .status-note,
.alt-app #adminModal .status-note{ font-size:12px; color:var(--text-faint); margin-top:10px; }
/* THE SAVE STATE LIVES IN THIS LINE, and one of its four states is "your last change was not
   saved". A refusal reported in the same faint grey as a creation date is a refusal nobody
   reads — see setTaskModalSaveState() in JS/features/board-task-modal.js. */
.alt-app #taskModal .status-note.err{ color:var(--red-text); font-weight:600; }
.alt-app #taskModal .acct-dest-controls select,
.alt-app #adminModal .acct-dest-controls select{ width:auto; min-width:150px; padding:5px 8px; font-size:12px; }
.alt-app #taskModal .acct-verify input,
.alt-app #adminModal .acct-verify input{ width:auto; max-width:120px; padding:5px 8px; font-size:12px; letter-spacing:.18em; }
.alt-app #taskModal .account-field input,
.alt-app #adminModal .account-field input{ background:var(--panel-2); color:var(--text); border:1px solid var(--border-strong); border-radius:var(--radius-sm); padding:7px 10px; font-size:13px; width:100%; }
.alt-app #taskModal .account-field input:focus,
.alt-app #adminModal .account-field input:focus{ border-color:var(--accent); }
.alt-app #taskModal .account-field input[readonly],
.alt-app #adminModal .account-field input[readonly]{ opacity:.65; cursor:default; }
.alt-app #taskModal button:disabled,
.alt-app #adminModal button:disabled,
.alt-app #taskModal input:disabled,
.alt-app #adminModal input:disabled,
.alt-app #taskModal select:disabled,
.alt-app #adminModal select:disabled,
.alt-app #taskModal textarea:disabled,
.alt-app #adminModal textarea:disabled,
.alt-app #taskModal .is-disabled,
.alt-app #adminModal .is-disabled{ opacity:.55; background:var(--gray-soft); border-color:var(--border-soft); cursor:not-allowed; }

/* `button.btn`, `a.btn` and `button.icon-btn` are the classic dialogs' own button primitive —
   not `.a-btn`, since swapping it in would mean editing markup this page copies verbatim.
   Without these, Save/Delete/Follow-up rendered as unstyled native buttons on a dark card. */
.alt-app #taskModal button.btn,
.alt-app #adminModal button.btn{ background:var(--panel-2); color:var(--text); border:1px solid var(--border-strong); border-radius:var(--radius-sm); padding:7px 12px; font-size:13px; font-weight:600; display:inline-flex; align-items:center; justify-content:center; gap:6px; white-space:nowrap; }
.alt-app #taskModal button.btn:hover,
.alt-app #adminModal button.btn:hover{ border-color:var(--accent); color:var(--accent-text); }
.alt-app #taskModal button.btn.primary,
.alt-app #adminModal button.btn.primary{ background:var(--accent-fill); border-color:var(--accent); color:#fff; }
.alt-app #taskModal button.btn.danger,
.alt-app #adminModal button.btn.danger{ background:var(--red-soft); border-color:var(--red); color:var(--red-text); }
.alt-app #taskModal button.btn:disabled,
.alt-app #adminModal button.btn:disabled{ opacity:.5; cursor:not-allowed; }
.alt-app #taskModal button.btn.small,
.alt-app #adminModal button.btn.small{ padding:5px 9px; font-size:12px; align-self:flex-end; }
.alt-app #taskModal a.btn,
.alt-app #adminModal a.btn{ background:var(--panel-2); color:var(--text); border:1px solid var(--border-strong); border-radius:var(--radius-sm); padding:7px 12px; font-size:13px; font-weight:600; display:inline-flex; align-items:center; gap:6px; white-space:nowrap; text-decoration:none; cursor:pointer; font-family:inherit; }
.alt-app #taskModal a.btn:hover,
.alt-app #adminModal a.btn:hover{ border-color:var(--accent); color:var(--accent-text); }
.alt-app #taskModal a.btn.small,
.alt-app #adminModal a.btn.small{ padding:5px 9px; font-size:12px; }
.alt-app #taskModal a.btn svg,
.alt-app #adminModal a.btn svg,
.alt-app #taskModal button.btn svg,
.alt-app #adminModal button.btn svg{ flex:0 0 auto; }
.alt-app #taskModal button.btn.active,
.alt-app #adminModal button.btn.active{ border-color:var(--accent); color:var(--accent-text); background:var(--accent-soft); }
.alt-app #taskModal button.icon-btn,
.alt-app #adminModal button.icon-btn{ background:transparent; border:none; border-radius:6px; color:var(--text-dim); padding:4px; display:flex; align-items:center; justify-content:center; font-size:16px; }
.alt-app #taskModal button.icon-btn:hover,
.alt-app #adminModal button.icon-btn:hover{ background:var(--panel-2); color:var(--text); }
.alt-app #taskModal button.icon-btn.danger,
.alt-app #adminModal button.icon-btn.danger{ color:var(--red-text); }
.alt-app #taskModal button.icon-btn.danger:hover,
.alt-app #adminModal button.icon-btn.danger:hover{ background:var(--red-soft); }
.alt-app #taskModal .section-toolbar .btn.small,
.alt-app #adminModal .section-toolbar .btn.small{ align-self:center; }
.alt-app #taskModal .person-actions > .btn,
.alt-app #adminModal .person-actions > .btn{ flex:0 0 auto; white-space:nowrap; }
.alt-app #taskModal .cfg-row .btn,
.alt-app #adminModal .cfg-row .btn{ flex:0 0 auto; align-self:center; white-space:nowrap; }
.alt-app #taskModal .topics-grid > .btn,
.alt-app #adminModal .topics-grid > .btn{ width:100%; justify-content:center; }
@media (max-width: 880px){
.alt-app #taskModal .topics-grid > .btn,
.alt-app #adminModal .topics-grid > .btn{ width:auto; }
}
.alt-app #taskModal .group-actions .btn,
.alt-app #adminModal .group-actions .btn{ font-variant-numeric:tabular-nums; }
.alt-app #taskModal .group-row .group-actions .btn,
.alt-app #adminModal .group-row .group-actions .btn{ align-self:auto; }

/* ---------- the settings panes ---------- */
.alt-app #adminModal .avatar-dot{ width:26px; height:26px; border-radius:50%; background:var(--accent-fill); color:#fff; font-size:11px; font-weight:700; display:flex; align-items:center; justify-content:center; margin-left:-8px; border:2px solid var(--panel); }
.alt-app #adminModal .avatar-dot:first-child{ margin-left:0; }
.alt-app #adminModal .avatar-dot[data-tooltip]{ position:relative; cursor:default; }
.alt-app #adminModal .avatar-dot[data-tooltip]:hover::after{ content:attr(data-tooltip); position:absolute; top:130%; right:0; left:auto; background:var(--panel); color:var(--text); border:1px solid var(--border); padding:5px 9px; border-radius:6px; font-size:12px; font-weight:500; white-space:nowrap; z-index:var(--z-float); box-shadow:0 4px 14px rgba(0,0,0,.35); pointer-events:none; }
.alt-app #adminModal .avatar-dot[data-tooltip]:hover::before{ content:''; position:absolute; top:100%; right:8px; border:5px solid transparent; border-bottom-color:var(--border); z-index:calc(var(--z-float) + 1); pointer-events:none; }
.alt-app #adminModal .modal-title-row,
.alt-app #adminModal .admin-tabs{ flex-shrink:0; }
.alt-app #adminModal .admin-pane.active{ display:flex; flex-direction:column; flex:1 1 auto; min-height:0; overflow-y:auto; }
.alt-app #adminModal .settings-board-row{ display:flex; align-items:center; gap:9px; flex-wrap:wrap; margin:0 0 14px; padding:0 0 12px; border-bottom:1px solid var(--border-soft); }
.alt-app #adminModal .settings-board-label{ font-size:11px; text-transform:uppercase; letter-spacing:.4px; color:var(--text-faint); font-weight:700; }
.alt-app #adminModal .settings-board-row select{ width:auto; min-width:180px; max-width:100%; }
.alt-app #adminModal .settings-board-note{ font-size:12px; color:var(--text-dim); }
.alt-app #adminModal .settings-board-row select:disabled{ opacity:.7; }
.alt-app #adminModal .section-toolbar{ display:flex; justify-content:flex-end; gap:6px; margin-bottom:4px; }
.alt-app #adminModal .section-toolbar .btn.small{ align-self:center; }
.alt-app #adminModal .inactive-head{ display:flex; align-items:center; gap:7px; cursor:pointer; user-select:none; font-size:12px; font-weight:600; color:var(--text-faint); margin:18px 0 8px; padding-top:10px; border-top:1px solid var(--border-soft); }
.alt-app #adminModal .inactive-head:hover{ color:var(--text-dim); }
.alt-app #adminModal .inactive-head.collapsed .chev{ transform:rotate(-90deg); }
.alt-app #adminModal .inactive-badge{ font-size:11px; letter-spacing:.04em; text-transform:uppercase; background:var(--gray-soft); color:var(--text-faint); border-radius:999px; padding:2px 7px; flex-shrink:0; }
.alt-app #adminModal .import-dropzone{ border:1.5px dashed var(--border); border-radius:var(--radius-sm); padding:20px; text-align:center; color:var(--text-dim); font-size:13px; cursor:pointer; }
.alt-app #adminModal .import-dropzone.dragover{ border-color:var(--accent); background:var(--accent-soft); color:var(--text); }
.alt-app #adminModal .import-hint{ font-size:12px; color:var(--text-faint); line-height:1.55; margin-top:12px; }
.alt-app #adminModal .import-hint code{ background:var(--panel-2); padding:1px 4px; border-radius:3px; font-size:11px; }
.alt-app #adminModal .team-row-name{ flex:1; min-width:0; font-weight:600; font-size:13px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.alt-app #adminModal .team-detail{ margin:10px 0 4px; padding:11px 13px; background:var(--panel-2); border:1px solid var(--border-soft); border-radius:var(--radius-sm); }
.alt-app #adminModal .team-detail h4{ margin:0 0 8px; font-size:12px; text-transform:uppercase; letter-spacing:.4px; color:var(--text-faint); }
.alt-app #adminModal .team-detail-grid{ display:flex; gap:18px; flex-wrap:wrap; }
.alt-app #adminModal .team-stat .n{ font-size:19px; font-weight:700; line-height:1.1; }
.alt-app #adminModal .team-stat .l{ font-size:11px; color:var(--text-faint); text-transform:uppercase; letter-spacing:.4px; }
.alt-app #adminModal .admin-tabs{ display:flex; gap:4px; margin-bottom:14px; background:var(--panel-2); border-radius:var(--radius-sm); padding:3px; overflow-x:auto; }
.alt-app #adminModal .admin-tab{ flex:1; background:transparent; border:none; padding:7px; border-radius:6px; color:var(--text-dim); font-weight:600; font-size:12px; white-space:nowrap; }
.alt-app #adminModal .admin-tab.active{ background:var(--accent-fill); color:#fff; }
/* THE OKRs TAB'S GREY WASH, which the shared `.is-disabled` rule above never actually painted
   here — it ties in specificity with the bare `.admin-tab` rule, and `.admin-tab`'s
   `background:transparent` sits below and wins, leaving a disabled tab indistinguishable from
   an inactive one. Fixed by specificity, not reordering: `.admin-tab.is-disabled` carries one
   more class than either colliding rule, so it wins without touching the shared rule other
   hosts still need. */
.alt-app #adminModal .admin-tab.is-disabled{ background:var(--gray-soft); border-color:var(--border-soft); }
.alt-app #adminModal .admin-pane{ display:none; }
.alt-app #adminModal .admin-pane.active{ display:block; }
.alt-app #adminModal .people-grid{ display:grid; grid-template-columns:minmax(170px, 1.5fr) 122px minmax(150px, 1.1fr) minmax(150px, 1.1fr) 292px; gap:8px 10px; align-items:center; }
.alt-app #adminModal .person-head > :last-child{ text-align:right; }
.alt-app #adminModal .person-head{ padding:2px 4px 6px; border-bottom:1px solid var(--border-soft); font-size:11px; text-transform:uppercase; letter-spacing:.4px; color:var(--text-faint); font-weight:700; position:sticky; top:0; z-index:1; background:var(--panel); }
.alt-app #adminModal .person-row{ padding:8px 4px; border-bottom:1px solid var(--border-soft); }
.alt-app #adminModal .person-row:hover{ background:var(--panel-2); }
.alt-app #adminModal .person-id{ min-width:0; }
.alt-app #adminModal .person-id .name{ font-size:13px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.alt-app #adminModal .person-id .email{ font-size:12px; color:var(--text-faint); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.alt-app #adminModal .person-row select{ width:100%; min-width:0; padding:6px 8px; }
.alt-app #adminModal .person-actions{ display:flex; gap:6px; align-items:center; justify-content:flex-end; flex-wrap:wrap; }
.alt-app #adminModal .person-actions > .btn{ flex:0 0 auto; white-space:nowrap; }
@media (max-width: 880px){
.alt-app #adminModal .people-grid{ grid-template-columns:1fr; gap:6px; }
}
@media (max-width: 880px){
.alt-app #adminModal .person-actions{ flex-wrap:wrap; }
}
@media (max-width: 880px){
.alt-app #adminModal .person-head{ display:none; }
}
@media (max-width: 880px){
.alt-app #adminModal .person-actions{ justify-content:flex-start; }
}
.alt-app #adminModal .invite-panel{ margin:0 0 12px; padding:9px 11px; background:var(--panel-2); border:1px solid var(--border-soft); border-radius:var(--radius-sm); }
.alt-app #adminModal .invite-copy{ font-size:12px; color:var(--text-dim); line-height:1.45; margin-bottom:8px; }
.alt-app #adminModal .invite-row{ margin:0; }
/* THE INVITE FEEDBACK SITS BESIDE THE CONTROL THAT CAUSED IT. It used to print at the bottom of
   the People pane, off-screen on any real team roster. Wraps rather than truncates — these
   sentences are long on purpose, so the status takes the remaining width and wraps under the
   button; `min-width:0` is what lets it wrap at all inside a flex row. */
.alt-app #adminModal .invite-actions{
  display:flex; align-items:flex-start; gap:10px; flex-wrap:wrap; margin-top:8px;
}
.alt-app #adminModal .invite-actions .cfg-status{ margin:0; flex:1 1 220px; min-width:0; }
.alt-app #adminModal .invite-actions .btn{ flex:0 0 auto; }
.alt-app #adminModal .people-filter-row{ margin:0 0 10px; padding:0 4px; }
.alt-app #adminModal .people-filter-label{ font-size:11px; text-transform:uppercase; letter-spacing:.4px; color:var(--text-faint); font-weight:700; }
.alt-app #adminModal .people-filter-row .ms-field{ flex:0 1 240px; }
.alt-app #adminModal .people-filter-count{ font-size:12px; color:var(--text-faint); }
.alt-app #adminModal .people-search{ width:auto; min-width:150px; max-width:220px; flex:0 1 190px; }
.alt-app #adminModal .roster-row{ display:flex; align-items:center; gap:8px; padding:8px 4px; border-bottom:1px solid var(--border-soft); }
.alt-app #adminModal .roster-row .name{ font-size:13px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.alt-app #adminModal .roster-row .email{ font-size:12px; color:var(--text-faint); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.alt-app #adminModal .roster-row .role-badge{ font-size:11px; padding:2px 8px; border-radius:999px; background:var(--panel-2); color:var(--text-dim); }
.alt-app #adminModal .roster-row .role-badge.admin{ background:var(--accent-soft); color:var(--accent-text); }
.alt-app #adminModal .add-row{ display:flex; align-items:center; gap:8px; margin-top:10px; flex-wrap:wrap; }
/* The add row leads its list now, so its spacing moved below it — the old top margin pushed
   against the thing above while the row ended flush on the list beneath (measured: 0px on
   Topics). The redundant top margin comes off wherever the row is genuinely first. */
.alt-app #adminModal .add-row{ margin-bottom:12px; }
.alt-app #adminModal .stg-sec-body > .add-row:first-child,
.alt-app #adminModal .admin-pane > .add-row,
.alt-app #adminModal .admin-pane > .stg-pane-head + .add-row{ margin-top:0; }
.alt-app #adminModal .add-row input{ flex:1 1 140px; min-width:0; }
.alt-app #adminModal .lane-complete-toggle{ display:inline-flex; align-items:center; gap:6px; white-space:nowrap; font-size:12px; color:var(--text-dim); cursor:pointer; }
.alt-app #adminModal .lane-complete-toggle input{ margin:0; cursor:pointer; }
.alt-app #adminModal .lane-complete-toggle:hover{ color:var(--text); }
.alt-app #adminModal .cfg-row{ display:flex; align-items:center; gap:8px; margin-bottom:6px; }
.alt-app #adminModal .cfg-row input[type=text]{ flex:1; background:var(--panel); border:1px solid var(--border-strong); border-radius:6px; color:var(--text); padding:5px 8px; font-size:13px; }
.alt-app #adminModal .cfg-row input[type=color],
.alt-app #adminModal .add-row input[type=color]{ width:28px; height:28px; padding:0; border:1px solid var(--border-strong); border-radius:6px; background:none; flex:0 0 auto; }
.alt-app #adminModal .add-row input[type=color]{ width:32px; height:32px; }
.alt-app #adminModal .cfg-row .btn{ flex:0 0 auto; align-self:center; white-space:nowrap; }
.alt-app #adminModal .cfg-row .cfg-swatch-gap{ width:28px; flex:0 0 auto; }
.alt-app #adminModal .cfg-row .cfg-pick{ width:15px; height:15px; flex:0 0 auto; accent-color:var(--accent); margin:0; }
.alt-app #adminModal .section-toolbar .bulk-count{ margin-right:auto; font-size:12px; color:var(--text-faint); align-self:center; }
.alt-app #adminModal .tag-bulk-bar{ padding-bottom:6px; border-bottom:1px solid var(--border-soft); margin-bottom:8px; }
.alt-app #adminModal .cfg-row .cfg-pseudo-label{ flex:1; font-size:13px; color:var(--text-dim); font-style:italic; }
.alt-app #adminModal .topics-grid{ display:grid; grid-template-columns:22px minmax(0,1fr) 110px 138px 84px; gap:6px 8px; align-items:center; }
.alt-app #adminModal .topic-id{ display:flex; align-items:center; gap:8px; min-width:0; }
.alt-app #adminModal .topic-head{ padding:2px 0 6px; border-bottom:1px solid var(--border-soft); font-size:11px; text-transform:uppercase; letter-spacing:.4px; color:var(--text-faint); font-weight:700; position:sticky; top:0; z-index:1; background:var(--panel); }
.alt-app #adminModal .topic-head > :nth-child(n+3){ text-align:center; }
.alt-app #adminModal .topics-grid > .btn{ width:100%; justify-content:center; }
.alt-app #adminModal .reorder-gap{ width:22px; }
@media (max-width: 880px){
.alt-app #adminModal .topics-grid{ grid-template-columns:1fr; gap:6px; }
}
@media (max-width: 880px){
.alt-app #adminModal .topic-head{ display:none; }
}
@media (max-width: 880px){
.alt-app #adminModal .topics-grid > .btn{ width:auto; }
}
.alt-app #adminModal .pane-intro{ font-size:12px; color:var(--text-dim); line-height:1.5; margin-bottom:12px; }
.alt-app #adminModal .cfg-row.group-row{ display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:center; column-gap:16px; padding:9px 0; margin-bottom:0; border-bottom:1px solid var(--border-soft); }
.alt-app #adminModal .cfg-row.group-row:last-child{ border-bottom:none; }
.alt-app #adminModal .group-id{ min-width:0; display:flex; flex-direction:column; gap:2px; }
.alt-app #adminModal .group-actions{ display:flex; align-items:center; gap:6px; }
.alt-app #adminModal .group-actions .btn{ font-variant-numeric:tabular-nums; }
.alt-app #adminModal .group-row .group-actions .btn{ align-self:auto; }
.alt-app #adminModal .group-row input[type=text].group-name{ width:100%; background:transparent; border:1px solid transparent; border-radius:6px; padding:3px 6px; margin-left:-6px; font-size:13px; font-weight:600; color:var(--text); }
.alt-app #adminModal .group-row input[type=text].group-name:hover{ background:var(--panel-2); border-color:var(--border); }
.alt-app #adminModal .group-row input[type=text].group-name:focus{ background:var(--panel-2); border-color:var(--accent); }
.alt-app #adminModal .group-sub{ font-size:11px; color:var(--text-faint); line-height:1.4; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.alt-app #adminModal .group-sub.warn{ color:var(--warn-text); }
.alt-app #adminModal .group-editor{ margin:2px 0 12px 10px; padding:8px 0 8px 10px; border-left:2px solid var(--border-soft); }
.alt-app #adminModal .group-editor-head{ font-size:11px; text-transform:uppercase; letter-spacing:.4px; color:var(--text-faint); font-weight:700; margin-bottom:6px; }
.alt-app #adminModal .add-row input{ flex:1; }
.alt-app #adminModal .empty-state{ color:var(--text-faint); font-size:13px; padding:30px; text-align:center; }

/* ---------- the two dialogs' own frames ---------- */
.alt-app #adminModal .modal-card{ display:flex; flex-direction:column; overflow:hidden; }
.alt-app #adminModal .modal-title-row,
.alt-app #adminModal .admin-tabs{ flex-shrink:0; }
.alt-app #adminModal .admin-pane.active{ display:flex; flex-direction:column; flex:1 1 auto; min-height:0; overflow-y:auto; }
/* The same crushed-card bug this file found independently (a `.stg-sec` flex item with
   `overflow:hidden` crushes toward 0 rather than letting the pane scroll — reproduced as
   `#inviteRow` at 2px tall over a 61-person roster) is fixed at its own component,
   `.stg-sec{flex-shrink:0}` in alt-settings-stride.css §3 — every host gets it, not just this one. */

/* ================= 4a · THE TEAMS TAB'S TWO-COLUMN LAYOUT =================
   PRODUCT OWNER: "In Teams, change to a two row layout AFTER team insights. Follow the sequence
   provided in the screen shot where team insights has its own row and delete this team has its
   own row... Ordering of the tabs should follow the number sequence provided in the screen
   shot." "Two row" means two COLUMN. His sequence is declared once, as data, in
   JS/features/team-pane.js's `TEAM_PANE_GRID_ORDER`; this rule only lays out whatever DOM order
   that array produces.
   Scoped to `#teamPane` specifically, not a redrawn `.admin-pane.active` — this file already
   declares that class-only selector three times, unconditionally, so a fourth would depend on
   source order. The second id here outranks all three regardless of position.
   `grid-auto-rows:min-content` is load-bearing: without it, every implicit row sized ~30px
   regardless of content, so an open card (measured: a 1842px-tall Customize email builder)
   overflowed into the row below — invisible because every card collapses at boot, so a probe
   that never opens one sees tidy headers and nothing wrong.
   `align-items` is `stretch`, not `start`, ON THE OWNER'S EXPLICIT INSTRUCTION after seeing a
   ragged-bottom pairing — the same pattern already used on My Settings' tabs and
   `.org-row-2` (alt-org-settings.css), with the same guard: `.stg-sec{min-height:min-content}`
   below means a stretched card can only be padded, never clipped. The cost is real and not
   hidden: the (OKR toggle, Customize email) pair, both open, leaves over a thousand pixels of
   empty space beneath the toggle — worth the owner's attention if he opens that pair. */
.alt-app #adminModal #teamPane.active{
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  grid-auto-rows:min-content;
  align-items:stretch;
  column-gap:14px;
  /* Matches the row rhythm every other settings pane already has
     (`.admin-pane.active{row-gap:10px}`, CSS/alt/alt-settings-stride.css) — grid's `row-gap` is
     the same property flexbox uses, so this restates that pane's own vertical spacing at the
     specificity this layout needs, rather than fighting it. */
  row-gap:10px;
}
/* THE FULL-WIDTH ROWS — Team Insights and Delete this team each sit alone, per the owner's
   screenshot; Your teams is included since it shares the same grid container. `.stg-grid-solo`
   handles the one case that cannot be a static list: five of eight paired cards are
   independently gated, so whichever ends up last on an odd count is a runtime fact
   (stgTeamPaneGridRepaint(), team-pane.js).
   `#teamEmailBuilderRow` spans both columns rather than being reordered to pair with a
   similar-height card — reordering `TEAM_PANE_GRID_ORDER` would break the owner's numbered
   sequence. It is the measured outlier (~1842px open), named by id rather than a height
   threshold, so `align-items:stretch` never has anything to stretch it against. */
.alt-app #adminModal #teamPane.active > .stg-pane-head,
.alt-app #adminModal #teamPane.active > #yourTeamsSection,
.alt-app #adminModal #teamPane.active > #teamInsightsLaunch,
.alt-app #adminModal #teamPane.active > #teamEmailBuilderRow,
.alt-app #adminModal #teamPane.active > #teamDeleteRow,
.alt-app #adminModal #teamPane.active .stg-grid-solo{
  grid-column:1 / -1;
}
/* Team details and Team admins become two grid cells, not one — team-config.js builds both as
   children of this single static mount, so `display:contents` removes the host div's own box
   from layout while the DOM stays exactly as built. Changes painted layout only, not focus order. */
.alt-app #adminModal #teamConfigHost{
  display:contents;
}
/* The same crushed-card bug this file already fixed once, in a new layout mode — `flex-shrink`
   is a no-op once `#teamPane.active` is GRID rather than flex, but Grid has the identical
   automatic-minimum-size rule for `min-height:auto` on an `overflow:hidden` item. Measured by
   forcing every card open: the outer `.stg-sec` clipped to ~31px, roughly the header alone, over
   a 1726px body. `min-height:min-content` is the grid analogue of `flex-shrink:0`. */
.alt-app #adminModal #teamPane.active .stg-sec{
  min-height:min-content;
}
/* Below 880px — this file's own established breakpoint (People and Topics grids collapse at
   the same width) — the pane stacks to one column; nothing narrowed it before this rule. */
@media (max-width: 880px){
.alt-app #adminModal #teamPane.active{
  grid-template-columns:1fr;
}
}

/* ================= 5a · THE STRIDE SETTINGS SHELL =================
   This dialog's half of the shared contract with My Settings. The header and section-card
   components are NOT restated here — they are alt-settings-stride.css's own (§5, §3); a
   second, page-scoped copy would be the duplication Core rule 4 exists to catch.
   Genuinely this dialog's own: the tab strip, the pane head, and — per that file's own §8,
   quoted: *"Dialog framing (width, height, the tab strip's own overflow behaviour) belongs to
   each host's existing shell chrome, not to this shared component file"* — the one header
   responsive rule that is framing: dropping the eyebrow below 900px. */

/* ---------- the header's one host-owned responsive rule — §5/§8c ---------- */
/* The eyebrow (STRIDE · TEAM SETTINGS) drops entirely under 900px — the mark and title alone
   are enough, and a truncated eyebrow reads worse than none. Framing, not a component
   property — alt-settings-stride.css's own §8 leaves this to the host. */
@media (max-width:900px){
  .alt-app #adminModal .stg-eyebrow{ display:none; }
}

/* ---------- the tab strip — restyle + the overflow affordance (risk R6) ---------- */
/* Measured: 13 tabs sum to ~690px inside a strip at most 598px wide, overflowing and silently
   scrolling at every width tested with no signal more tabs exist. The pinned declarations below
   are unchanged (`modal-size.test.js` asserts them verbatim) — this adds the missing affordance:
   an edge fade via `mask-image` on the scroll container, GPU-composited so it never intercepts a
   click meant for the tab underneath it. */
.alt-app #adminModal .admin-tabs{
  position:relative;
  -webkit-mask-image:linear-gradient(to right, transparent 0, #000 0, #000 100%, transparent 100%);
          mask-image:linear-gradient(to right, transparent 0, #000 0, #000 100%, transparent 100%);
  scroll-behavior:smooth;
}
/* The fade widens only on the side there is more to see — toggled by stgTabStripSync()
   (team-pane.js) off the strip's real scrollLeft/scrollWidth, never guessed from the tab count,
   since a role that hides tabs changes whether it overflows at all. */
.alt-app #adminModal .admin-tabs.stg-can-scroll-start{
  -webkit-mask-image:linear-gradient(to right, transparent 0, #000 28px, #000 100%, transparent 100%);
          mask-image:linear-gradient(to right, transparent 0, #000 28px, #000 100%, transparent 100%);
}
.alt-app #adminModal .admin-tabs.stg-can-scroll-end{
  -webkit-mask-image:linear-gradient(to right, transparent 0, #000 0, #000 calc(100% - 28px), transparent 100%);
          mask-image:linear-gradient(to right, transparent 0, #000 0, #000 calc(100% - 28px), transparent 100%);
}
.alt-app #adminModal .admin-tabs.stg-can-scroll-start.stg-can-scroll-end{
  -webkit-mask-image:linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
          mask-image:linear-gradient(to right, transparent 0, #000 28px, #000 calc(100% - 28px), transparent 100%);
}
/* A reader who cannot see the mask still has a working, keyboard-reachable, scrolling strip —
   the mask is a hint, never the only signal. `scrollbar-width:thin` stays visible rather than
   hidden, so the fade is not the only affordance. */
.alt-app #adminModal .admin-tabs{ scrollbar-width:thin; }
.alt-app #adminModal .admin-tab{
  border-radius:var(--stg-r, 9px);
}
.alt-app #adminModal .admin-tab:focus-visible{
  outline:2px solid var(--stg-ring, var(--accent)); outline-offset:-2px;
}

/* ---------- the pane head — §3 rule 5 ---------- */
/* The fold-all control sits outside the scrolling pane, on the same line as the intro copy —
   never inside the scroll region, never repeated per card. `flex-wrap` so a narrow dialog drops
   it under the intro rather than clipping it. */
.alt-app #adminModal .stg-pane-head{
  display:flex; align-items:flex-start; justify-content:space-between; gap:12px;
  flex-wrap:wrap; margin-bottom:12px;
}
.alt-app #adminModal .stg-pane-head .pane-intro{ flex:1 1 240px; margin-bottom:0; }
.alt-app #adminModal .stg-pane-actions{ display:flex; gap:8px; flex:0 0 auto; }
.alt-app #adminModal .stg-pane-actions .btn svg{ flex:0 0 auto; }

/* ---------- THE FOLD-ALL TOGGLE THAT REPLACED THE PAIR — 2026-09-23 ----------
   `Expand all` / `Collapse all` became ONE toggle application-wide — sys_design-system.md,
   "Hierarchical lists: one fold-all toggle". Twelve pane heads here draw it from one emitter.
   `.stg-fold-mount{display:contents}`: a plain wrapper would hold an 8px gap open around
   nothing while a pane has no foldable card yet (groupsPane, boardsPane).
   The button wears this dialog's `.btn.small` vocabulary via the component's `cls` hook rather
   than forking it. Only the UNLIT `[aria-pressed="false"]` face is styled here — an id-scoped
   rule would otherwise beat alt-components.css's lit-state rule on specificity and silently
   kill the selected treatment on all twelve controls. */
.alt-app #adminModal .stg-fold-mount{ display:contents; }
.alt-app #adminModal .stg-pane-actions .a-btn.stg-fold-all{
  align-self:flex-end; height:auto; padding:5px 9px; border-radius:var(--radius-sm);
}
.alt-app #adminModal .stg-pane-actions .a-btn.stg-fold-all[aria-pressed="false"]{
  background:var(--panel-2); color:var(--text); border-color:var(--border-strong);
}
.alt-app #adminModal .stg-pane-actions .a-btn.stg-fold-all[aria-pressed="false"]:hover{
  border-color:var(--accent); color:var(--accent-text);
}


/* ================= WIDTHS =================
   The strip must not grow as the window shrinks — the fix the task page's own band needed:
   at the width where three columns stop fitting, the glance becomes two, then one, rather than
   three columns of wrapped content. Nothing is removed at any width, only rearranged — a
   summary that drops half its figures on a laptop is a summary that lies. */
/* Measured, not guessed: the second row is a decision, taken above where an 8-control row would
   wrap raggedly anyway (flex decides which items share a line from their BASIS, so stragglers
   drop to their own line while something else grows to fill the gap). The View tabs take their
   own line since they're the widest single block and the only control about the whole page.
   Done with markup order, not `order` — View is the FIRST child of `.at-ctx` so reading order
   and focus order agree; `order:-1` was tried and measured to desync keyboard focus from visual
   position. */
@media (max-width:1599px){
  .alt-app .at-ctx-view{ flex:1 1 100%; }
  .alt-app .at-ctx-view > span{ margin-bottom:-2px; }
}
@media (max-width:1439px){
  .alt-app .at-glance{ grid-template-columns:minmax(0,480px) minmax(0,1fr) minmax(0,1fr); }
  .alt-app .at-ctx-board{ min-width:180px; max-width:260px; }
}
@media (max-width:1279px){
  .alt-app .at-glance{
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  }
  /* The figures span both columns on the row they head, so five tiles keep one line. */
  .alt-app .at-part-stats{ grid-column:1 / -1; padding-top:0; }
  .alt-app .at-person{ width:164px; }
}
/* THE THIRD ROW, ALSO A DECISION. Measured at 1024: the scope row needs 883px and search needs
   200 more than the 992 available, so Filters and More dropped first — alone on a line, adrift.
   Search is the elastic one, so search moves instead, taking the row for itself: three named
   rows (what, scoped to what, looking for what) rather than two and a remainder. */
@media (max-width:1039px){
  /* `margin-left:auto` drops since nothing is pinning the buttons to an edge any more once the
     row wraps at this width. */
  .alt-app .at-ctx-acts{ margin-left:0; }
}
@media (max-width:1023px){
  /* The lane's own width at this breakpoint is in CSS/alt/alt-team-kanban.css, which loads
     AFTER this file — a base rule there would otherwise beat this media query on specificity. */
  .alt-app .at-ctx{ gap:var(--a-2); }
  .alt-app .at-glance{ grid-template-columns:minmax(0,1fr); }
  .alt-app .at-part-stats{ grid-column:auto; }
}
@media (max-width:819px){
  /* The header's controls fall under its title rather than squeezing it — this only stops the
     due-date row being pinned to the trailing edge of a line it's now alone on. */
  .alt-app .at-band-h > .at-due{ margin-left:0; flex:1 1 100%; }
  .alt-app .at-band-h > .at-count{ margin-left:0; }
  .alt-app .at-band-h > .a-btn{ margin-left:auto; }
  .alt-app .at-ctx-team,.alt-app .at-ctx-board,.alt-app .at-ctx-group{ flex:1 1 46%; }
  /* Sharing a line at 46% each, the cap is the line — not a number from the desktop row. */
  .alt-app .at-ctx-board{ max-width:none; }
}
@media (max-width:639px){
  /* Squares the Focused button once alt-responsive.css folds its word away below this width —
     measured: a 13px surplus pushed the pin's right edge past the bar at 390px. `--a-ctl` is
     the same token the pin and roster button size from, so all three stay one height. */
  .alt-app .at-ctx-btns .at-focused-btn{ width:var(--a-ctl); padding:0; }
}
@media (max-width:479px){
  /* Team and board names are long and are the two things a reader must be able to READ; the
     grouping select and Mine are short enough to share a line. The roster button stays beside
     the team it lists rather than taking a 100% basis onto a line of its own. */
  .alt-app .at-ctx-team{ flex:1 1 200px; }
  .alt-app .at-ctx-board{ flex:1 1 100%; max-width:none; }
  .alt-app .at-ctx-group{ flex:1 1 50%; min-width:120px; }
  .alt-app .at-person{ width:152px; }
}

/* ================= MOTION: THE MICRO RESPONSE =================
   Everything a reader touches all day changes between two frames: a tab, a person's card, a
   lane header, a card picked up. `--dur-micro` (140ms, linear) is the application's timing,
   not invented here — `.micro` (CSS/components.css) is unreachable from JS/alt/'s markup, so
   the selectors are this page's own.
   Two clocks: a hover that CHANGES a control is `--dur-micro`; a control REVEALED by hover takes
   `--a-quick` instead, same as `.a-note-star` on Notes. `box-shadow` and layout are deliberately
   absent — a shadow under a card strip is paint the compositor can't skip, and `background-color`
   is already animated by `altTbNewCard`'s own flash.
   Reduced motion is answered at the token: alt-tokens.css zeroes both durations under
   `prefers-reduced-motion: reduce` on `.alt-app`, so every rule below inherits 0s for free. */
/* `.at-tab` is not in this list — it moved to alt-components.css and is eased there instead. */
.alt-app .at-person,
.alt-app .at-any,
.alt-app .a-tb-retired-h,
.alt-app .a-tb-lane-h,
.alt-app .a-tb-card-t,
.alt-app .a-tb-lane-btn{
  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 card: its edge on hover, and its whole self while it is being dragged. */
.alt-app .a-tb-card{
  transition:border-color var(--dur-micro, 140ms) linear,
             opacity      var(--dur-micro, 140ms) linear;
}
/* The row and topic actions, which are hidden until the row is hovered or focused. Same clock
   as every other hover-reveal in the suite. */
.alt-app .a-tb-topic-acts .a-btn,
.alt-app .a-tb-row-acts .a-btn{
  transition:opacity var(--a-quick) var(--a-ease);
}

/* ---------- FOCUSED, IN THE ACTIONS CLUSTER, IMMEDIATELY RIGHT OF MORE ----------
   Placed there by the owner from a screenshot with an arrow at the spot — the third position in
   one day, after "the right-most side of the section" was first read as the View field, which
   is only ~479px inside a ~1637px bar and so does not reach the bar's true right edge.
   `flex:0 0 auto` keeps it from shrinking when the cluster runs out of width. Nothing else is
   declared: `.a-btn.a-focus-btn` paints the control, and alt-responsive.css already folds the
   word away below its breakpoint, same as Tasks and Notes. */
.alt-app .at-focused-btn{ flex:0 0 auto; }

/* ---------- "Bulk Import": the segmented control choosing which import is showing ----------
   The owner asked for the two import tabs to become one; this control replaced the distinction
   the tab names used to carry. Its own classes, deliberately not a nested `.admin-tabs`/
   `.admin-tab` pair — those are bound globally by team-pane.js's `querySelectorAll`, so a nested
   pair would be swept into the dialog's own top-level tab-switching logic. Same visual recipe,
   different selectors. `.import-kind-panel[hidden]` needs no rule — CSS/base.css's global
   `[hidden]{display:none!important}` already covers it. */
.alt-app #adminModal .import-kind-tabs{
  display:flex; gap:4px; margin-bottom:14px;
  background:var(--panel-2); border-radius:var(--radius-sm); padding:3px;
}
.alt-app #adminModal .import-kind-tab{
  flex:1; background:transparent; border:none; border-radius:6px;
  padding:7px; color:var(--text-dim); font-weight:600; font-size:12px; cursor:pointer;
}
.alt-app #adminModal .import-kind-tab.active{ background:var(--accent-fill); color:#fff; }
.alt-app #adminModal .import-kind-tab:focus-visible{
  outline:2px solid var(--stg-ring, var(--accent)); outline-offset:-2px;
}
