/* xp-console.css — the FULL-PAGE SEARCH CONSOLE (branch experimental/mobile-ux-v2).
   Every rule is scoped under html.xp so this sheet is completely inert while the flag is off
   (CLAUDE.md "xp" law): the public archive must render byte-identical to master until the
   owner flips the toggle. xp-console.js only ever builds this DOM after confirming
   xpEnabled(), and this scoping is the CSS half of that same guarantee.

   MOBILE FIRST, verified at 390x844. Every touch target is >= 44px, and APPLY is pinned to
   the BOTTOM of the page, in the thumb zone — which is the whole reason this is a full page
   rather than a dropdown. (Clear used to be down there beside it; owner ruling 2026-07-30
   moved it up against the input and sent the ☆ down in its place.) Palette and type
   reuse app.css's vars (--accent/--dim/--hair/--sunk/…) so this reads as the same product.
   Labels are authored lowercase; text-transform still applies on skins that want caps. */

/* ---- THE BODY LOCK. Identical to app.css's .vw-lock, for the identical reason: a
   full-screen surface needs position:fixed to stop the grid scrolling behind it (nothing
   else works on iOS), and that silently teleports the page to the top — xp-console.js pins
   the offset in body.style.top and restores it on teardown. Do not add `top:0` here; the
   inline offset IS the saved scroll position. ---- */
html.xp body.xpc-lock { overflow: hidden; position: fixed; width: 100%; }
/* the brand background is decorative and expensive; it is not painted under a full page */
html.xp body.xpc-lock .shredbg { display: none; }

/* ---- the page itself ---- */
html.xp .xpc-root {
  position: fixed;
  inset: 0;
  /* A full-screen panel. Above the masthead drawer (--z-nav); BELOW --z-modal so the
     save-name prompt and the remove confirmation land on TOP of the console; below
     --z-viewer, which must never be covered.
     (The old comment also ranked this against "the tray (60)". THE TRAY NO LONGER EXISTS —
     see xp-tray.css, which the same ruling emptied.) */
  z-index: var(--z-panel, 900);
  background: var(--panel);
  color: var(--ink);
  display: flex;
  flex-direction: column;
  font-family: var(--ui, var(--mono));
  opacity: 0;
  transition: opacity .16s ease;
  overscroll-behavior: contain;
}
html.xp .xpc-root.open { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  html.xp .xpc-root { transition: none; opacity: 1; }
}

/* ---- head: title · live count · close ---- */
html.xp .xpc-head {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 8px 8px 16px;
  padding-top: max(8px, env(safe-area-inset-top));
  border-bottom: 1px solid var(--hair);
}
html.xp .xpc-title {
  font-size: 11px;
  letter-spacing: calc(.18em * var(--track));
  text-transform: var(--caps);
  color: var(--accent);
}
/* THE LIVE COUNT is the load-bearing element of the faceted-filter pattern (NN/G): it is
   what tells you a filter over-narrowed BEFORE you commit to it. It is pinned in the fixed
   header, never in the scrolling body. Never drop it. */
html.xp .xpc-count {
  margin-left: auto;
  font-size: 12px;
  color: var(--bright);
  font-variant-numeric: tabular-nums;
  letter-spacing: calc(.06em * var(--track));
}
html.xp .xpc-count.loading { color: var(--faint); }
html.xp .xpc-close {
  flex: 0 0 auto;
  min-width: 44px; min-height: 44px;
  border: 1px solid var(--hair);
  background: var(--sunk);
  color: var(--ink);
  font-size: 20px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
}
html.xp .xpc-close:hover { border-color: var(--accent); color: var(--bright); }

/* ---- the query row ---- */
html.xp .xpc-form {
  flex: 0 0 auto;
  position: relative;              /* anchors the .ac autocomplete panel (app.css: absolute) */
  display: flex;
  /* ⚠ flex-end, NOT stretch. The box GROWS DOWNWARD now, and a stretched ⌫ beside a three-row
     box is a 150px vertical bar. Bottom-aligned, it stays pressed against the typing row —
     which is the last row of the box, and the thing the owner's 2026-07-30 ruling put it against. */
  align-items: flex-end;
  gap: 8px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hair);
}

