/* ══════════════════════════════════════════════════════════════════════════════
   analysis-center-pro.css — VOLURR Analysis Center · design language (W1)
   Spec: docs/analysis/ANALYSIS_CENTER_SPEC.md
   ------------------------------------------------------------------------------
   NOT LINKED INTO index.html YET — by design. A stylesheet with no consumer
   changes nothing: no rule can match, so there is nothing to measure and nothing
   to regress. It is linked in W4 together with `view/inspector.js`, its first
   consumer, which is the first commit where a size / theme / token claim can be
   made honestly. Until then this file is a contract, not a behaviour.
   ------------------------------------------------------------------------------
   LAWS THIS FILE ENFORCES

   D1  NEW design language, not a polish of analysis-center.css. Every colour,
       space, radius, elevation and duration comes from a TOKEN (base.css /
       tokens.css). **ZERO hardcoded hex, zero rgba() literal, zero named colour
       in this file** — including fallbacks. base.css (index.html:24) and
       tokens.css (:25) both load before any consumer of this file, so a
       `var(--x, #hex)` safety fallback would be dead code that only serves to
       break the zero-hex law. See §0.1 for the one derived near-white.

   D6  Eight size classes (SPEC §6) — §11. Zero horizontal scrollbar and zero
       clipped control at every class. Controls WRAP rather than overflow: the
       drawtools campaign measured 1638 controls silently cut off by
       `overflow-x:hidden` (defect R6-D1) because a segmented control kept
       `white-space:nowrap` with no `flex-wrap`. That failure mode is designed
       out here from the start, at every width, not only on coarse pointers.

   D7  NO hover-only affordance. Every control that acts is visible without a
       pointer hovering it — §12 makes this unconditional on coarse pointers and
       :focus-within keeps it true for keyboard users on fine pointers.

   F5  SCOPING. `analysis-center.css` and `academy.css` share 25 unscoped `.ac-*`
       class names; every property academy does not itself declare falls through
       to the Analysis Center rule (SPEC §4.4 F5). This file therefore uses the
       `acp-` prefix — verified unused repo-wide — and roots its tokens on `.acp`.
       No selector here may be a bare generic name.

   RTL/LTR  LOGICAL PROPERTIES ONLY. No left/right/margin-left/padding-right,
       no `text-align:left|right`. AR and KU are RTL; EN is LTR; Kurdish is
       typically the longest string and sets the column width.

   COLOR LAW (BR-AGI-001)  --pcac / --gold crimson is the ONLY brand chrome
       accent. --up green / --down red are PRICE DIRECTION ONLY and never appear
       as UI chrome anywhere in this file (grep: they do not). The honesty tiers
       are --amber (real) · --info (broker tick) · --warn (estimate) · --muted
       (no source) — a provenance scale, never a good/bad scale.

   REAL DATA  §7 gives every honesty tier a visual form INCLUDING the "no source"
       tier. A card with no data must be able to say so; it must never be able to
       borrow the styling of a card that has data.
   ══════════════════════════════════════════════════════════════════════════════ */


/* ═══ §0 · component tokens ═══════════════════════════════════════════════════ */
.acp{
  /* geometry */
  --acp-w:min(1480px,97vw);      /* panel width, overridden per size class §11 */
  --acp-h:min(90vh,940px);
  --acp-rail:232px;
  --acp-aside:264px;
  --acp-insp:396px;              /* inspector width — matches the drawing inspector */
  --acp-col:224px;               /* grid column floor → 4 columns at the owner profile */
  --acp-row:40px;                /* inspector row height, 48 on coarse (§12) */
  --acp-tap:28px;                /* min control box, 44 on coarse (§12) */

  /* surfaces — derived, so both themes follow base.css with no override block */
  --acp-inset:color-mix(in srgb,var(--txt) 6%,transparent);
  --acp-hover:color-mix(in srgb,var(--txt) 9%,transparent);
  --acp-hair:color-mix(in srgb,var(--line) 70%,transparent);
  --acp-sb:color-mix(in srgb,var(--txt) 18%,transparent);
  --acp-sbh:color-mix(in srgb,var(--txt) 32%,transparent);
  --acp-glass:color-mix(in srgb,var(--card) 86%,transparent);
  --acp-scrim:color-mix(in srgb,var(--bg) 64%,transparent);
  --acp-blur:18px;               /* set to 0 by §13 on reduced-transparency */

  /* brand */
  --acp-ac:var(--pcac);
  --acp-ac-bg:var(--pcac-bg);
  --acp-solid:var(--gold2);      /* filled active state */

  /* §0.1 — text on a filled brand surface.
     There is no --on-brand token in the design system and a literal #fff would
     break the zero-hex law. It is derived instead, per theme, from a token that
     is near-white in that theme: dark --txt is #eef2fa, light --card is #ffffff.
     Both land above 4.5:1 on the theme's crimson, so this is a contrast decision
     with a source, not a convenience. */
  --acp-on:var(--txt);
}
html[data-theme="light"] .acp{ --acp-on:var(--card); }


/* ═══ §1 · overlay + panel shell ══════════════════════════════════════════════ */
.acp-scrim{
  position:fixed; inset:0; z-index:var(--z-modal,300);
  display:none; align-items:center; justify-content:center;
  padding:var(--sp-9,24px);
  background:var(--acp-scrim);
  -webkit-backdrop-filter:blur(6px); backdrop-filter:blur(6px);
}
.acp-scrim.is-open{display:flex}

.acp-panel{
  display:flex; flex-direction:column;
  width:var(--acp-w); height:var(--acp-h);
  background:var(--bg2); border:1px solid var(--line);
  border-radius:var(--rad-xl,18px);
  box-shadow:var(--el-4);
  overflow:hidden; outline:none;
  contain:layout paint;   /* the panel never invalidates the chart behind it (LAW 14) */
}


/* ═══ §2 · header ═════════════════════════════════════════════════════════════ */
/* The header WRAPS at every width. SPEC §4.4 F2: the current header cannot wrap
   between 721 and ~870px and `overflow:hidden` cuts the close button off — with
   tablet portrait (768) sitting inside the band. Wrapping is unconditional here. */
