/* v103 (AX, 3 Oct 2026) — the shared accessibility + responsive layer. Loaded last; one place for the page frame's reflow, the tab row, the focus
   ring's variants, the 24px targets and the hover-only controls. _research/2026-10-a11y-responsive/01-audit.md §4 · _reviews/2026-10-03-a11y/FIX.md.

   ONE BREAKPOINT SCALE, on the CONTENT width (the area beside the sidebar), never the window: the scroller is the container, so a 1024px window
   with the sidebar open (776px of content) behaves like a 776px page, not like a desktop.
     ≤ 1100   tight desktop          ≤ 760   tablet / phone: one column, the page head stacks          ≤ 480   phone: the smallest paddings */

/* ---------- AX5 · the page frame reflows ---------- */
@container pg (max-width:760px){
  .page{padding-left:16px;padding-right:16px}
  /* the page head: title, then its line, then the tools on their own row (they wrap) — never a 0px title column (audit K2) */
  .pl-hd{display:flex!important;flex-direction:column;align-items:stretch!important;gap:8px}
  .pl-hd > .grow{display:block!important;min-width:0}
  .pl-hd > :not(.grow){align-self:flex-start!important;justify-self:start;max-width:100%;flex-wrap:wrap;justify-content:flex-start!important;margin-top:0;grid-column:auto!important;grid-row:auto!important}
  .pl-hd .pl-s{max-width:none!important}
  .pl-t{overflow-wrap:anywhere}
  /* the tab row takes the whole line; the tools wrap under it */
  .pl-bar{flex-wrap:wrap!important;row-gap:6px}
  .pl-bar > .pl-tabs{flex:1 1 100%!important;max-width:100%}
  .pl-bar > .grow{display:none}
  /* the record pages (finding, action, change): one column; the side panel sits right after the header, not stuck to the side (audit K3) */
  .fd-grid{grid-template-columns:minmax(0,1fr)!important;row-gap:16px;padding-right:0!important}
  .fd-grid > .fd-main{display:contents}
  .fd-grid > .fd-main > *{min-width:0}
  .fd-grid > .fd-main > .fd-hd{order:-2}
  .fd-grid > .fd-side{position:static!important;display:block!important;min-width:0}   /* night C5 (Oct 8): last, where it is in the page — Tab follows what you see */
  /* Oct 7 review (D13): on a finding the fix and its steps come before the "This finding" card — the decision first, the facts after it */
  .fd-grid > .fd-main > :is(.fd-story,:has(~ .fd-story)){order:-1}
  .fd-side .fd-f:not(.is-wide){grid-template-columns:84px minmax(0,1fr);row-gap:8px}   /* full width again: the label beside its value */
  .fd-side dd,.fd-side .fd-f{min-width:0;overflow-wrap:anywhere}
  /* a record's facts and a card's head wrap instead of running off the page */
  .ap-facts{grid-template-columns:repeat(2,minmax(0,1fr))!important}
  .ap-facts > *{min-width:0;overflow-wrap:anywhere}
  .ap-hd{flex-wrap:wrap;row-gap:4px;height:auto;min-height:48px;padding-top:6px;padding-bottom:6px}
  .ap-hd .wt-acts{white-space:normal;flex-wrap:wrap}
  .ap-hd .f-age{white-space:normal}
  .cg-notes .pt-nr{grid-template-columns:minmax(0,1fr) auto!important}
  .cg-notes .pt-nr > .pt-nc{grid-column:1 / -1}
}
@container pg (max-width:480px){
  .page{padding-left:12px;padding-right:12px}
  .fd-nav,.pp-currow,.pp-curr{flex-wrap:wrap;row-gap:6px}
  .pp-curr{flex:1 1 100%;min-width:0}
}
/* the tab row: scrolls sideways when it can't fit (lboard.js fitTabs folds into "More" first on a wide page), a fade on the cut edge */
.pl-bar > .pl-tabs{min-width:0;flex:0 1 auto;flex-wrap:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:none;scroll-snap-type:x proximity;overscroll-behavior-x:contain}
.pl-bar > .pl-tabs::-webkit-scrollbar{display:none}
.pl-bar > .pl-tabs > .pl-tab{flex:none;scroll-snap-align:start}
.pl-tabs.is-ovf-r{-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 40px),transparent);mask-image:linear-gradient(to right,#000 calc(100% - 40px),transparent)}
.pl-tabs.is-ovf-l{-webkit-mask-image:linear-gradient(to right,transparent,#000 40px);mask-image:linear-gradient(to right,transparent,#000 40px)}
.pl-tabs.is-ovf-l.is-ovf-r{-webkit-mask-image:linear-gradient(to right,transparent,#000 40px,#000 calc(100% - 40px),transparent);mask-image:linear-gradient(to right,transparent,#000 40px,#000 calc(100% - 40px),transparent)}
.pl-tab[hidden]{display:none!important}

/* ---------- AX4 · one focus ring ----------
   The ring is linear.css's one rule — `:focus-visible{outline:2px solid var(--ring);outline-offset:2px}` with --ring #0071e3 light (≥ 3.77:1 even on
   the board grey #e6e6e9) / #0091ff dark. Its second tone is a 2px --bg band between the element and the ring, so it reads on any surface; it sits in
   a cascade layer, so a control that draws its own shadow (a card's lift, a tab's underline) keeps it. The per-component outline rules are gone:
   a control either takes the ring as it is, or the INSET variant below when it is a row, a cell or a tab inside a box that clips (audit S4 · K6). */
@layer a11y-ring {
  :focus-visible{box-shadow:0 0 0 2px var(--bg)}
  /* the inset variant (below) draws inside the edge, so it needs no band outside it */
  :is(.i-row,.tl-row,.ip-row,.vd-row,.goal-row,.cp-hd.is-strip,.np-row,.pal-i,.f-row,.ch-row,.fd-goal,.a-row,.r-row,.fold-hd,.c-row,.pn-i,.cl-row,.mv-row,.cg-row,.s-row,.pal-in input,.menu-qw input,.cp-comp textarea,
    .glance.is-counts .gl-c,a.mini,.fp-tab,.seg>button,button.kp,a.kp.is-link,.tbl-r,.qr-row,.cg-near,.ai-ansr,.cal-ev,.ai-loop-r,.ai .ai-cmp-r,.ag .ag-rd,.mn-kp,.mn-g,
    .apq-row,.cl-wk,.inv-s,.stg-ni,.stg-li.is-link,.stg-st,.ig-vw,.ig-ri,.rp-tabs button,.rp-tbl.rp-tbl-q .rp-tr,.cw-it,.ag-row,.db-ctr,.db-mb,
    .pl-tabs .pl-tab,.menu-i,.nav-i,.sb-sec,.kb-colh,.kb-more,.crumbs a.cr-a,.k2 > .k,.tbl .k,.tbl .u,.u > a,.ellipsis > a,a.ellipsis,.rp-src,.ai-led a,.cn-ewh,.ig-card-a,.al-more,.gr-grp > .sv-i,.gr-pv,.lc-inwork,.kb-card.is-kf,[data-route-focus],#scroll,
    .hs-wtl-a,.hs-rl,.hs-star,.hs-card .menu-btn.ib,.pl-views .pl-chip,.kb-extra,.kb-also,.lm-map,[id^="gr-seen-"]):focus-visible{box-shadow:none}
}
/* inset: rows, list items, tiles, tabs and links inside clipping or single-line cells — the ring is drawn inside their edge, never cut */
:is(.i-row,.tl-row,.ip-row,.vd-row,.goal-row,.cp-hd.is-strip,.np-row,.pal-i,.f-row,.ch-row,.fd-goal,.a-row,.r-row,.fold-hd,.c-row,.pn-i,.cl-row,.mv-row,.cg-row,.s-row,
  .glance.is-counts .gl-c,a.mini,.fp-tab,.seg>button,button.kp,a.kp.is-link,.tbl-r,.qr-row,.cg-near,.ai-ansr,.cal-ev,.ai-loop-r,.ai .ai-cmp-r,.ag .ag-rd,.mn-kp,.mn-g,
  .apq-row,.cl-wk,.inv-s,.stg-ni,.stg-li.is-link,.stg-st,.ig-vw,.ig-ri,.rp-tabs button,.rp-tbl.rp-tbl-q .rp-tr,.cw-it,.ag-row,.db-ctr,.db-mb,
  .pl-tabs .pl-tab,.menu-i,.nav-i,.sb-sec,.kb-colh,.kb-more,.crumbs a.cr-a,
  .k2 > .k,.tbl .k,.tbl .u,.u > a,.ellipsis > a,a.ellipsis,.rp-src,.ai-led a,.cn-ewh,.ig-card-a,
  .al-more,.gr-grp > .sv-i,.gr-pv,.lc-inwork,
  .hs-wtl-a,.hs-rl,.hs-star,.hs-card .menu-btn.ib,.pl-views .pl-chip,.kb-extra,.kb-also,.lm-map,[id^="gr-seen-"]):focus-visible{outline-offset:-2px}   /* Oct 10 (impeccable A4): Home's card links and card-foot buttons, the Changes view chips in their scroller, the boards' trailing links, Local's map and Growth's "Mark as seen" at a panel's edge */   /* night build (I4): four more that sat on a clipping edge — the Ask list's ⋯, Growth's (i) in a cut line and its "Measured" tag at a strip's edge, Local's in-work link in a phone table */
.apq-row.is-kf,.kb-card.is-kf{outline:2px solid var(--ring);outline-offset:-2px}
/* a menu item: the tint AND the inset ring — never a tint alone (audit S5, 1.13:1) */
.menu-i:focus-visible{outline:2px solid var(--ring)!important;outline-offset:-2px;background:var(--bg-3)}
/* a heading the router focuses after a page change is not a control — no ring (it is announced instead) */
[data-route-focus]:focus,[data-route-focus]:focus-visible,#scroll:focus-visible{outline:none;box-shadow:none}
/* D04: a folded page summary opens while a link inside it has focus — nothing focusable is hidden, no ring is cut */
.pl-s.is-clamp:focus-within{max-height:none!important;overflow:visible}
/* the sticky top bar never covers the focused control (audit S6, 198 stops) */
/* ---------- AX8 · one table pattern (audit K5) ----------
   ui/a11y.js gives every grid-table its roles; a sort button sits inside its columnheader (.tbl-ch). Under 760px of content each row is a card:
   the first cell as its title, then one "label  value" line per column; the header keeps only its sort buttons, as a "Sort by" row. */
.tbl-h > .tbl-ch{display:flex;align-items:center;min-width:0}
.tbl-h > .tbl-ch.r{justify-content:flex-end}
@container pg (max-width:760px){
  .tbl:is(.is-tbl,[role=table]){min-width:0!important;width:100%}
  .tbl:is(.is-tbl,[role=table]) > .tbl-h:not(:has(.tbl-ch)){position:absolute!important;width:1px;min-width:0!important;max-width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;padding:0;border:0}
  .tbl:is(.is-tbl,[role=table]) > .tbl-h:has(.tbl-ch){display:flex!important;flex-wrap:wrap;align-items:center;gap:4px 14px;height:auto;min-height:32px;padding:4px 8px}
  .tbl:is(.is-tbl,[role=table]) > .tbl-h:has(.tbl-ch)::before{content:"Sort by";color:var(--fg-3)}
  .tbl:is(.is-tbl,[role=table]) > .tbl-h > [role=columnheader]:not(.tbl-ch){position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .tbl:is(.is-tbl,[role=table]) > .tbl-h > .tbl-ch{justify-content:flex-start}
  .tbl:is(.is-tbl,[role=table]) > .tbl-h > .tbl-ch > button{min-height:24px}
  .tbl:is(.is-tbl,[role=table]) > .tbl-r{display:grid!important;grid-template-columns:minmax(0,1fr)!important;row-gap:3px;padding:10px 8px;min-height:0;height:auto}
  .tbl:is(.is-tbl,[role=table]) > .tbl-r > :first-child{margin-bottom:3px}
  :where(.tbl:is(.is-tbl,[role=table]) > .tbl-r) > :not(:first-child){display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:baseline;gap:2px 8px;min-width:0;text-align:right}
  :where(.tbl:is(.is-tbl,[role=table]) > .tbl-r) > :not(:first-child)[data-label]::before{content:attr(data-label);flex:none;max-width:55%;margin-right:auto;color:var(--fg-3);font-size:var(--t-co);line-height:var(--lh-co);font-weight:var(--w-regular);text-align:left;white-space:normal}
  :where(.tbl:is(.is-tbl,[role=table]) > .tbl-r) > :not(:first-child):empty{display:none}
  /* D13 (7 Oct): a grid list that is not a table (its rows differ, or are links) scrolls sideways in its own box — never under the card's edge */
  .tbl:not(.is-tbl):not([role=table]){overflow-x:auto;overscroll-behavior-x:contain}
}

/* ---------- AX9 · targets ≥ 24px (WCAG 2.5.8) ----------
   .hit: a 24px hit area around a small control without moving it (an invisible ::after, inset −4px). Applied here to the chart markers (18px,
   200+ on the site), the settings back link, the reports' bare source icons; the tick boxes and "Used by" chips are 24px themselves. */
.hit,.stg-back .stg-a,.rp-src.is-bare{position:relative}   /* .annot-n is already absolute — its own box holds the ::after */
.hit::after,.annot-n::after,.stg-back .stg-a::after,.rp-src.is-bare::after{content:"";position:absolute;inset:-4px;border-radius:inherit}
.annot-n::after{inset:-3px}
.rp-src.is-bare::after{inset:-6px}   /* a 12px icon link → 24px */
.stg-back .stg-a{display:inline-flex;align-items:center;min-height:24px}

/* ---------- AX10 · no iOS switches (audit K7) ----------
   A single-select view switch (Actions: List / One by one · Board / Calendar) is drawn like the page's views (.pl-views): text, icon, and an
   underline under the one shown — never two filled capsules side by side. */
.pl-vsw{gap:4px 18px}
.pl-vsw .prop{height:30px;padding:0 1px!important;gap:6px;border:0;border-radius:0;background:none!important;box-shadow:inset 0 -2px 0 transparent!important;color:var(--fg-3);font-weight:var(--w-medium);transition:var(--tr-ui)}
.pl-vsw .prop svg{color:currentColor}
.pl-vsw .prop > span{display:inline!important}
@media (hover:hover){.pl-vsw .prop:hover{color:var(--fg);box-shadow:inset 0 -2px 0 var(--ln)!important}}
.pl-vsw .prop.is-set,.pl-vsw .prop[aria-pressed="true"]{color:var(--fg);box-shadow:inset 0 -2px 0 var(--fg)!important}

/* ---------- AX12 · nothing only on hover (audit S11) ----------
   Controls that appear on hover (Why?, the board's tick boxes) are always shown on a touch screen and on a narrow page. */
@media (hover:none){.db-why,.kb-ck,.apq-ck,.al-more,.cs-x,.ol-mv,.rm-acts,.kb-colx{opacity:1!important}}
@container pg (max-width:900px){.db-why,.kb-ck,.apq-ck,.al-more,.rm-acts{opacity:1!important}}

/* ---------- AX13 · page groups (loop L, Growth G, Settings C) ---------- */
/* L7: an approval card's title is an h2 (it was an h3 straight under the page's h1) — the same look */
.ap-card h2.ap-t{margin:2px 0 0;font-size:var(--t-t2);line-height:var(--lh-t2);font-weight:var(--w-semibold);letter-spacing:var(--ls-t2);color:var(--fg)}
.ap-card h2.ap-t a{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
@media (hover:hover){.ap-card h2.ap-t a:hover{text-decoration:underline;text-underline-offset:3px}}
/* L4: the action's lifecycle stepper in a narrow column — words hyphenate inside their step, only the current step keeps its date (no overlap) */
@container lp (max-width:560px){
  .loop li .loop-l{font-size:var(--t-sh);line-height:var(--lh-sh);padding-right:4px;hyphens:auto;-webkit-hyphens:auto;overflow-wrap:break-word}
  .loop li:not(.is-now) .loop-t{visibility:hidden}
}
/* Oct 7 review (D13): at phone width the stepper stands upright — one step a line, its date beside it — so a word is never split ("Detecte / d",
   "Fix recom- / mended"); and a waiting fix's button drops under its words instead of squeezing them into a 74px column */
@container pg (max-width:480px){
  .loop{flex-direction:column;gap:10px}
  .loop li{flex:none;flex-direction:row;flex-wrap:wrap;align-items:baseline;column-gap:8px;padding:0 0 0 26px;min-height:16px}
  .loop li::before{top:19px;bottom:-7px;left:7px;right:auto;width:2px;height:auto}
  .loop li .loop-l{font-size:var(--t-co);line-height:16px;padding-right:0;hyphens:manual;-webkit-hyphens:manual;overflow-wrap:normal}
  .loop li:not(.is-now) .loop-t{visibility:visible}
  .loop li .loop-t:empty{display:none}
  .story .fd-fix{flex-wrap:wrap;align-items:flex-start;row-gap:10px}
  .story .fd-fix > .grow{flex:1 1 calc(100% - 48px)}
}
/* G2: the keyboard's day on a Growth chart shows like the pointer's — its line and its tooltip */
.ccol.is-kf{z-index:6}
.ccol.is-kf::before{content:"";position:absolute;top:0;bottom:0;left:50%;border-left:1px solid var(--fg-3)}
.ccol.is-kf .tip{display:block}
.chart-plot > .cols[role=slider]{position:absolute;inset:0;border-radius:var(--r-4)}
.chart-plot > .cols[role=slider]:focus-visible{outline-offset:2px}
/* L2: the approvals queue on a phone — one card per fix: tick · priority · chevron, the fix, then "label  value" lines (At stake, Expected,
   Waiting, Approver); the header row stays for screen readers only */
@container pg (max-width:760px){
  .apq-h{position:absolute!important;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
  .apq-row{grid-template-columns:24px minmax(0,1fr) 16px!important;row-gap:4px;align-items:start}
  .apq-row > :nth-child(1){grid-column:1;grid-row:1 / span 2}
  .apq-row > :nth-child(2){grid-column:2;grid-row:1}
  .apq-row > :nth-child(8){grid-column:3;grid-row:1}
  .apq-row > :nth-child(3){grid-column:2 / 4;grid-row:2}
  .apq-row > :nth-child(n+4):nth-child(-n+7){grid-column:2 / 4;display:flex!important;flex-direction:row;flex-wrap:wrap;align-items:baseline;gap:0 8px}
  .apq-row > :nth-child(n+4):nth-child(-n+7)[data-label]::before{content:attr(data-label);flex:none;min-width:104px;color:var(--fg-3);font-size:var(--t-co);line-height:var(--lh-co)}
  .apq-row .k2 .k,.apq-row .k2 .u{white-space:normal}
  .apq-row > :nth-child(n+4):nth-child(-n+7) > .u{flex-basis:100%;padding-left:112px}
}
/* L3: the bulk bar's live sentence sits in one span */
.apq-bulk-t{min-width:0}
/* C3: an integration's name wraps to two lines instead of being cut without a title */
.ig-card-a{white-space:normal;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}

/* ---------- AX7 · ink on grey ----------
   Tertiary text inside a grey chip or a grey box takes --chip-fg (#636368, 4.8:1 on #e6e6e9) — --fg-3 was 4.06–4.40:1 there (audit S9). */
.chip .fd-rel-n,.cg-ba .fd-k,.fl-zero-c b,.ai-from .chip,.sb-user.is-on .ur,.chip .fd-k,.chip .cw-pos,.cs-chip.is-view{color:var(--chip-fg)}@media (hover:hover){.sb-user:hover .ur{color:var(--chip-fg)}}

/* a composer whose textarea draws no outline: its box shows the one ring (audit A2 — the border moving from --bd to --bd-3 was ≈ 1.8:1) */
.ask-comp:focus-within,.ap-comp:focus-within,.cp-comp:focus-within{outline:2px solid var(--ring);outline-offset:2px}   /* night fix (Oct 8): the chat composer too — its textarea draws no band (above) */
/* the ⌘K field: the field is the control, so its box shows the ring */
.palette .pal-in:focus-within{outline:2px solid var(--ring);outline-offset:-2px;border-radius:var(--r-card) var(--r-card) 0 0}

/* ---------- D08/D13 (design review, 7 Oct) · nothing is clipped, nothing scrolls the page sideways ----------
   A chip inside a table cell wraps instead of running out of its column; a "for" pill, a note's button and a status line wrap on a phone;
   the Results and Closed rows become labelled cards (the state and the date on top, the name across, the numbers two by two). */
.tbl-r > .lbl,.tbl-r > * > .lbl,.f-cell > .lbl,.mn-g-st > .lbl,.mn-g-st > .m-cd{white-space:normal;height:auto;min-height:22px;padding-top:3px;padding-bottom:3px;line-height:var(--lh-sh);text-wrap:balance}
.kp-s{white-space:normal}   /* a KPI's explanation wraps on its own row of the strip (the subgrid keeps the rows aligned) */
.tbl-r .k2 > .u{white-space:normal}   /* a cell's second line wraps in its column */
@container pg (max-width:760px){
  .fd-for{height:auto;min-height:26px;flex-wrap:wrap;row-gap:2px;padding-top:4px;padding-bottom:4px;border-radius:var(--r-12)}
  .fd-for span{white-space:normal}
  .fd-for b{flex:1 1 100%}
  .lc-stat{white-space:normal}
  .r-row,.r-row.is-7,.r-row.is-7.is-6,.f-row.is-closed{grid-template-columns:repeat(2,minmax(0,1fr))!important;column-gap:12px!important;row-gap:8px;align-items:start;padding-top:12px;padding-bottom:12px}
  :is(.r-row,.f-row.is-closed) > :first-child{grid-column:1;grid-row:1;justify-self:start}
  :is(.r-row,.f-row.is-closed) > .f-age{grid-column:2;grid-row:1;justify-self:end;text-align:right}
  :is(.r-row,.f-row.is-closed) > .f-main{grid-column:1 / -1;grid-row:2}
  .r-row > .r-num.is-wrap{grid-column:1 / -1}
  /* night fix (Oct 8): AI Search's "By assistant" table takes the stacked card like every table (its 5 fixed columns broke words letter by letter) */
  .f-list > .f-cols{display:none!important}   /* the column titles are aria-hidden; each card's cells carry their own words */
  .f-row .f-cell .lbl{white-space:normal;height:auto;min-height:22px;padding-top:3px;padding-bottom:3px;line-height:var(--lh-sh)}
  .stg-pendline{flex-wrap:wrap}
  .stg-pendline .stg-a{white-space:normal;flex-basis:100%;padding-left:22px}
  /* a KPI strip is two tiles a row on a phone — the value keeps its size (D03), the tiles reflow */
  .kp-strip,.kp-strip.is-3,.kp-strip.is-4,.kp-strip.is-5,.kp-strip.is-6{grid-template-columns:repeat(2,minmax(0,1fr))!important}
  .kp-strip > .kp{border-left:1px solid var(--ln-2);border-top:1px solid var(--ln-2)}
  .kp-strip > .kp:nth-child(odd){border-left:0}
  /* night fix (Oct 8): a tile that starts a row lines up with the one above it (the card's first tile has no left padding) */
  :is(.sec.panel,.hx) .kp-strip > .kp:nth-child(odd){padding-left:0}
  :is(.sec.panel,.hx) .kp-strip.lc-tiles > .kp:nth-child(odd):not(:first-child){padding-left:12px}
  :is(.sec.panel,.hx) .kp-strip.lc-tiles > .kp:nth-child(even){padding-left:0}
  .sec.panel .lc-tiles .lc-pair-i:first-child{padding-left:0}
  .kp-strip > .kp:nth-child(-n+2){border-top:0}
  .kp-strip > .kp:last-child:nth-child(odd){grid-column:1 / -1}
  .kp > *{max-width:100%;overflow-wrap:break-word}
  .sv-two,.sv-two.is-eq{grid-template-columns:minmax(0,1fr)!important}   /* two cards side by side become one column */
  /* a chart that names its lines at their ends keeps most of the width for the plot */
  .chart.has-endl .chart-body,.cps .chart.has-endl .chart-body,.cp .chart.has-endl .chart-body{grid-template-columns:36px minmax(0,1fr) 108px}
  /* a short word set on one line (a status, a tag, a caption, a card's sub-line) wraps on a phone instead of running out of its box */
  :is(.lbl,.chip,.stg-uc,.chip.sm){white-space:normal;height:auto;min-height:22px;padding-top:3px;padding-bottom:3px;line-height:var(--lh-sh);text-wrap:balance}
  :is(.sv-cap,.fd-k,.sec-hd .n,.sec-hd h2,.kp-s,.num small,.ap-note){white-space:normal;min-width:0;overflow-wrap:break-word}
}

/* ---------- night C5 · C6 (Oct 8) · touch targets, phone layouts ---------- */
/* C6: on a phone or a touch screen every control is at least 40px tall — buttons, menus, chips, folds, fields and the stand-alone links grow; the
   small icon buttons ((i), ×, copy, a switch, chart markers) keep their look and get an invisible 40px area around their centre */
@media (max-width:600px),(pointer:coarse){
  :is(.btn,.prop,.menu-btn,.pl-chip,.stg-in,.stg-find-q){min-height:40px}
  .menu .menu-i{min-height:44px;flex-shrink:0}   /* night fix (Oct 8, MOB-3): menu rows — the switcher, the account menu — are 44px to the finger */
  .menu-hint.is-kbd{display:none}   /* a keyboard shortcut means nothing on a phone */
  summary{min-height:40px;align-content:center}
  :is(button.lk,a.more,.cr-a,.fd-back){display:inline-flex;align-items:center;min-height:40px}
  /* night fix (Oct 8): a link inside a sentence stays in the line — its 40px area is an invisible box around it, never a gap in the text */
  :is(.u,.mn-g-u,p,.sv-cap) > button.lk,span > button.lk.ag-see{display:inline;min-height:0;position:relative}   /* closing round L (#82): + Agent Readiness' "See the change" */
  :is(.u,.mn-g-u,p,.sv-cap) > button.lk::after,span > button.lk.ag-see::after{content:"";position:absolute;left:-4px;right:-4px;top:50%;height:40px;transform:translateY(-50%)}
  /* closing round L (#93, rulebook §8.6): a primary button is 44px to the finger — it keeps its 40px look, an invisible 2px band above and below takes the touch */
  :where(.btn.pri){position:relative}
  .btn.pri::after{content:"";position:absolute;left:-1px;right:-1px;top:-3px;bottom:-3px}   /* measured from inside its 1px border: 40 + 2 × 2 = 44 */
  :where(.ib,.sv-i,.cp-i,.fd-i,.db-i,.stg-copy,.ac-x){position:relative}
  :is(.ib,.sv-i,.cp-i,.fd-i,.db-i,.stg-copy,.stg-tg,.ac-x)::after{content:"";position:absolute;left:50%;top:50%;width:40px;height:40px;transform:translate(-50%,-50%);border-radius:var(--r-8)}
  :is(.db-b,.iv-page,.chart-plot) .annot-n::after{inset:auto;left:50%;top:50%;width:40px;height:40px;transform:translate(-50%,-50%)}
  /* "Show details" sits at the end of a sentence: a 40px area around it, the sentence's lines untouched (its ::after is the chevron) */
  details.pt-more > summary{position:relative}
  details.pt-more > summary::before{content:"";position:absolute;left:0;right:0;top:50%;height:40px;transform:translateY(-50%)}
  /* small text buttons in a row (the chart's foot, the Dashboard's Why?, the editor's toolbar): 40px tall to the finger, their own width */
  :where(.ch-fold,.ch-mk-b,.db-know,.db-why,.dp-tools > button,.dn-hd){position:relative}
  :is(.ch-fold,.ch-mk-b,.db-know,.db-why,.dp-tools > button,.dn-hd)::after{content:"";position:absolute;left:0;right:0;top:50%;height:40px;transform:translateY(-50%)}
}
/* closing round L (#92, WCAG 1.4.10 reflow at 320px): a long button or link label wraps inside its card, and its row wraps — nothing is cut */
@media (max-width:360px){
  #scroll :is(.btn,.stg-a){white-space:normal;max-width:100%;height:auto;text-align:start;overflow-wrap:anywhere}
  #scroll .btn{padding-top:6px;padding-bottom:6px}
  :is(.gr-slim-b,.stg-inline,.lc-ask-tl){flex-wrap:wrap}
}
@container pg (max-width:760px){
  /* C6: a table cell that sets its own display (.tbl .u is a block) still puts its column's name beside its value in the card layout */
  .tbl:is(.is-tbl,[role=table]) > .tbl-r > :is(.u,.k):not(:first-child){display:flex}
  /* a group or total row (ui/a11y.js marks it data-tbl-part) keeps every cell in the card's one column */
  .tbl:is(.is-tbl,[role=table]) > .tbl-r[data-tbl-part] > *{grid-column:auto}
  /* Local › Listings: each location's mark sits beside the location's name, as every other card line does */
  .lc-list.is-tbl > .tbl-r > .lc-mx:not(:first-child){flex-direction:row;align-items:baseline}
  .lc-list.is-tbl .lc-vis{align-items:flex-end;text-align:right;max-width:62%}
  /* night fix (Oct 8): Website › Pages keeps its own compact phone line ("Home · Indexable · Issues None · Last changed Sep 7 · Google clicks 2,234")
     instead of the label/value card — the two layouts no longer fight ("IndexableIndexable") */
  .tbl.wx-pages > .tbl-r{display:flex!important;flex-wrap:wrap;align-items:baseline;column-gap:0!important}
  .tbl.wx-pages > .tbl-r > .wx-cl:not(:first-child){display:inline;text-align:left}
  .tbl.wx-pages > .tbl-r > .wx-cl:not(:first-child)[data-label]::before{content:" · ";flex:none;max-width:none;margin-right:0;white-space:pre;color:var(--fg-4)}
  .tbl.wx-pages > .tbl-r > .wx-cl:is([data-l="Issues"],[data-l="Last changed"],[data-l="Google clicks"]):not(:first-child)[data-label]::before{content:" · " attr(data-l) " "}
  .tbl.wx-pages > .tbl-r > .k2 + .wx-cl:not(:first-child)[data-label]::before{content:none}
  /* night fix (Oct 8): Experience › a stuck point's split tables — each line says its own column ("Ordered  371", "Share  40%"), never "·", and the
     unit isn't said twice ("Checkouts  937 checkouts") */
  .ex-sp.is-5 .tbl-r > .ex-c + .ex-c:not(:first-child)[data-label]::before{content:attr(data-label);color:var(--fg-3)}
  .ex-sp.is-5 .tbl-r > .ex-c[data-l]:not(:first-child)[data-label]::after{content:none}
  .ex-sp.is-5 .tbl-r > :last-child:not(:first-child){flex-direction:column;align-items:flex-start;text-align:left}   /* the comparison sentence reads under its label */
  .ex-sp.is-5 .tbl-r > :last-child:not(:first-child)[data-label]::before{max-width:none}
  /* night fix (Oct 8): every card line starts at the card's edge (a desktop gutter never indents one label), and a value made of words and a quoted
     search ("#2 for “macbook air m4 price”, above your #3") flows as one sentence beside its label */
  .tbl:is(.is-tbl,[role=table]) > .tbl-r > :not(:first-child){padding-left:0}
  .tbl:is(.is-tbl,[role=table]) > .tbl-r > :not(:first-child):is(.u,.k,.num,span,div):has(> bdi){display:block;text-align:right}
  .tbl:is(.is-tbl,[role=table]) > .tbl-r > :not(:first-child):is(.u,.k,.num,span,div):has(> bdi) > bdi{display:inline}
  .tbl:is(.is-tbl,[role=table]) > .tbl-r > :not(:first-child):is(.u,.k,.num,span,div):has(> bdi)[data-label]::before{float:left;margin-right:12px;text-align:left}
  /* AI Search › By assistant: a rate and its range read "Named in   56% 47–65%" on one line, as every card line does */
  .tbl.ai-eng > .tbl-r > .ai-rate:not(:first-child){flex-direction:row;align-items:baseline;gap:2px 6px}
  /* Topics: a number with its change under it reads "Clicks  17,288 −8%" on one line */
  .tbl:is(.is-tbl,[role=table]) > .tbl-r > .tx-c:not(:first-child){flex-direction:row;align-items:baseline;gap:2px 6px}
}
/* C6: a record's lifecycle (Health problem, Experience record) reads top to bottom on a phone — one step a line, the line between the dots */
@container pg (max-width:600px){
  .hx-life{grid-template-columns:minmax(0,1fr)!important;gap:10px}
  .hx-life li{flex-direction:column;padding:0 0 0 28px;min-height:18px}
  .hx-life li::before{display:block;left:8px;right:auto;top:20px;bottom:-12px;width:2px;height:auto}
  .hx-life li:last-child::before{display:none}
}
@container pg (max-width:480px){
  /* C6: form rows put the label over the field (New document, Brand voice); the note under the buttons wraps inside the card */
  .vo-f,.nd-hit .vo-f{grid-template-columns:minmax(0,1fr)}
  .vo-f > :is(input,textarea,.menu-btn){width:100%}
  .nd-acts{flex-wrap:wrap}
  .nd-acts .ap-note{flex:1 1 100%;min-width:0;margin-left:0}
  /* Competitors › Their ads: one card a row, the "first seen · last shown" line under the header */
  .cp-ads-g{grid-template-columns:minmax(0,1fr)}
  .cp-ads-g .cp-ad:nth-last-child(2):nth-child(odd){border-bottom:1px solid var(--ln-2)}
  .cp-ad-h{flex-wrap:wrap}
  /* a long card title wraps inside its card; the header's tools go under it */
  .sec-hd{flex-wrap:wrap}
  :is(.sv,.cps,.cp,.hs-page) .sec-hd > h2,.sec-hd > h2{flex-shrink:1;min-width:0;max-width:100%;overflow-wrap:anywhere}
  /* smaller cuts: who a role covers, a change's source, a location's open work, a Home tile's name */
  .ag-rolep .stg-uc,.cg-srcl,.cg-srcl *{white-space:normal;min-width:0}
  .lc-facts-here .lc-fixin{flex:0 1 auto;min-width:0}
  .lc-inwork{min-width:0}
  .hs-st-l{white-space:normal}
  /* an action's stake reads as one sentence that wraps ("Opportunity ≈ 230 Google clicks a month (estimate) · from …"), not four squeezed columns */
  .fd-stk{display:block}
  .fd-stk > * + *{margin-left:4px}
}
/* loop fixer: the approval facts are one column in a narrow pane */
@container pg (max-width:520px){.ap-facts{grid-template-columns:minmax(0,1fr)!important}}