/* ═══ THE QUERY BOX — IT WRAPS, AND IT KNOWS WHEN TO STOP ══════════════════════════════════
   ⚖ OWNER RULING 2026-08-25: *"extra search mods get cut off in the search drawer or whatever
   this screen is called. the box should add new lines below itself to fit all the criteria I
   add."* The box is the grid's `.sqbox`, adopted (web/page-index-search.js "ONE PILL BOX, TWO
   HOSTS"), so every pill here is dressed by app-search.css and there is no second palette.
   `.xpc-box` declares only what is different about a full-page phone surface:
   ⚖ IT WRAPS WHERE THE GRID'S SCROLLS, AND THAT IS NOT A CONTRADICTION OF THE 2026-08-20 RULING.
   That ruling is about the GRID's box — one line on a row it shares with the `search` button,
   where a second line pushes the whole result grid down the page. This box owns the top of a
   screen that exists to compose a query, and the thing that ruling actually forbids is OVERLAPPING
   HIT BOXES on a wrapped row: `.sqpill::after` hangs a 44px halo on a 21px pill, so two rows 4px
   apart steal each other's taps — the `shuffle` canyon. So the pills here take a REAL 44px
   instead of a halo, and the row gap is measured against the drawn box rather than against it.
   ⚖ AND IT STOPS AT ABOUT FIVE ROWS. A box that grows without limit is not a fix either: this
   row is fixed chrome above a scrolling body, so an unbounded one would push the drawer, the
   saved searches and the syntax help off the bottom of the screen — the member would be looking
   at a screenful of their own query with nothing left to narrow with. Past the cap the box
   scrolls, which is the one place scrolling is right: the criteria are reachable, `apply` and the
   live count never move, and the count on screen still describes the whole query. Six criteria —
   the owner's case — is three rows and never reaches it. */
html.xp .xpc-box {
  flex: 1 1 auto;
  min-width: 0;
  flex-wrap: wrap;
  align-content: flex-start;
  row-gap: 6px;
  padding: 5px 6px;
  min-height: 48px;
  max-height: 34vh;
  overflow-x: hidden;
  overflow-y: auto;
}
/* the field inside is borderless (app-search.css), so the FOCUS RING belongs to the box —
   otherwise tapping into a box full of pills lights nothing. */
html.xp .xpc-box:focus-within { border-color: var(--accent); }
/* ⚖ A REAL 44px, NOT A HALO — see the box's note. The label grows with the target: a 10.5px
   word inside a 44px chip reads as a mis-drawn button, and this surface has the width for 12px. */
html.xp .xpc-box .sqpill {
  min-height: var(--tap-min, 44px);
  font-size: 12px;
  padding: 0 10px 0 7px;
  gap: 4px;
}
/* 16px minimum: anything smaller makes mobile Safari zoom the page on focus. */
html.xp .xpc-input {
  flex: 1 0 110px;
  min-width: 110px;
  min-height: var(--tap-min, 44px);
  font-size: 16px;
  padding: 5px 4px;
  background: none;
  border: 0;
  color: var(--ink);
}
html.xp .xpc-input:focus { outline: none; }
/* ⌫ CLEAR — an ICON pressed against the input (owner ruling 2026-07-30; it swapped places
   with the ☆, which now lives in the foot). Same 48px block the star used to occupy, so the
   query row's geometry is unchanged. Hover goes to --bad, not --accent: this is the
   destructive one of the two, and it now empties the WHOLE query. */