.acp-hd{
  flex:none; display:flex; flex-wrap:wrap; align-items:center;
  gap:var(--sp-4,10px);
  padding:var(--sp-4,10px) var(--sp-8,18px);
  border-block-end:1px solid var(--line);
  background:var(--card);
}
.acp-brand{display:flex;align-items:center;gap:var(--sp-3,8px);flex:0 1 auto;min-width:0}
.acp-brand b{
  font-size:16px; font-weight:800; letter-spacing:-.2px; color:var(--txt);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; min-width:0;
}
.acp-pro{
  flex:none; font-size:10px; font-weight:800; letter-spacing:.5px;
  color:var(--acp-ac); background:var(--acp-ac-bg);
  border:1px solid color-mix(in srgb,var(--acp-ac) 35%,var(--line));
  border-radius:var(--rad-xs,6px); padding:2px 6px;
}
/* search grows, but never below a usable box — it is not the only thing that gives */
.acp-srch{
  position:relative; flex:1 1 220px; min-width:180px; max-width:480px;
  display:flex; align-items:center;
}
.acp-srch input{
  width:100%; min-height:38px;
  padding-block:8px; padding-inline:36px var(--sp-5,12px);
  border:1px solid var(--line); border-radius:var(--rad-sm,9px);
  background:var(--card2); color:var(--txt); font:600 13.5px inherit;
  transition:border-color var(--dur-1,.12s) var(--ease,ease);
}
.acp-srch input::placeholder{color:var(--muted);font-weight:500}
.acp-srch input:focus{outline:0;border-color:color-mix(in srgb,var(--acp-ac) 55%,var(--line))}
.acp-srch svg{
  position:absolute; inset-inline-start:11px; inset-block-start:50%;
  transform:translateY(-50%); width:15px; height:15px;
  fill:none; stroke:var(--muted); stroke-width:2; pointer-events:none;
}
.acp-acts{display:flex;flex-wrap:wrap;gap:var(--sp-3,8px);margin-inline-start:auto}
.acp-act{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-2,6px);
  min-height:34px; min-width:var(--acp-tap); padding-inline:var(--sp-5,12px);
  border:1px solid var(--line); border-radius:var(--rad-md,10px);
  background:var(--card2); color:var(--txt2);
  font:600 13px inherit; white-space:nowrap;
  transition:background var(--dur-1,.12s) var(--ease,ease),
             color var(--dur-1,.12s) var(--ease,ease),
             border-color var(--dur-1,.12s) var(--ease,ease);
}
.acp-act:hover{color:var(--txt);border-color:color-mix(in srgb,var(--acp-ac) 45%,var(--line))}
.acp-act.is-pri{color:var(--acp-ac);border-color:color-mix(in srgb,var(--acp-ac) 45%,var(--line))}
.acp-act.is-pri:hover{background:var(--acp-ac-bg);border-color:var(--acp-ac)}
.acp-ib{
  flex:none; display:inline-flex; align-items:center; justify-content:center;
  width:34px; height:34px; min-width:var(--acp-tap); min-height:var(--acp-tap);
  border:1px solid var(--line); border-radius:var(--rad-md,10px);
  background:var(--card2); color:var(--txt2);
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease);
}
.acp-ib:hover{background:var(--acp-hover);color:var(--txt)}


/* ═══ §3 · body + rail ════════════════════════════════════════════════════════ */
.acp-body{flex:1 1 auto;display:flex;min-height:0;min-width:0}
.acp-rail{
  flex:0 0 var(--acp-rail); display:flex; flex-direction:column;
  min-height:0; min-width:0;
  border-inline-end:1px solid var(--line); background:var(--bg);
}
.acp-rail-l{flex:1 1 auto;min-height:0;padding:var(--sp-4,10px) var(--sp-3,8px)}
.acp-gt{
  padding:var(--sp-5,12px) var(--sp-3,8px) var(--sp-1,4px);
  font:800 10px inherit; letter-spacing:.9px; text-transform:uppercase; color:var(--muted);
}
.acp-cat{
  position:relative; display:flex; align-items:center; gap:var(--sp-4,10px);
  width:100%; min-height:var(--acp-tap); padding:var(--sp-3,8px) var(--sp-3,8px);
  border:0; border-radius:var(--rad-sm,9px); background:transparent;
  color:var(--txt2); font:500 13.5px inherit; text-align:start;
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease);
}
.acp-cat:hover{background:var(--acp-hover);color:var(--txt)}
.acp-cat[aria-selected="true"]{background:var(--acp-ac-bg);color:var(--txt);font-weight:700}
/* the active marker is a logical inline-start bar → it mirrors in LTR/RTL by itself */
.acp-cat[aria-selected="true"]::before{
  content:""; position:absolute; inset-block:4px; inset-inline-start:0;
  width:2.5px; border-radius:2px; background:var(--acp-ac);
}
.acp-cat-ic{flex:none;display:grid;place-items:center;width:18px;height:18px}
.acp-cat-lb{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* count badge — a REAL computed count (engine/counts.js), Latin digits, tabular */
.acp-n{
  flex:none; min-width:20px; padding:1px 7px; border-radius:var(--rad-xs,6px);
  background:var(--card2); color:var(--txt2);
  font:600 11px inherit; text-align:center;
  font-variant-numeric:tabular-nums; direction:ltr;
}
.acp-cat[aria-selected="true"] .acp-n{color:var(--acp-ac);background:var(--acp-ac-bg)}


/* ═══ §4 · main column ════════════════════════════════════════════════════════ */
.acp-main{flex:1 1 auto;display:flex;flex-direction:column;min-width:0;min-height:0}
.acp-chips{
  flex:none; display:flex; flex-wrap:wrap; gap:var(--sp-2,6px);
  padding:var(--sp-5,12px) var(--sp-8,18px) var(--sp-1,4px);
}
.acp-chip{
  min-height:var(--acp-tap); padding:5px var(--sp-5,12px);
  border:1px solid var(--line); border-radius:var(--rad-pill,999px);
  background:var(--card2); color:var(--txt2);
  font:600 12px inherit; white-space:nowrap;
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease),
             border-color var(--dur-1,.12s) var(--ease,ease);
}
.acp-chip:hover{color:var(--txt);border-color:color-mix(in srgb,var(--acp-ac) 40%,var(--line))}
.acp-chip[aria-pressed="true"]{
  background:var(--acp-ac-bg); border-color:color-mix(in srgb,var(--acp-ac) 50%,var(--line));
  color:var(--acp-ac);
}

.acp-sh{
  flex:none; display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between;
  gap:var(--sp-5,12px); padding:var(--sp-4,10px) var(--sp-8,18px) var(--sp-3,8px);
}
.acp-sh-t{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:var(--sp-3,8px);
  min-width:0; font:800 18px inherit; letter-spacing:-.2px; color:var(--txt);
}
.acp-sh-n{font:600 12px inherit;color:var(--muted);font-variant-numeric:tabular-nums;direction:ltr}
/* per-symbol honesty split — the same source as the per-card pills, so the two
   can never disagree. It WRAPS instead of being deleted at narrow widths: the
   old rule hid it below 560px, which removed the honesty statement exactly where
   the per-card pills are hardest to read. */
.acp-sh-s{
  flex:1 1 100%; min-width:0; font:600 11px inherit; color:var(--muted);
  font-variant-numeric:tabular-nums;
}
.acp-sh-c{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-3,8px)}
.acp-tg{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--sp-2,6px);
  min-width:var(--acp-tap); min-height:var(--acp-tap); padding-inline:var(--sp-3,8px);
  border:1px solid var(--line); border-radius:var(--rad-sm,9px);
  background:var(--card2); color:var(--txt2); font:600 12px inherit;
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease);
}
.acp-tg:hover{color:var(--txt);border-color:color-mix(in srgb,var(--acp-ac) 40%,var(--line))}
.acp-tg[aria-pressed="true"]{
  background:var(--acp-ac-bg); border-color:color-mix(in srgb,var(--acp-ac) 50%,var(--line));
  color:var(--acp-ac);
}
.acp-sep{flex:none;inline-size:1px;block-size:20px;background:var(--line);margin-inline:var(--sp-1,4px)}