html.xp .xpc-clear {
  flex: 0 0 auto;
  min-width: 48px; min-height: 48px;
  border: 1px solid var(--hair);
  background: var(--sunk);
  color: var(--dim);
  font-size: 17px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
html.xp .xpc-clear:hover { border-color: var(--bad); color: var(--bad); }
/* ⚰ `.xpc-ac` STOOD HERE (the shared tag-autocomplete panel, tags only and counted over the
   whole archive). The console adopts the grid's `.sqsugg` now — owner report 2026-08-25, *"I am
   not getting the suggestions in the search bar"*. THE PANEL IS THE SAME NODE THE GRID DRAWS, so
   app-search.css dresses it and there is no second palette; this declares only what is different
   about a full-page phone surface — it hangs inside the padded query row rather than flush to a
   box edge, and it stops before it owns the screen. ⚠ Its `[hidden]` partner rule lives with the
   base class in app-search.css; do not add a `display:` here without one. */
html.xp .xpc-sugg { left: 16px; right: 16px; top: calc(100% - 10px); max-height: 46vh; }

/* ---- scrolling body ---- */
html.xp .xpc-body {
  flex: 1 1 auto;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 0 16px 20px;
}
html.xp .xpc-sec { margin-top: 18px; }
html.xp .xpc-seclabel {
  font-size: 10px;
  letter-spacing: calc(.14em * var(--track));
  text-transform: var(--caps);
  color: var(--faint);
  font-weight: 400;
  margin-bottom: 8px;
}
html.xp .xpc-empty { color: var(--faint); font-size: 12px; padding: 6px 0 2px; }

/* ---- recent + saved lists. Full-width rows, not a cramped dropdown — the whole point of
   moving them onto a page is that there is room for a real list. ---- */
html.xp .xpc-list { border-top: 1px solid var(--hair); }
html.xp .xpc-row { display: flex; align-items: stretch; border-bottom: 1px solid var(--hair); }
html.xp .xpc-row-main {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 48px;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 4px;
  text-align: left;
  background: none; border: 0;
  color: var(--ink);
  font-family: var(--ui, var(--mono));
  font-size: 13px;
  cursor: pointer;
  overflow: hidden;
}
html.xp .xpc-row-main:hover, html.xp .xpc-row-main:focus-visible { background: var(--sunk); color: var(--bright); }
html.xp .xpc-row-main .xpc-q { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
html.xp .xpc-row-main .xpc-name { color: var(--accent); font-weight: 600; flex: 0 0 auto; }
html.xp .xpc-row.saved .xpc-row-main::before { content: "★ "; color: var(--accent); flex: 0 0 auto; }
html.xp .xpc-row:not(.saved) .xpc-row-main::before { content: "↺ "; color: var(--faint); flex: 0 0 auto; }
html.xp .xpc-x {
  flex: 0 0 auto;
  min-width: 48px; min-height: 48px;
  border: 0; border-left: 1px solid var(--hair);
  background: none; color: var(--faint);
  font-size: 16px; cursor: pointer;
}
html.xp .xpc-x:hover { color: var(--bad); background: var(--sunk); }

/* ---- THE NARROWING DRAWER, ADOPTED (owner ruling 2026-08-24) ------------------------------
   ⚰ `.xpc-fgroup` / `.xpc-flabel` / `.xpc-chiprow` / `.xpc-chip` ARE DELETED. They styled this
   file's own chip strip — a second facet vocabulary that competed with the grid's drawer and
   lost. What renders here now is `drawDrawer()`'s real body, so it wears `.sq-grp` / `.sq-opt` /
   `.sq-when` / `.sq-rung` from web/app-search.css: ONE set of rules for one control, on both
   surfaces. ⛔ Do not restyle a `.sq-*` class under `html.xp` — that is how two layouts become
   two designs, and app-search.css already carries the phone case (it is written mobile-first
   and its 44px floor block is scoped to coarse pointers, which is this surface exactly).
   ⚠ THE HOST BLEEDS THROUGH `.xpc-body`'s 16px GUTTER. `.sq-grp` draws its own 12px padding and
   a full-bleed hairline between groups; nesting that inside a second gutter reads as a card in
   a card, and the drawer's own hairlines are what say "these are separate questions". */
html.xp .xpc-drawer { margin: 0 -16px; border-top: 1px solid var(--hair); }
html.xp .xpc-drawer .sq-grp:last-child { border-bottom: 0; }

/* ---- query syntax help: ONE compact row of group names, ONE shared panel below (the same
   idiom index.html's #qhelp uses — never 8 stacked open sections). On this page the panel
   can afford the description text next to each example, which the bar never could. ---- */
html.xp .xpc-qtabs { display: flex; flex-wrap: wrap; gap: 6px; }
html.xp .xpc-qtab {
  min-height: 44px;
  padding: 0 11px;
  border: 1px solid var(--hair);
  background: none;
  color: var(--dim);
  font-family: var(--ui, var(--mono));
  font-size: 11.5px;
  cursor: pointer;
}
html.xp .xpc-qtab:hover { color: var(--ink); border-color: var(--hair-hi); }
html.xp .xpc-qtab.on { color: var(--bright); border-color: var(--accent); }
html.xp .xpc-qpanel { display: none; }
html.xp .xpc-qpanel.show { display: block; margin-top: 8px; border-top: 1px solid var(--hair); }
html.xp .xpc-qrow { display: flex; align-items: center; gap: 10px; border-bottom: 1px solid var(--hair); }
html.xp .xpc-qex {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 10px;
  border: 0;
  background: none;
  color: var(--accent);
  font-family: var(--mono);
  font-size: 12px;
  text-align: left;
  cursor: pointer;
}
html.xp .xpc-qex:hover { color: var(--bright); background: var(--sunk); }
html.xp .xpc-qdesc { color: var(--faint); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- foot: SAVE (a compact ☆ icon, bottom-left) + APPLY ACROSS THE REST. This is the
   mobile-first payoff of a full page over a dropdown — "apply" is reachable one-handed at
   the bottom of the screen instead of floating above the fold — and since 2026-07-30 apply
   is no longer sharing that row with a second word-labelled button, so the bar really does
   go across (owner ruling). Clear used to be here; it is up against the input now. ---- */
html.xp .xpc-foot {
  flex: 0 0 auto;
  display: flex;
  gap: 10px;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--hair);
  background: var(--panel);
}
/* ☆ SAVE — a compact icon, never flexing. Its width is the only thing apply does not get. */
html.xp .xpc-star {
  flex: 0 0 auto;
  min-width: 48px; min-height: 48px;
  border: 1px solid var(--hair-hi);
  background: var(--sunk);
  color: var(--dim);
  font-size: 19px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
}
html.xp .xpc-star:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
html.xp .xpc-star.on { color: var(--accent); border-color: var(--accent-deep); }
/* An EMPTY query has nothing to save (xp-console.js refreshStar). Dimmed, NOT hidden and NOT
   shrunk: it is still a visible button, so it still owes the 44px floor, and the gate counts
   it. Do not reach for display:none here. */
html.xp .xpc-star:disabled { color: var(--faint); opacity: .45; cursor: default; }
html.xp .xpc-apply {
  flex: 1 1 auto;
  min-height: 48px;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--void);
  font-family: var(--ui, var(--mono));
  font-size: 11px;
  letter-spacing: calc(.1em * var(--track));
  text-transform: var(--caps);
  font-weight: 600;
  cursor: pointer;
}
html.xp .xpc-apply:hover { background: var(--accent-deep); border-color: var(--accent-deep); }

/* On a roomy screen the console is still a page (it is the ONLY search surface now), but the
   content column is centred rather than stretched to a 2000px line length. */
@media (min-width: 900px) {
  html.xp .xpc-head, html.xp .xpc-form, html.xp .xpc-foot { padding-left: max(16px, calc(50vw - 420px)); padding-right: max(16px, calc(50vw - 420px)); }
  html.xp .xpc-body { padding-left: max(16px, calc(50vw - 420px)); padding-right: max(16px, calc(50vw - 420px)); }
  html.xp .xpc-sugg { left: max(16px, calc(50vw - 420px)); right: max(16px, calc(50vw - 420px)); }
}