/* ═══ §5 · scroll surfaces — in-panel bar, never the native OS bar ════════════ */
.acp-scroll,.acp-rail-l,.acp-aside,.acp-grid,.acp-insp-b{
  overflow-y:auto; overflow-x:hidden; overscroll-behavior:contain;
  scrollbar-width:thin; scrollbar-color:var(--acp-sb) transparent; scrollbar-gutter:stable;
  touch-action:pan-y;   /* a two-finger scroll inside the panel never reaches the chart */
}
.acp-scroll::-webkit-scrollbar,.acp-rail-l::-webkit-scrollbar,.acp-aside::-webkit-scrollbar,
.acp-grid::-webkit-scrollbar,.acp-insp-b::-webkit-scrollbar{width:6px;height:0}
.acp-scroll::-webkit-scrollbar-track,.acp-rail-l::-webkit-scrollbar-track,
.acp-aside::-webkit-scrollbar-track,.acp-grid::-webkit-scrollbar-track,
.acp-insp-b::-webkit-scrollbar-track{background:transparent}
.acp-scroll::-webkit-scrollbar-thumb,.acp-rail-l::-webkit-scrollbar-thumb,
.acp-aside::-webkit-scrollbar-thumb,.acp-grid::-webkit-scrollbar-thumb,
.acp-insp-b::-webkit-scrollbar-thumb{background:var(--acp-sb);border-radius:var(--rad-pill,999px)}
.acp-scroll::-webkit-scrollbar-thumb:hover,.acp-rail-l::-webkit-scrollbar-thumb:hover,
.acp-aside::-webkit-scrollbar-thumb:hover,.acp-grid::-webkit-scrollbar-thumb:hover,
.acp-insp-b::-webkit-scrollbar-thumb:hover{background:var(--acp-sbh)}
.acp-scroll::-webkit-scrollbar-button,.acp-rail-l::-webkit-scrollbar-button,
.acp-aside::-webkit-scrollbar-button,.acp-grid::-webkit-scrollbar-button,
.acp-insp-b::-webkit-scrollbar-button,.acp-scroll::-webkit-scrollbar-corner{
  display:none;width:0;height:0;background:transparent;
}
/* structural guard against flex-child overflow — scoped to LAYOUT boxes ONLY.
   `.acp *` would sit at (0,1,1) and out-specify every control rule, silently
   zeroing each min-width: that is how a 44px touch target measured 28px in the
   drawtools campaign. Named boxes only, deliberately. */
.acp-body,.acp-main,.acp-hd,.acp-brand,.acp-sh,.acp-sh-t,.acp-grid,.acp-card,
.acp-c-mid,.acp-insp,.acp-insp-b,.acp-r,.acp-r>label,.acp-ctl{min-width:0}


/* ═══ §6 · filters aside ══════════════════════════════════════════════════════ */
.acp-aside{
  flex:0 0 var(--acp-aside); min-height:0;
  padding:var(--sp-6,14px) var(--sp-7,16px) var(--sp-9,24px);
  border-inline-start:1px solid var(--line); background:var(--bg);
}
.acp-fh{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3,8px);
  padding-block-end:var(--sp-2,6px);font:700 14px inherit;color:var(--txt)}
.acp-fsec{padding-block:var(--sp-5,12px);border-block-start:1px solid var(--line)}
.acp-flb{margin-block-end:var(--sp-3,8px);font:800 10px inherit;letter-spacing:.8px;
  text-transform:uppercase;color:var(--muted)}
.acp-fopts{display:flex;flex-direction:column;gap:var(--sp-2,6px)}
.acp-fopt{
  display:flex; align-items:center; gap:var(--sp-2,6px);
  min-height:var(--acp-tap); padding:var(--sp-3,8px) var(--sp-4,10px);
  border:1px solid var(--line); border-radius:var(--rad-sm,9px);
  background:var(--card2); color:var(--txt2); font:600 12.5px inherit; text-align:start;
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease);
}
.acp-fopt:hover{color:var(--txt);border-color:color-mix(in srgb,var(--acp-ac) 40%,var(--line))}
.acp-fopt[aria-pressed="true"]{background:var(--acp-ac-bg);
  border-color:color-mix(in srgb,var(--acp-ac) 50%,var(--line));color:var(--txt)}
.acp-ftags{display:flex;flex-wrap:wrap;gap:var(--sp-2,6px)}
.acp-ftag{
  display:inline-flex; align-items:center; gap:var(--sp-2,6px);
  min-height:var(--acp-tap); padding:5px var(--sp-4,10px);
  border:1px solid var(--line); border-radius:var(--rad-pill,999px);
  background:var(--card2); color:var(--txt2); font:600 11.5px inherit;
}
.acp-ftag[aria-pressed="true"]{background:var(--acp-ac-bg);color:var(--acp-ac);
  border-color:color-mix(in srgb,var(--acp-ac) 50%,var(--line))}
/* a facet with a real count of zero is DISABLED, not hidden — the user learns the
   filter exists and that this symbol has none, which is a fact, not an absence */
.acp-ftag[disabled]{opacity:.45;pointer-events:none}
.acp-ftn{font:700 10px inherit;color:var(--muted);font-variant-numeric:tabular-nums;direction:ltr}
.acp-ftag[aria-pressed="true"] .acp-ftn{color:var(--acp-ac)}
.acp-fcount{padding-block-start:var(--sp-5,12px);border-block-start:1px solid var(--line);
  font:400 12px inherit;color:var(--muted);font-variant-numeric:tabular-nums}
.acp-fcount b{color:var(--txt);font-weight:700}


/* ═══ §7 · grid + card ════════════════════════════════════════════════════════ */
.acp-grid{flex:1 1 auto;min-height:0;padding:var(--sp-3,8px) var(--sp-8,18px) var(--sp-9,24px)}
.acp-grid-in{
  display:grid; gap:var(--sp-6,14px); align-items:stretch;
  grid-template-columns:repeat(auto-fill,minmax(min(var(--acp-col),100%),1fr));
  /* min() lets auto-fill drop BELOW the floor instead of overflowing the panel —
     the guard against a horizontal scrollbar at every intermediate width */
}
.acp-card{
  display:flex; flex-direction:column; gap:var(--sp-4,10px);
  padding:var(--sp-6,14px);
  border:1px solid var(--line); border-radius:var(--rad-lg,14px);
  background:var(--card); text-align:start;
  transition:border-color var(--dur-1,.12s) var(--ease,ease),
             box-shadow var(--dur-1,.12s) var(--ease,ease),
             background var(--dur-1,.12s) var(--ease,ease);
}
.acp-card:hover{border-color:color-mix(in srgb,var(--acp-ac) 38%,var(--line));box-shadow:var(--el-1)}
.acp-card[aria-pressed="true"]{
  border-color:color-mix(in srgb,var(--acp-ac) 52%,var(--line));
  background:color-mix(in srgb,var(--acp-ac) 6%,var(--card));
}
.acp-c-top{display:flex;align-items:flex-start;gap:var(--sp-4,10px)}
/* --acp-ic is set inline by the renderer from the card's own colour token */
.acp-ic{
  flex:none; display:grid; place-items:center; width:40px; height:40px;
  border-radius:var(--rad-md,10px); background:var(--acp-ic,var(--acp-ac));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--acp-ic,var(--acp-ac)) 80%,var(--txt));
}
.acp-ic svg{width:21px;height:21px;display:block}
.acp-c-mid{flex:1 1 auto;min-width:0}
.acp-c-name{font:700 14.5px inherit;color:var(--txt);letter-spacing:-.1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acp-c-desc{margin-block-start:2px;font:400 11.5px inherit;line-height:1.45;color:var(--txt2);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.acp-tags{display:flex;flex-wrap:wrap;gap:var(--sp-1,4px)}
.acp-tag{
  padding:2px var(--sp-3,8px); border:1px solid var(--line); border-radius:var(--rad-xs,6px);
  background:color-mix(in srgb,var(--card2) 65%,transparent);
  font:600 10px inherit; color:var(--muted); white-space:nowrap;
}
/* the real per-card preview. `.acp-spark-na` is NOT a decoration: it is the
   honest state for a card whose named series cannot be computed on this symbol.
   REAL-DATA LAW: a card may never fall back to drawing PRICE under an indicator's
   name (SPEC §4.2 C1 — 65 of 92 do that today). No series → this box. */
.acp-spark{display:block;inline-size:100%;block-size:38px}
.acp-spark-ph{block-size:38px}
.acp-spark-na{
  display:grid; place-items:center; block-size:38px;
  border:1px dashed var(--line); border-radius:var(--rad-sm,9px);
  background:color-mix(in srgb,var(--card2) 40%,transparent);
  font:600 10.5px inherit; letter-spacing:.3px; color:var(--muted); text-align:center;
}
.acp-c-val{font:400 11px inherit;color:var(--muted);font-variant-numeric:tabular-nums}
.acp-c-val b{color:var(--txt2);font-weight:700}
.acp-c-bot{display:flex;flex-wrap:wrap;align-items:center;gap:var(--sp-3,8px);margin-block-start:auto}
.acp-c-foot{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--sp-2,6px)}
/* card action buttons — ALL of them meet --acp-tap and NONE is hover-revealed (D7) */
.acp-cb{
  flex:none; display:inline-flex; align-items:center; justify-content:center;
  min-width:var(--acp-tap); min-height:var(--acp-tap);
  border:0; border-radius:var(--rad-xs,6px); background:transparent; color:var(--muted);
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease);
}
.acp-cb:hover{background:var(--acp-hover);color:var(--acp-ac)}
.acp-cb[aria-pressed="true"]{color:var(--acp-ac)}
.acp-add{
  flex:none; display:inline-flex; align-items:center; justify-content:center;
  min-width:32px; min-height:32px;
  border:1px solid var(--line); border-radius:var(--rad-sm,9px);
  background:var(--card2); color:var(--txt2); font:600 16px inherit;
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease),
             border-color var(--dur-1,.12s) var(--ease,ease);
}
.acp-add:hover{border-color:var(--acp-ac);color:var(--acp-ac);background:var(--acp-ac-bg)}
.acp-add[aria-pressed="true"]{background:var(--acp-ac);border-color:var(--acp-ac);color:var(--acp-on)}
.acp-add.is-radio{border-radius:var(--rad-pill,999px)}


/* ═══ §7.1 · HONESTY TIERS — provenance, never quality ════════════════════════
   A provenance scale, not a good/bad scale, and deliberately NOT green/red:
   --up/--down belong to price direction only (COLOR LAW).
     real  --amber  real per-trade tape / real volume
     tick  --info   real BROKER TICK-COUNT volume (pcRealVol is the authority)
     est   --warn   estimated / derived — honest approximation
     na    --muted  NO source for this symbol. Must stay visually distinct: a
                    card with no data may never borrow the look of one with data.
   ─────────────────────────────────────────────────────────────────────────── */
.acp-q{
  display:inline-flex; align-items:center; gap:var(--sp-1,4px);
  padding:2px 7px; border:1px solid; border-radius:var(--rad-xs,6px);
  font:800 9px inherit; letter-spacing:.4px; text-transform:uppercase;
  line-height:1; white-space:nowrap;
}
.acp-q::before{content:"";flex:none;width:5px;height:5px;border-radius:50%;background:currentColor}
.acp-q.is-real{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 40%,var(--line));
  background:color-mix(in srgb,var(--amber) 10%,transparent)}
.acp-q.is-tick{color:var(--info);border-color:color-mix(in srgb,var(--info) 38%,var(--line));
  background:color-mix(in srgb,var(--info) 9%,transparent)}
.acp-q.is-est{color:var(--warn);border-color:color-mix(in srgb,var(--warn) 36%,var(--line));
  background:color-mix(in srgb,var(--warn) 8%,transparent)}
.acp-q.is-na{color:var(--muted);border-color:var(--line);background:transparent}
.acp-q.is-na::before{background:transparent;box-shadow:inset 0 0 0 1px currentColor}

/* complexity tier — an EDITORIAL classification. `.acp-cx` carries a permanent
   textual qualifier from the renderer (SPEC §4.2 C3): the badge must never read
   as a measured score. It is deliberately the quietest badge on the card. */
.acp-cx{
  padding:2px var(--sp-2,6px); border:1px solid var(--line); border-radius:var(--rad-xs,6px);
  background:transparent; color:var(--muted);
  font:800 8.5px inherit; letter-spacing:.4px; line-height:1; white-space:nowrap;
}

/* per-symbol capability banner — shown for EVERY family, not only Order Flow
   (SPEC §4.3 E1/E2). Neutral by default; tinted only when a real tier applies. */
.acp-banner{
  display:flex; align-items:flex-start; gap:var(--sp-3,8px);
  margin-block-end:var(--sp-5,12px); padding:var(--sp-4,10px) var(--sp-5,12px);
  border:1px solid var(--line); border-radius:var(--rad-md,10px);
  background:color-mix(in srgb,var(--card2) 55%,transparent);
  font:400 11.5px inherit; line-height:1.5; color:var(--txt2);
}
.acp-banner b{color:var(--txt);font-weight:700}
.acp-banner-d{flex:none;width:8px;height:8px;border-radius:50%;margin-block-start:4px;background:var(--muted)}
.acp-banner.is-real{border-color:color-mix(in srgb,var(--amber) 32%,var(--line));
  background:color-mix(in srgb,var(--amber) 7%,transparent)}
.acp-banner.is-real .acp-banner-d{background:var(--amber)}
.acp-banner.is-tick{border-color:color-mix(in srgb,var(--info) 30%,var(--line));
  background:color-mix(in srgb,var(--info) 6%,transparent)}
.acp-banner.is-tick .acp-banner-d{background:var(--info)}
.acp-banner.is-est{border-color:color-mix(in srgb,var(--warn) 28%,var(--line));
  background:color-mix(in srgb,var(--warn) 6%,transparent)}
.acp-banner.is-est .acp-banner-d{background:var(--warn)}


/* ═══ §8 · INSPECTOR (D1) — the settings surface that has never existed ═══════
   Same information architecture and the same control vocabulary as the drawing
   inspector, so the two cannot drift into two different products. Docked beside
   the grid on wide classes; a bottom sheet on phones (§11).                    */
.acp-insp{
  flex:0 0 var(--acp-insp); display:flex; flex-direction:column;
  min-width:0; min-height:0;
  border-inline-start:1px solid var(--line); background:var(--card);
  contain:layout paint;
}
.acp-insp[hidden]{display:none}
.acp-insp-h{
  flex:none; display:flex; align-items:center; gap:var(--sp-4,10px);
  padding:var(--sp-6,14px) var(--sp-6,14px) var(--sp-5,12px);
}
.acp-insp-h b{flex:1 1 auto;min-width:0;font:800 15px inherit;letter-spacing:-.1px;color:var(--txt);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* scope control — same three write targets as the drawing inspector */
.acp-scope{display:flex;gap:var(--sp-1,4px);padding-inline:var(--sp-6,14px);
  padding-block-end:var(--sp-4,10px)}
.acp-scope button{
  flex:1 1 0; min-width:0; min-height:var(--acp-tap);
  padding:var(--sp-3,8px) var(--sp-1,4px);
  border:0; border-radius:var(--rad-sm,9px);
  background:var(--acp-inset); color:var(--txt2);
  font:700 10.5px inherit; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease);
}
.acp-scope button[aria-pressed="true"]{background:var(--acp-ac);color:var(--acp-on)}
.acp-insp-b{flex:1 1 auto;min-height:0;padding-inline:var(--sp-6,14px);
  padding-block-end:var(--sp-5,12px)}
.acp-g{
  position:sticky; inset-block-start:0; z-index:3;
  display:flex; align-items:center; gap:var(--sp-3,8px);
  padding:var(--sp-4,10px) 2px var(--sp-2,6px);
  background:var(--card);
}
.acp-g b{font:800 10px inherit;letter-spacing:.7px;text-transform:uppercase;color:var(--muted)}
.acp-g hr{flex:1;margin:0;border:0;border-block-start:1px solid var(--acp-hair)}

/* A ROW MAY WRAP AT EVERY WIDTH. This is the R6-D1 lesson, applied before the
   defect exists: a control that cannot fit beside its label takes the next line.
   It is never cut, and it never forces a horizontal scrollbar. */
.acp-r{
  display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-4,10px);
  min-height:var(--acp-row); padding:3px 2px; border-radius:var(--rad-sm,9px);
}
.acp-r>label{
  flex:1 1 auto; min-width:38%; display:flex; align-items:center; gap:7px;
  font:600 12.5px inherit; color:var(--txt2);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
/* source dot — hollow = inherited · filled = overridden on this card */
.acp-r>label::before{
  content:""; flex:none; width:6px; height:6px; border-radius:50%;
  box-shadow:inset 0 0 0 1px var(--muted); opacity:.55;
}
.acp-r[data-ov="1"]>label{color:var(--txt)}
.acp-r[data-ov="1"]>label::before{background:var(--acp-ac);opacity:1;box-shadow:none}
.acp-ctl{flex:0 1 auto;max-width:100%;display:inline-flex;align-items:center;
  gap:var(--sp-3,8px);margin-inline-start:auto}
/* revert — visible whenever the row is overridden AND focused/hovered on a fine
   pointer, and UNCONDITIONALLY visible on coarse pointers (§12). Never the only
   way to reach a value. */
.acp-rev{
  flex:none; display:none; align-items:center; justify-content:center;
  min-width:22px; min-height:22px;
  border:0; border-radius:var(--rad-xs,6px); background:transparent; color:var(--muted);
}
.acp-r[data-ov="1"]:hover .acp-rev,
.acp-r[data-ov="1"]:focus-within .acp-rev{display:inline-flex}
.acp-rev:hover{background:var(--acp-hover);color:var(--acp-ac)}
.acp-rev svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}


/* ═══ §8.1 · the settings box as a STANDALONE docked surface ══════════════════
   §8 designs the inspector as a column of the pro shell (`.acp-body > .acp-insp`).
   The pro shell is not built yet and the settings box is; so the box mounts its
   own host — the SAME `.acp` token block, the SAME `.acp-insp` component — docked
   to the inline-end edge above the shipped `#acenter` (z-index 1200). When the pro
   shell lands, the host is deleted and the component moves into `.acp-body`
   unchanged: nothing below re-styles `.acp-insp` itself.                        */
/* The host spans the inline axis and docks its child to the inline-end edge, rather than shrink-wrapping
   to that child. MEASURED, and it is the reason the container query below is safe: with only
   `inset-inline-end:0` the host's width was shrink-to-fit FROM ITS CONTENT, and an inline-size container
   contributes 0 to its parent's intrinsic size by definition — the box collapsed to 1px at 480 and 768,
   taking 1 200 clipped controls and 800 horizontal-scroll containers with it (ac-size-box, first run after
   the container query). A definite inline size removes the dependency entirely. The host stays
   `pointer-events:none`, so spanning the viewport costs the chart and the grid nothing. */
.acs{
  position:fixed; inset-block:0; inset-inline:0; z-index:1210;
  display:flex; justify-content:flex-end; max-inline-size:100%;
  pointer-events:none;                 /* the chart and the grid stay reachable beside it */
}
.acs[hidden]{display:none}
.acs>.acp-insp{pointer-events:auto;box-shadow:var(--el-3);position:relative}
/* ── BOX CONTROL (owner: drag + resize, mouse AND touch) ──────────────────────────────────────────
   Docked (default) is byte-identical to before; .acs-float is entered by the first header-drag or
   corner-resize (settings-box.js boxDown) and carries explicit physical top/left/width/height. */
.acs.acs-float{justify-content:flex-start}
.acs.acs-float>.acp-insp{position:fixed;border:1px solid var(--line);border-radius:14px;overflow:hidden}
.acs>.acp-insp .acp-insp-h{cursor:grab;touch-action:none;user-select:none;-webkit-user-select:none}
.acs.acs-gesture>.acp-insp{box-shadow:var(--el-3)}
.acs.acs-gesture .acp-insp-h{cursor:grabbing}
.acs-rz{position:absolute;inset-inline-start:0;inset-block-end:0;width:24px;height:24px;cursor:nesw-resize;touch-action:none;z-index:5}
[dir="rtl"] .acs-rz{cursor:nwse-resize}
.acs-rz::before{content:'';position:absolute;inset-inline-start:5px;inset-block-end:5px;width:9px;height:9px;
  border-inline-start:2px solid var(--muted);border-block-end:2px solid var(--muted);border-end-start-radius:5px;opacity:.45}
.acs-rz:hover::before{opacity:.9}
@media (max-width:479px){.acs-rz{display:none}}   /* the phone sheet IS the phone geometry — no float there */
.acs-orb{
  flex:none; display:grid; place-items:center;
  inline-size:30px; block-size:30px; border-radius:var(--rad-md,10px);
  background:var(--acp-ac-bg); color:var(--acp-ac);
}
.acs-orb svg{inline-size:17px;block-size:17px;fill:none;stroke:currentColor;
  stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.acs-sub{flex:none;font:600 10.5px var(--font-mono);color:var(--muted);
  direction:ltr;font-variant-numeric:tabular-nums;white-space:nowrap}
.acs .acp-ib svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
.acs .acp-act svg{width:14px;height:14px;flex:none;fill:none;stroke:currentColor;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.acs-srch{padding-inline:var(--sp-6,14px);padding-block-end:var(--sp-4,10px)}
.acs-srch .acp-srch{flex:1 1 auto;max-width:none}
/* the tab strip IS the scope control's geometry — same component, one role apart */
.acp-tabs[role="tablist"] button[aria-pressed="true"]{background:var(--acp-ac);color:var(--acp-on)}
.acs-f{
  flex:none; display:flex; flex-wrap:wrap; gap:var(--sp-3,8px);
  padding:var(--sp-4,10px) var(--sp-6,14px) var(--sp-5,12px);
  border-block-start:1px solid var(--acp-hair);
}
.acs-f .acp-act{flex:1 1 auto}
.acs-f .acp-act[aria-pressed="true"]{color:var(--acp-ac);
  border-color:color-mix(in srgb,var(--acp-ac) 45%,var(--line));background:var(--acp-ac-bg)}
/* phone: the host itself becomes the sheet slot; §11 already turns .acp-insp into
   the sheet, so the host only has to stop being a full-height inline-end column */
@media (max-width:479px){ .acs{inset-block:auto 0} }
/* MEASURED (ac-size-gate --box, 400 cells): the header line is orb + NAME + sub + close, and `.acs-sub` is
   flex:none nowrap, so it takes its ~90px off the top of the name's share. The card name — which is the
   box's whole identity — ellipsised on the ONE card whose name is longest ("Auto pattern detection"): 4px
   lost in the 375px phone sheet, 10px lost at every DPR wherever `--acp-insp` is 360px.
   THE PREDICATE IS THE BOX, NOT THE VIEWPORT. The box is 396px at one viewport band, 372px at another and
   360px at a third; a media query would be a proxy for the thing that actually decides, and it is why the
   first fix closed 375px and left 1024px open. A container query asks the real question. Nothing is hidden
   to satisfy it: the sub keeps every character and takes the next line, which gives the name the full
   remaining width. `order` alone performs the wrap, so the close button stays on line 1. */
.acs>.acp-insp{container-type:inline-size;container-name:acsbox}
@container acsbox (max-width:390px){
  .acs .acp-insp-h{flex-wrap:wrap}
  .acs .acs-sub{order:9;flex:1 1 100%;padding-inline-start:40px}
}

/* ── W17 · THE SCOPE SWITCH + THE MIXED STATE ────────────────────────────────
   The switch itself is .acp-scope, unchanged — the same component the tab strip
   uses and the same one the drawing inspector's one/tool/all wears, because it
   is the same idea: the same controls, a different write target. Only two extra
   things are needed. */
/* (1) the family COUNT rides inside the "all indicators" button. It is a real
   measured number (§2b famIds().length), so it is rendered as data, not as
   decoration, and it must not push the label out of the button. */
.acs-scopesw .acs-n{
  font-style:normal; font-weight:800; font-family:var(--font-mono);
  opacity:.62; margin-inline-start:3px;
}
.acs-scopesw button[aria-pressed="true"] .acs-n{opacity:.8}
/* (2) MIXED — at scope=all the 90 cards do not agree on this property. The row
   states that in WORDS (data-mix-lbl carries the translated label) rather than
   showing one card's value as if it were all of them. ::after, not a node:
   sync() may not create one (LAW 14). */
.acs .acp-r[data-mix="1"]>label::after{
  content:attr(data-mix-lbl);
  flex:none; margin-inline-start:6px; padding:1px 5px;
  border-radius:var(--rad-xs,6px);
  background:var(--acp-inset); color:var(--muted);
  font:800 9px var(--font-mono); letter-spacing:.4px; text-transform:uppercase;
}
/* a mixed row is BY DEFINITION overridden somewhere, so its revert must be
   reachable on a fine pointer too — otherwise the only way out of "mixed" is to
   set a value, which is not the same act as clearing one. */
.acs .acp-r[data-mix="1"]:hover .acp-rev,
.acs .acp-r[data-mix="1"]:focus-within .acp-rev{display:inline-flex}

/* ── W18 · THE REACH, NAMED · AND THE WAY OUT OF MIXED ───────────────────────
   (3) `83/90` is a CLAIM about seven indicators the reader cannot see. So it is
   a BUTTON, and it opens their names. Not a title attribute and not a hover
   reveal: on a touch screen neither exists, and §12's law is that no affordance
   may be hover-only. The list node is built with the row and only toggled, so
   sync() still creates nothing (LAW 14). */
.acs-rx{
  flex:none; display:inline-flex; align-items:center; justify-content:center;
  min-block-size:22px; padding-inline:6px;
  border:0; border-radius:var(--rad-xs,6px);
  background:var(--acp-inset); color:var(--muted);
  font:800 10px var(--font-mono); letter-spacing:.3px;
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease);
}
.acs-rx:hover{background:var(--acp-hover);color:var(--txt2)}
.acs-rx[aria-expanded="true"]{background:var(--acp-hover);color:var(--acp-ac)}
.acs-rxl{
  flex:1 1 100%; display:flex; flex-wrap:wrap; gap:4px;
  margin-block-start:2px; padding:var(--sp-3,8px);
  border-radius:var(--rad-sm,9px); background:var(--acp-inset);
}
.acs-rxl b{
  flex:1 1 100%; margin-block-end:2px;
  font:800 9.5px inherit; letter-spacing:.4px; text-transform:uppercase; color:var(--muted);
}
.acs-rxl span{
  padding:2px 6px; border-radius:var(--rad-xs,6px);
  background:var(--acp-hover); color:var(--txt2); font:600 10.5px inherit;
}
/* (4) MIXED → agreement AT A VALUE. Clearing was always available; agreeing was
   not: a colour picker and a slider both sit on a concrete value while the row
   is mixed, so choosing that value fires no event and writes nothing. This
   button commits what the control is showing. It is ABSENT while the row
   agrees — never present-and-dead. */
.acs-mixa{
  display:none; align-items:center; justify-content:center;
  min-block-size:22px; padding-inline:var(--sp-3,8px);
  border:0; border-radius:var(--rad-xs,6px);
  background:var(--acp-solid); color:var(--acp-on);
  font:800 10.5px inherit; white-space:nowrap;
}
.acs .acp-r[data-mix="1"] .acs-mixa{display:inline-flex}
.acs-mixa:hover{filter:brightness(1.08)}


/* ═══ §9 · control vocabulary ═════════════════════════════════════════════════ */
.acp-seg{
  display:inline-flex; flex-wrap:wrap; max-width:100%; gap:2px; padding:3px;
  border-radius:var(--rad-md,10px); background:var(--acp-inset);
}
.acp-seg button{
  display:inline-flex; align-items:center; justify-content:center;
  min-height:var(--acp-tap); padding:5px var(--sp-3,8px);
  border:0; border-radius:var(--rad-xs,6px);
  background:transparent; color:var(--txt2); font:700 11px inherit; white-space:nowrap;
  transition:background var(--dur-1,.12s) var(--ease,ease), color var(--dur-1,.12s) var(--ease,ease);
}
.acp-seg button:hover:not([aria-pressed="true"]){color:var(--txt)}
.acp-seg button[aria-pressed="true"]{background:var(--acp-solid);color:var(--acp-on)}

.acp-num,.acp-txt{
  min-height:var(--acp-tap); padding:6px var(--sp-3,8px);
  border:1px solid transparent; border-radius:var(--rad-sm,9px);
  background:var(--acp-inset); color:var(--txt);
}
/* Latin digits law: numeric fields are direction:ltr with tabular figures in all
   three languages — a number is never rendered in Arabic-Indic form. */
.acp-num{inline-size:112px;font:600 11.5px var(--font-mono);font-variant-numeric:tabular-nums;
  direction:ltr;text-align:end}
.acp-txt{inline-size:100%;font:600 12px inherit}
.acp-num:focus,.acp-txt:focus{outline:0;border-color:color-mix(in srgb,var(--acp-ac) 55%,var(--line))}

.acp-rng{display:flex;align-items:center;gap:var(--sp-3,8px)}
.acp-rng input[type=range]{
  inline-size:106px; max-inline-size:100%; block-size:var(--acp-tap);
  accent-color:var(--acp-ac);
  touch-action:none;   /* the slider owns the drag — the panel never scrolls under it */
}
.acp-rng b{min-inline-size:44px;text-align:end;font:700 11.5px var(--font-mono);
  color:var(--txt);font-variant-numeric:tabular-nums;direction:ltr}

.acp-tgl{
  position:relative; flex:none; inline-size:40px; block-size:23px;
  min-inline-size:44px; min-block-size:var(--acp-tap);
  padding:0; border:0; border-radius:var(--rad-pill,999px);
  background:var(--acp-inset); box-shadow:inset 0 0 0 1px var(--acp-hair);
  transition:background var(--dur-1,.12s) var(--ease,ease);
}
/* the knob travels along the INLINE axis, so it mirrors in RTL by itself */
.acp-tgl i{
  position:absolute; inset-block-start:50%; inset-inline-start:3px;
  inline-size:17px; block-size:17px; margin-block-start:-8.5px;
  border-radius:50%; background:var(--muted);
  transition:inset-inline-start var(--dur-1,.12s) var(--ease,ease),
             background var(--dur-1,.12s) var(--ease,ease);
}
.acp-tgl[aria-pressed="true"]{background:var(--acp-ac);box-shadow:none}
.acp-tgl[aria-pressed="true"] i{inset-inline-start:20px;background:var(--acp-on)}

.acp-col{
  position:relative; flex:none; inline-size:38px; block-size:32px;
  min-inline-size:var(--acp-tap); min-block-size:var(--acp-tap);
  border:0; border-radius:var(--rad-md,10px); background:var(--acp-c,var(--acp-ac));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--txt) 20%,transparent);
}
.acp-col input{position:absolute;inset:0;inline-size:100%;block-size:100%;opacity:0;
  border-radius:inherit;cursor:pointer}
/* INHERITED colour. The engine's effective default for an unoverridden colour is computed inside the panel
   that draws it and is in no table a schema-driven box can read, so the swatch must NOT assert a colour it
   never measured. It renders as an explicit empty state instead — the same statement the row's hollow
   source dot makes, on the control itself. (REAL-DATA LAW: state the limit, never invent the value.) */
.acp-col[data-inh="1"]{background:var(--acp-inset);
  box-shadow:inset 0 0 0 1px var(--acp-hair)}
.acp-col[data-inh="1"]::after{
  content:""; position:absolute; inset-block:50%; inset-inline:6px;
  block-size:1px; margin-block-start:-.5px; background:var(--muted); opacity:.55;
}

/* honesty note — the surface used where a control is deliberately ABSENT, or
   where a value cannot be sourced for this symbol. Stating the limitation is the
   requirement; hiding the row is not an option (REAL-DATA LAW). */
.acp-note{
  display:flex; align-items:flex-start; gap:var(--sp-3,8px);
  margin-block:2px 4px; padding:var(--sp-3,8px) var(--sp-4,10px);
  border:1px solid color-mix(in srgb,var(--acp-ac) 22%,transparent);
  border-radius:var(--rad-md,10px);
  background:color-mix(in srgb,var(--acp-ac) 8%,transparent);
  font:600 11.5px inherit; line-height:1.55; color:var(--txt2);
}
.acp-note svg{flex:none;width:15px;height:15px;margin-block-start:1px;
  fill:none;stroke:var(--acp-ac);stroke-width:2}

.acp-empty{padding:var(--sp-10,32px) var(--sp-5,12px);text-align:center;
  font:600 12.5px inherit;color:var(--muted)}


/* ═══ §10 · focus — one visible ring for every interactive element ════════════
   Declared once, on a list, so a control added later cannot be born without a
   focus ring. `:focus-visible` only: a pointer click never paints it.          */
.acp-act:focus-visible,.acp-ib:focus-visible,.acp-cat:focus-visible,.acp-chip:focus-visible,
.acp-tg:focus-visible,.acp-fopt:focus-visible,.acp-ftag:focus-visible,.acp-card:focus-visible,
.acp-cb:focus-visible,.acp-add:focus-visible,.acp-scope button:focus-visible,
.acp-seg button:focus-visible,.acp-tgl:focus-visible,.acp-rev:focus-visible,
.acp-col:focus-within,.acp-srch input:focus-visible,.acp-rng input:focus-visible{
  outline:2px solid var(--acp-ac); outline-offset:2px;
}
.acp-seg button:focus-visible{outline-offset:-2px}


/* ═══ §11 · SIZE CLASSES (D6 · SPEC §6) ══════════════════════════════════════ */

/* Large / 4K ≥1920 — the panel does NOT scale with the viewport; it stays at its
   designed measure so a card never becomes a billboard. (default above)        */

/* Desktop 1440–1919 — default. Owner profile 1536×864 lands here: panel 1480,
   main column ≈992, grid content ≈956 → exactly 4 columns at 224px + 14 gap.   */

/* Laptop 1280–1439 */
@media (max-width:1439px){ .acp{--acp-rail:216px;--acp-aside:248px;--acp-insp:372px} }

/* Tablet landscape 1024–1279 — the filters aside folds; its facets move into the
   section-header controls. They are RELOCATED, never deleted: Schools,
   Complexity and the availability facet stay reachable (SPEC §3.6 records that
   the current build simply loses them below 1120). */
@media (max-width:1279px){
  .acp{--acp-rail:200px;--acp-insp:360px}
  .acp-aside{display:none}
  .acp-sh-c .acp-mini{display:inline-flex}
}
.acp-mini{display:none}

/* Tablet portrait 768–1023 — the F2 clip band. The header already wraps (§2);
   the rail becomes a horizontal strip so the grid keeps its full measure. */
@media (max-width:1023px){
  .acp-scrim{padding:var(--sp-5,12px)}
  .acp-panel{--acp-w:100%;--acp-h:100%}
  .acp-body{flex-direction:column}
  .acp-rail{flex:0 0 auto;border-inline-end:0;border-block-end:1px solid var(--line)}
  .acp-rail-l{display:flex;gap:var(--sp-2,6px);overflow-x:auto;overflow-y:hidden;
    padding:var(--sp-3,8px)}
  .acp-gt{display:none}
  .acp-cat{inline-size:auto;flex:0 0 auto;white-space:nowrap}
  .acp-cat[aria-selected="true"]::before{inset-block:auto 0;inset-inline:4px;
    inline-size:auto;block-size:2.5px}
  /* absolutely positioned here, so `flex:0 0 var(--acp-insp)` no longer sizes it. The token is stated
     explicitly rather than left to shrink-to-fit: an inline-size container (§8.1) contributes 0 to its own
     intrinsic width, and a content-derived width collapsed the box to 0.8px across this whole band. */
  .acp-insp{position:absolute;inset-block:0;inset-inline-end:0;z-index:4;
    inline-size:var(--acp-insp);max-inline-size:100%;
    box-shadow:var(--el-3)}
}

/* Phone landscape <768 and short — full viewport, compressed chrome */
@media (max-width:767px) and (max-height:479px){
  .acp-scrim{padding:0}
  .acp-panel{border:0;border-radius:0}
  .acp-hd{padding-block:var(--sp-2,6px)}
  .acp-grid-in{grid-template-columns:1fr}
}

/* Phone portrait <480 — full viewport with DYNAMIC viewport units.
   `100vh` is wrong on mobile: browser chrome makes it exceed the visible
   viewport, which puts the bottom of the grid — where the add control lives —
   underneath the URL bar. chart-terminal.css already uses 100dvh for exactly
   this reason (SPEC §4.4 F3). */
@media (max-width:479px){
  .acp-scrim{padding:0}
  .acp-panel{
    inline-size:100dvw; block-size:100dvh;
    max-inline-size:100dvw; max-block-size:100dvh;
    border:0; border-radius:0;
  }
  .acp-grid{padding-inline:var(--sp-5,12px)}
  .acp-grid-in{grid-template-columns:1fr}
  .acp-sh,.acp-chips,.acp-hd{padding-inline:var(--sp-5,12px)}
  /* the inspector becomes a bottom sheet — it must never cover the whole grid */
  .acp-insp{
    position:fixed; inset:auto 0 0 0; z-index:var(--z-overlay,1000);
    inline-size:100%; block-size:var(--acp-snap,56dvh); max-block-size:92dvh;
    border-inline-start:0; border-block-start:1px solid var(--line);
    border-start-start-radius:var(--rad-xl,18px); border-start-end-radius:var(--rad-xl,18px);
    box-shadow:var(--el-4);
  }
  .acp-insp-h{padding-block-start:var(--sp-5,12px)}
  .acp-insp-h::before{     /* drag handle */
    content:""; position:absolute; inset-inline:0; inset-block-start:6px;
    margin-inline:auto; inline-size:38px; block-size:4px;
    border-radius:4px; background:var(--muted); opacity:.5;
  }
  /* the AGI ask box is RELOCATED into the rail strip, never display:none —
     the current build deletes it outright on phones (SPEC §3.6) */
  .acp-agi{order:99;flex:1 1 100%}
}


/* ═══ §12 · INPUT (D6 · D7) ═══════════════════════════════════════════════════ */
@media (pointer:coarse),(max-width:479px){
  .acp{--acp-tap:44px;--acp-row:48px}
  /* NO hover-only affordance: every revealed control is permanently visible */
  .acp-r[data-ov="1"] .acp-rev{display:inline-flex}
  .acp-rev{min-inline-size:var(--acp-tap);min-block-size:var(--acp-tap)}
  /* a sticky :hover on touch is noise, not feedback */
  .acp-card:hover{border-color:var(--line);box-shadow:none}
  .acp-cb:hover,.acp-tg:hover,.acp-fopt:hover,.acp-chip:hover,.acp-act:hover{background:inherit}
  /* every control class reaches the 44px law — not a chosen two of nine */
  .acp-cb,.acp-add,.acp-ib,.acp-tg,.acp-chip,.acp-ftag,.acp-fopt,.acp-act,
  .acp-seg button,.acp-scope button,.acp-cat,.acs-rx,.acs-mixa{
    min-inline-size:var(--acp-tap); min-block-size:var(--acp-tap);
  }
  /* MEASURED (ac-settings-gate S5, 390×844 · DPR 2 · coarse): the search field was the ONE control in the
     box still under the floor — 362×38, because §2 gives it a literal `min-height:38px` that the token
     cannot reach. It is the same defect class F1 closed on the card, one control further in. */
  .acp-srch input{min-block-size:var(--acp-tap)}
  .acp-seg{gap:3px}
  .acp-r>label{flex:1 1 100%}
  .acp-ctl{flex:1 1 100%;max-width:100%;justify-content:flex-end}
  .acp-rng input[type=range]{inline-size:100%;block-size:var(--acp-tap)}
  .acp-tags{gap:var(--sp-2,6px)}
  .acp *{-webkit-tap-highlight-color:transparent}
}
/* a fine pointer keeps the compact box — but NEVER below the phone breakpoint,
   where the touch sizing above must win regardless of the reported pointer type */
@media (pointer:fine) and (min-width:480px){ .acp{--acp-tap:28px} }


/* ═══ §13 · MOTION · TRANSPARENCY · FORCED COLORS ════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  .acp,.acp *{transition:none!important;animation:none!important;scroll-behavior:auto!important}
}
/* Not concealment (LAW 13): removing a backdrop filter reveals MORE, not less,
   and hides no defect. It is honoured for users who ask for it and for devices
   that cannot composite it inside a frame budget. */
@media (prefers-reduced-transparency:reduce),(update:slow){
  .acp{--acp-blur:0px;--acp-glass:var(--card);--acp-scrim:var(--bg)}
  .acp-scrim{-webkit-backdrop-filter:none;backdrop-filter:none}
}
@media (forced-colors:active){
  .acp-panel,.acp-insp{background:Canvas;border-color:CanvasText}
  .acp-scrim{-webkit-backdrop-filter:none;backdrop-filter:none}
  .acp-cat[aria-selected="true"],.acp-chip[aria-pressed="true"],
  .acp-tg[aria-pressed="true"],.acp-fopt[aria-pressed="true"],
  .acp-ftag[aria-pressed="true"],.acp-seg button[aria-pressed="true"],
  .acp-scope button[aria-pressed="true"],.acp-add[aria-pressed="true"],
  .acp-tgl[aria-pressed="true"],
  .acs-mixa,.acs-rx[aria-expanded="true"]{background:Highlight;color:HighlightText;forced-color-adjust:none}
  /* the reach list must keep a drawn edge: in a forced palette its inset background collapses into the
     surface, and a list of seven names with no boundary reads as part of the row above it */
  .acs-rxl{border:1px solid CanvasText}
  /* the honesty tier must survive a forced palette: colour alone can never be
     the carrier of a provenance claim, so the dot keeps a drawn border */
  .acp-q{border-color:CanvasText;forced-color-adjust:none}
  .acp-q::before{box-shadow:inset 0 0 0 1px CanvasText}
  .acp-r>label::before,.acp-banner-d{forced-color-adjust:none}
  .acp-card[aria-pressed="true"]{outline:2px solid Highlight;outline-offset:-2px}
}
