/* PromptShare surfaces that sit above the library: editor, fill-in sheet, share dialog, command palette, shortcuts. Tokens only. */

.ps-scrim--2 { z-index: var(--z-popover); }
.ps-dialog--top { z-index: var(--z-toast); }
.ps-anchor-block { position: relative; }
.ps-menu--combo { left: var(--sp-0); right: var(--sp-0); top: calc(100% + var(--sp-1)); min-width: 0; }
.ps-menu--up { right: var(--sp-0); bottom: calc(100% + var(--sp-1)); transform-origin: bottom; }
.ps-dot { width: var(--sp-2); height: var(--sp-2); border-radius: var(--r-pill); background: var(--warning); display: inline-block; }
.ps-dialog-status .ps-i { width: var(--sp-3); height: var(--sp-3); color: var(--success); }

/* ───────── Editor ───────── */
.ps-ed .ps-dialog-head { border-bottom: var(--sp-px) solid var(--border); min-height: var(--sp-14); padding-block: var(--sp-3); }
/* MA2-4: the Check result needed 928px in a 596px column. The dialog now takes the height it needs (capped to the
   viewport) and the fixes are disclosures, so the result fits instead of hiding a third of itself behind a fade. */
.ps-ed { height: min(calc(var(--sp-24) * 9), calc(100dvh - var(--sp-24))); }
.ps-ed-grid { flex: 1; min-height: 0; display: grid; grid-template-columns: minmax(0, 1fr) calc(var(--sp-24) * 3.5); }
.ps-ed-main { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-5) var(--sp-6); min-width: 0; min-height: 0; }
.ps-ed-side { border-left: var(--sp-px) solid var(--border); background: var(--bg); min-height: 0;
  /* the fade remains as a scroll signal for the Details panel, which can legitimately be long */
  /* BL6-2: no text on this site is masked — a fade over glyphs is invisible to every contrast sweep. */ }
.ps-ed-title { width: 100%; height: var(--sp-8); padding: var(--sp-0); border: 0; background: none; outline: none; color: var(--text);
  font-family: var(--font-display); font-size: var(--fs-title); line-height: var(--lh-title); font-weight: var(--fw-medium); letter-spacing: var(--ls-tight); }
.ps-ed-title::placeholder { color: var(--text-3); opacity: 1; }
.ps-ed-title:focus-visible { outline: none; box-shadow: 0 var(--sp-px) 0 var(--accent); }

.ps-editor { flex: 1; min-height: calc(var(--sp-24) * 2); border-radius: var(--r-lg); border: var(--sp-px) solid var(--border-control); background: var(--bg); overflow: auto; position: relative;
  transition: border-color var(--t-fast) var(--ease-out), box-shadow var(--t-fast) var(--ease-out); scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
.ps-editor.is-focus, .ps-editor:focus-within { border-color: var(--accent); box-shadow: 0 0 0 var(--sp-px) var(--accent); }
.ps-editor.is-invalid { border-color: var(--danger); box-shadow: 0 0 0 var(--sp-px) var(--danger); }
.ps-editor.is-busy { opacity: .6; }
.ps-editor--read { background: var(--surface-1); border-color: var(--border); }
.ps-editor-text { padding: var(--sp-4) var(--sp-5); min-height: 100%; outline: none; max-width: none; }
.ps-editor-ph { color: var(--text-3); }

/* ── D11 close-out · the MIRRORED editor (textarea + highlight layer) ───────────────────────────────────────
 * This mock's editor is a single contenteditable, so nothing here ever had to position a mirror over an input.
 * The product needs one, because live `{{var}}` colouring while typing is worth keeping — see the note at the
 * end on why the contenteditable is the WRONG thing to copy into production.
 *
 * The layer order is: mirror BEHIND, textarea on top with transparent glyphs and a visible caret. The other way
 * round (mirror in front, `pointer-events: none`) also stops the double-print, but it hides the textarea's own
 * selection highlight behind the mirror, and selecting text you cannot see is worse than the bug being fixed.
 * z-index is explicit so this does not depend on which of the two comes first in the markup.
 *
 * A mirror only works while the two boxes agree to the pixel, so the typography is pinned here rather than left
 * to inheritance. Three of these are not obvious and each one drifts the glyphs on its own:
 *   · `font-variant-ligatures: none` — a ligature changes the advance width, so `ff` in the mirror and `ff` in
 *     the textarea end at different x positions and every chip after it is wrong.
 *   · `tab-size: 2` — a textarea defaults to 8. One tab and the whole line is out.
 *   · `hanging-punctuation` is UNSET here on purpose. `.ps-prompt` asks for it and a <textarea> cannot do it,
 *     so leaving it on would shift the mirror's first glyph relative to the text being typed.
 *
 * The heights are deliberately auto, NOT `inset: 0`. `.ps-editor` is the scroll container; an `inset: 0` mirror
 * is only ever as tall as the scrollport, so a prompt longer than the box would paint its first screenful of
 * chips and nothing after it. Both boxes are content-height and scroll together inside `.ps-editor`.
 *
 * WHAT CSS CANNOT DO HERE, so it needs to be said plainly: a <textarea> does not grow to its content. Keeping
 * the two in step as the prompt gets longer is a JS job — either set the textarea's height to its scrollHeight
 * on input, or sync `scrollTop` between the two. Without one of those they drift apart vertically as soon as
 * the prompt passes the height of the box, and no rule in this file can prevent it. */
.ps-editor > .ps-editor-text {
  position: absolute; top: var(--sp-0); left: var(--sp-0); right: var(--sp-0); z-index: 0;
  pointer-events: none; user-select: none; hanging-punctuation: none;
}
.ps-editor > textarea {
  position: relative; z-index: 1; display: block; width: 100%; min-height: 100%;
  margin: var(--sp-0); padding: var(--sp-4) var(--sp-5);   /* must equal .ps-editor-text's padding */
  border: var(--sp-0); outline: none; resize: none; overflow: hidden; background: transparent;
  color: transparent; caret-color: var(--text);
  font-family: var(--font-prompt); font-size: var(--fs-read); line-height: var(--lh-read); font-weight: var(--fw-read);
  white-space: pre-wrap; overflow-wrap: anywhere; tab-size: 2; font-variant-ligatures: none;
}
.ps-editor > textarea::placeholder { color: var(--text-3); }
.ps-editor > textarea::selection { background: var(--mark); color: transparent; }
.ps-caret { display: inline-block; width: var(--sp-half); height: 1.15em; margin: var(--sp-0) calc(var(--sp-px) * -1); vertical-align: text-bottom; background: var(--accent); animation: ps-blink 1.1s steps(1) infinite; }
@keyframes ps-blink { 50% { opacity: 0; } }
.ps-editor-count { max-width: var(--measure); display: flex; gap: var(--sp-4); color: var(--text-3); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.ps-editor-count .ps-end { margin-left: auto; }
.ps-editor-count ins, .ps-editor-count del { padding: var(--sp-0) var(--sp-1); }
.ps-editor-meta { display: flex; align-items: flex-start; gap: var(--sp-3); min-height: var(--ctl-sm); }
.ps-editor-meta > .ps-h { height: var(--sp-5); align-items: center; }
.ps-editor-meta > .ps-btn { margin-top: calc(var(--sp-half) * -1); }
/* MA3-7: the one unbounded list in the build reached 644px (76% of a phone) at 40 variables. Two rows, then it
   scrolls, with the count in the label — the same treatment as the rail's collections and the palette's list. */
.ps-editor-blanks { display: flex; flex-wrap: wrap; gap: var(--sp-1); flex: 1; min-width: 0;
  max-height: calc(var(--sp-5) * 2 + var(--sp-1)); overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent;
  /* BL6-2: mask removed — see app.css `.ps-nav--bounded`. */ }
.ps-ed-tip { max-width: var(--measure-panel); }   /* MA5-8: was 64ch — help text is never the reading column */

/* ROUND 7: the first-line fallback, shown as a status line under an empty title rather than asserted in a tip. */
.ps-ed-fallback { display: flex; gap: var(--sp-2); align-items: flex-start; margin-top: var(--sp-2);
  max-width: var(--measure); color: var(--text-2); font-size: var(--fs-label); line-height: var(--lh-label); }
.ps-ed-fallback .ps-i { flex: none; color: var(--text-3); margin-top: var(--sp-half); }
.ps-ed-fallback strong { color: var(--text); font-weight: var(--fw-medium); }
.ps-ed-tabs { padding: var(--sp-0) var(--sp-5); position: sticky; top: var(--sp-0); background: var(--bg); z-index: 1; }
.ps-ed-tabs .ps-tab { height: var(--sp-12); }
/* The Check pane takes focus when it opens (so the answer is announced and ↓ scrolls it), but programmatic focus
   must not paint a ring — a stray rule across the panel reads as a divider that means nothing. Keyboard focus
   still shows, because :focus-visible is what a keyboard sets. */
.ps-ed-pane { padding: var(--sp-4) var(--sp-5) var(--sp-5); display: grid; gap: var(--sp-4); align-content: start; }
.ps-ed-pane:focus { outline: none; }
.ps-ed-pane:focus-visible { outline: var(--focus-w) solid var(--focus); outline-offset: calc(var(--focus-w) * -1); }
.ps-ed-aihelp { margin-top: calc(var(--sp-2) * -1); }
.ps-ed-ai { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); }
.ps-ed-pane .ps-sugg { margin-top: calc(var(--sp-2) * -1); }
.ps-ed-pane .ps-field .ps-sugg, .ps-ed-main .ps-field .ps-sugg { margin-top: var(--sp-0); }
.ps-sugg strong { font-weight: var(--fw-medium); color: var(--accent); }
.ps-sugg-skel { margin-top: calc(var(--sp-3) * -1); padding: var(--sp-3); border-radius: var(--r-md); background: var(--surface-1); }
.ps-field .ps-sugg-skel { margin-top: var(--sp-0); }
.ps-sugg-skel { display: grid; gap: var(--sp-2); }
.ps-sugg-skel .ps-skel { width: 72%; }
.ps-sugg-skel-l { color: var(--text-3); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.ps-ed-hint { display: inline-flex; align-items: center; gap: var(--sp-1); }

/* At 768 the segmented control and the version line did not both fit this row, and because nothing here could
   shrink or wrap the control was laid out over the line's glyphs — 3 of 9 sampled points of "11 Sep, 14:02 · 61
   chars shorter" were painted by the "Changes" button. Found by check-occlusion.mjs measuring the TEXT RANGE
   rather than the element box, which is the only way this one was visible at all. The row wraps now. */
.ps-diffbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2) var(--sp-3); min-height: var(--sp-8); font-size: var(--fs-label); }
.ps-diffbar > div { flex: 1 1 auto; min-width: 0; color: var(--text-3); display: grid; font-size: var(--fs-meta); line-height: var(--lh-meta); }
.ps-diffbar strong { color: var(--text); font-family: var(--font-display); font-size: var(--fs-title); line-height: var(--lh-title); font-weight: var(--fw-medium); letter-spacing: var(--ls-tight); }
.ps-diff del + ins, .ps-diff ins + del { margin-left: var(--sp-1); }
.ps-diff-legend { display: inline-flex; gap: var(--sp-2); white-space: nowrap; }
.ps-dialog-lede, .ps-linkitem-state { text-wrap: pretty; }

.ps-verdict-band { font-family: var(--font-display); font-size: var(--fs-title); line-height: var(--lh-title); font-weight: var(--fw-medium); letter-spacing: var(--ls-tight); }
.ps-verdict-sub { color: var(--text-2); font-size: var(--fs-label); line-height: var(--lh-label); margin-top: var(--sp-half); }
.ps-verdict-note { color: var(--text-3); font-size: var(--fs-meta); line-height: var(--lh-meta); margin-top: var(--sp-1); }
.ps-ed-pane > .ps-h { margin-bottom: calc(var(--sp-2) * -1); }
.ps-fixes { display: grid; gap: var(--sp-0); counter-reset: fix; }
/* Found by check-occlusion.mjs: `display: grid` on a <details> puts the summary and the disclosed content in
   the SAME grid area in Chrome, so every open fix in the AI panel painted its suggestion on top of its own
   heading — measured at identical left/top, 295px wide, in 13 screen×state combinations. A <details> is a block;
   the gap that `grid` was here for belongs to the body. */
.ps-fix { display: block; padding: var(--sp-0); border-top: var(--sp-px) solid var(--border); font-size: var(--fs-label); line-height: var(--lh-label); }
.ps-fix > summary { display: flex; align-items: flex-start; gap: var(--sp-2); min-height: var(--ctl-lg); padding: var(--sp-2) var(--sp-0); cursor: pointer; list-style: none; color: var(--text); font-weight: var(--fw-medium); }
.ps-fix > summary::-webkit-details-marker { display: none; }
.ps-fix > summary .ps-i { color: var(--text-3); flex: none; transition: transform var(--t-med) var(--ease-out); }
.ps-fix[open] > summary .ps-i { transform: rotate(180deg); }
.ps-fix > summary .ps-fix-crit { margin-left: auto; flex: none; }
/* An author `display` on a <details>'s content overrides the UA rule that hides it when the element is CLOSED,
   so every closed fix painted its body over the NEXT fix in the list while contributing no height — the details
   measured 56px (its summary) with 136px of content drawn past it. Found by check-occlusion.mjs. The content is
   laid out only when the element is actually open; a state that wants it shown carries `open` in the markup. */
.ps-fix[open] > .ps-fix-body { display: grid; gap: var(--sp-1); padding: var(--sp-0) var(--sp-0) var(--sp-3); }
.ps-fix:not([open]) > .ps-fix-body { display: none; }
.ps-fix:first-child { border-top: 0; }
.ps-fix-crit { color: var(--text-3); font-size: var(--fs-meta); line-height: var(--lh-meta); }
.ps-fix-problem { color: var(--text); font-weight: var(--fw-medium); }
.ps-fix-sugg { color: var(--text-2); }
.ps-fix-add { margin-top: var(--sp-2); display: grid; gap: var(--sp-2); justify-items: start; }
.ps-fix-add code { display: block; width: 100%; padding: var(--sp-2) var(--sp-3); border-radius: var(--sp-0) var(--r-sm) var(--r-sm) var(--sp-0); background: var(--surface-1); font-size: var(--fs-label); line-height: var(--lh-label); border-left: var(--sp-half) solid var(--success); }
.ps-linkrow--foot { margin: var(--sp-0) calc(var(--sp-2) * -1); color: var(--accent); }
.ps-linkrow--foot > .ps-i:first-child, .ps-linkrow--foot > .ps-i:last-child { color: var(--accent); width: var(--sp-4); height: var(--sp-4); }
.ps-linkrow--foot span { flex: 1; }

.ps-vers-head { display: grid; grid-template-columns: var(--sp-8) 1fr auto; gap: var(--sp-2); padding: var(--sp-0) var(--sp-3); }
.ps-vers { display: grid; gap: var(--sp-half); margin: var(--sp-0) calc(var(--sp-2) * -1); }
.ps-ver { display: grid; grid-template-columns: var(--sp-8) minmax(0, 1fr) auto; align-items: center; gap: var(--sp-2); width: 100%; height: var(--ctl-lg); padding: var(--sp-0) var(--sp-3); border-radius: var(--r-sm); font-size: var(--fs-label); color: var(--text-2); position: relative; transition: background var(--t-fast) var(--ease-out); }
/* the middle track was `1fr`, which has an `auto` MINIMUM: a long version line refused to shrink and the
   segmented control at the end was laid out over it at 768. `minmax(0, 1fr)` lets it ellipsise. */
.ps-ver > .ps-num { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-ver:hover { background: var(--surface-1); }
.ps-ver.is-selected { background: var(--surface-2); color: var(--text); }
.ps-ver.is-selected::before { content: ""; position: absolute; left: var(--sp-0); top: var(--sp-2); bottom: var(--sp-2); width: var(--sp-half); border-radius: var(--sp-half); background: var(--accent); }
.ps-ver-n { color: var(--text-3); font-size: var(--fs-meta); }
.ps-ver-delta { color: var(--text-3); font-size: var(--fs-meta); }

/* ───────── Fill in the blanks ───────── */
.ps-fill { width: min(calc(var(--sp-24) * 9), calc(100vw - var(--sp-8))); }
.ps-fill-head { min-width: 0; }
.ps-fill-head .ps-dialog-lede { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-fill .ps-dialog-head { align-items: flex-start; padding-bottom: var(--sp-4); border-bottom: var(--sp-px) solid var(--border); }
.ps-fill-body { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); min-height: 0; flex: 1; }
.ps-fill-fields { padding: var(--sp-5) var(--sp-6); display: grid; gap: var(--sp-5); align-content: start; }
.ps-fill-fields > div { display: grid; gap: var(--sp-4); }
.ps-fill-row { display: grid; gap: var(--sp-1); justify-items: start; }
.ps-fill-row .ps-input { width: 100%; }
.ps-fill-name { font-family: var(--font-prompt); font-size: var(--fs-label); line-height: var(--lh-label); color: var(--var); }
.ps-fill-remember { display: flex; gap: var(--sp-2); align-items: flex-start; }
.ps-fill-remember .ps-i { width: var(--sp-3); height: var(--sp-3); margin-top: var(--sp-half); }
.ps-fill-preview { padding: var(--sp-5) var(--sp-6); background: var(--bg); border-left: var(--sp-px) solid var(--border); display: grid; gap: var(--sp-3); align-content: start; }
.ps-fill-preview .ps-prompt { font-size: var(--fs-body); line-height: var(--lh-read); }
.ps-fill .ps-dialog-foot { padding-left: var(--sp-3); }

/* ───────── Share ───────── */
.ps-share .ps-dialog-body { display: grid; gap: var(--sp-4); align-content: start; padding-top: var(--sp-0); }
.ps-share .ps-dialog-head { padding-bottom: var(--sp-2); }
.ps-linkfield { display: flex; gap: var(--sp-2); }
/* minor 11: the URL is a string to copy, not the dialog's headline — it is set quiet and small. */
.ps-linkfield .ps-input { flex: 1; min-width: 0; font-size: var(--fs-meta); color: var(--text-3); text-overflow: ellipsis; background: var(--bg); }
.ps-share-stats { display: flex; flex-wrap: wrap; align-items: center; color: var(--text-2); font-size: var(--fs-label); line-height: var(--lh-label); margin-top: calc(var(--sp-1) * -1); }
.ps-share-stats > span + span::before { content: "·"; margin: var(--sp-0) var(--sp-2); color: var(--text-disabled); }
.ps-share-stats .ps-i { color: var(--success); margin-right: var(--sp-2); }
.ps-share-send { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin: calc(var(--sp-1) * -1) var(--sp-0) var(--sp-0) calc(var(--sp-2) * -1); }
.ps-share-via { color: var(--text-3); font-size: var(--fs-label); }
.ps-disclose { border-top: var(--sp-px) solid var(--border); padding-top: var(--sp-2); }
.ps-disclose-btn { display: flex; align-items: center; gap: var(--sp-2); width: calc(100% + var(--sp-4)); height: var(--ctl-lg); margin: var(--sp-0) calc(var(--sp-2) * -1); padding: var(--sp-0) var(--sp-2); border-radius: var(--r-sm); font-size: var(--fs-label); font-weight: var(--fw-medium); color: var(--text); }
.ps-disclose-btn:hover { background: var(--surface-2); }
.ps-disclose-btn .ps-i { color: var(--text-3); }

/* ROUND 8 / D11 · a disclosure whose trigger is a <summary> rather than a <button>.
   `.ps-disclose-btn` was written for a <button>, so a <summary> carrying it still paints the browser's raw
   black ▶: the marker is a list marker, not a border, and nothing here reset it. The mock's own disclosures
   (`.ps-fix > summary`, `.ps-faq > summary`) each reset it locally, which meant the SHARED vocabulary could not
   be used on a <details> without inheriting the default marker. The in-app share dialog is the first surface to
   need it — the mock's share dialog has no <details> at all, which is why this gap survived six critics.
   Nothing in this mock renders these rules, so they are NOT exercised by its checks or shots. Stated plainly
   rather than implied: they are the one part of this stylesheet carried on inspection, not on evidence. */
summary.ps-disclose-btn { list-style: none; cursor: default; }
summary.ps-disclose-btn::-webkit-details-marker { display: none; }
summary.ps-disclose-btn::marker { content: ""; }
.ps-disclose[open] > summary.ps-disclose-btn { margin-bottom: var(--sp-1); }
.ps-disclose-body { display: grid; gap: var(--sp-2); padding: var(--sp-1) var(--sp-0) var(--sp-2); }
.ps-disclose-sum { margin-left: auto; color: var(--text-3); font-weight: var(--fw-regular); font-size: var(--fs-meta); }
.ps-disclose-body { display: grid; gap: var(--sp-4); padding: var(--sp-2) var(--sp-0) var(--sp-2); }
.ps-disclose-body fieldset { border: 0; padding: var(--sp-0); margin: var(--sp-0); }
.ps-choices { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.ps-choices .ps-fchip { height: var(--ctl-sm); padding: var(--sp-0) var(--sp-3); font-size: var(--fs-label); }
.ps-optgrid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-4); }
.ps-inputwrap { position: relative; display: flex; align-items: center; }
.ps-inputwrap-end { position: absolute; right: var(--sp-3); color: var(--text-3); font-size: var(--fs-label); pointer-events: none; }
.ps-share-others { border-top: var(--sp-px) solid var(--border); padding-top: var(--sp-4); display: grid; gap: var(--sp-2); }
.ps-share-others > .ps-h .ps-end { margin-left: var(--sp-2); }
.ps-linkitems { display: grid; }
.ps-linkitem { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--sp-1) var(--sp-3); align-items: center; padding: var(--sp-3) var(--sp-0); border-bottom: var(--sp-px) solid var(--border); }
.ps-linkitem:last-child { border-bottom: 0; }
.ps-linkitem-label { font-size: var(--fs-label); font-weight: var(--fw-medium); }
.ps-linkitem-state { font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--text-3); margin-top: var(--sp-half); }
.ps-linkitem-actions { display: flex; gap: var(--sp-half); margin-right: calc(var(--sp-2) * -1); }
.ps-linkitem-note { grid-column: 1 / -1; display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-1); padding: var(--sp-2) var(--sp-2) var(--sp-2) var(--sp-3); border-radius: var(--r-md); background: var(--surface-2); font-size: var(--fs-meta); line-height: var(--lh-meta); color: var(--text-2); }
.ps-linkitem-note .ps-i { color: var(--warning); }
.ps-linkitem-note span { flex: 1; }
.ps-share-new { justify-self: start; margin-left: calc(var(--sp-2) * -1); }
.ps-share .ps-dialog-foot .ps-help { display: inline-flex; align-items: center; gap: var(--sp-2); }

/* ───────── Command palette ───────── */
.ps-palette { position: fixed; z-index: var(--z-dialog); left: 50%; top: calc(var(--nav-h) + var(--sp-10)); transform: translateX(-50%); width: min(var(--palette-w), calc(100vw - var(--sp-8))); height: fit-content; max-height: min(calc(var(--sp-24) * 7), calc(100dvh - var(--nav-h) - var(--sp-16)));
  display: flex; flex-direction: column; overflow: hidden; border-radius: var(--r-lg); border: var(--sp-px) solid var(--border-strong); background: var(--surface-1); box-shadow: var(--e-3); animation: ps-rise var(--t-med) var(--ease-out); }
.ps-pal-input { display: flex; align-items: center; gap: var(--sp-3); height: var(--sp-14); padding: var(--sp-0) var(--sp-4) var(--sp-0) var(--sp-5); border-bottom: var(--sp-px) solid var(--border); flex: none; color: var(--text-3); }
.ps-pal-input input { flex: 1; min-width: 0; height: 100%; border: 0; background: none; outline: none; color: var(--text); font-size: var(--fs-input); }
.ps-pal-input input::placeholder { color: var(--text-3); }
/* the list scrolls: a 24px fade says so, so a group cut at the edge reads as 'more below', not as a bug */
.ps-pal-list { flex: 1; min-height: 0; padding: var(--sp-1) var(--sp-2) var(--sp-2); }
.ps-pal-list .ps-menu-label { padding: var(--sp-3) var(--sp-3) var(--sp-1); }
.ps-pal-item { display: flex; align-items: center; gap: var(--sp-3); height: var(--ctl-lg); padding: var(--sp-0) var(--sp-3); border-radius: var(--r-sm); font-size: var(--fs-body); color: var(--text); cursor: default; }
.ps-pal-item > .ps-i { color: var(--text-3); }
.ps-pal-item > .ps-i[class*="fill"] { color: var(--warning); }
.ps-pal-item.is-active { background: var(--surface-3); }
.ps-pal-item.is-active > .ps-i { color: var(--text); }
.ps-pal-label { flex: none; max-width: 55%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: var(--fw-medium); }
.ps-pal-sub { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-3); font-size: var(--fs-label); }
.ps-pal-sub .ps-var { color: var(--var); }
.ps-pal-end { margin-left: auto; display: inline-flex; align-items: center; gap: var(--sp-2); color: var(--text-3); font-size: var(--fs-meta); flex: none; }
.ps-pal-hint { color: var(--text-2); }
.ps-pal-none { padding: var(--sp-6) var(--sp-3) var(--sp-2); color: var(--text-2); font-size: var(--fs-body); }
/* The hint row listed five shortcuts in a nowrap row and silently amputated the last 17px of the fifth at every
   width — `overflow: hidden` hid the evidence rather than the problem. It now drops the least-used hints as space
   width. Six hints never fitted the palette's 640px; the row now carries five and check-fit.mjs fails if any of
   them is cut. Shift+Enter (Open) was the one dropped — it is the least-used of the three open paths and it is
   still discoverable in the Tab actions menu. */
.ps-pal-foot { display: flex; align-items: center; gap: var(--sp-4); height: var(--ctl-lg); padding: var(--sp-0) var(--sp-4); border-top: var(--sp-px) solid var(--border); background: var(--bg); color: var(--text-3); font-size: var(--fs-meta); flex: none; white-space: nowrap; overflow: hidden; }

.ps-pal-foot span { display: inline-flex; align-items: center; gap: var(--sp-2); }
.ps-pal-foot .ps-end { margin-left: auto; }

/* shortcuts sheet */
.ps-keys { width: min(calc(var(--sp-24) * 9), calc(100vw - var(--sp-8))); }
.ps-keys-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-8); padding-top: var(--sp-2); }
.ps-keys-grid section { display: grid; gap: var(--sp-2); align-content: start; }
.ps-keys-h2 { margin-top: var(--sp-4); }
.ps-keys-row { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); min-height: var(--ctl-md); border-bottom: var(--sp-px) solid var(--border); font-size: var(--fs-label); }
.ps-keys-row dt { color: var(--text-2); }
.ps-keys-row dd { display: inline-flex; align-items: center; gap: var(--sp-1); flex: none; }
.ps-keys-or { color: var(--text-3); font-size: var(--fs-meta); }

/* ───────── < 1024 ───────── */
@media (max-width: 1023.98px) {
  .ps-ed-grid { grid-template-columns: minmax(0, 1fr) calc(var(--sp-24) * 3); }
  .ps-keys-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ───────── < 768: sheets ───────── */
/* MA2-6: the rig declares hasTouch below 1024, so the 44px floor applies there too — not only on phones. */
@media (max-width: 1023.98px) {
  .ps-ed .ps-dialog-head .ps-iconbtn, .ps-ed .ps-dialog-foot .ps-btn, .ps-fill .ps-dialog-foot .ps-btn,
  .ps-share .ps-dialog-foot .ps-btn, .ps-dialog-head .ps-iconbtn { min-height: var(--target); min-width: var(--target); }
  .ps-ed-main .ps-btn, .ps-ed-pane .ps-btn, .ps-fix .ps-btn, .ps-linkrow--foot, .ps-ver, .ps-seg-btn,
  .ps-diffbar .ps-btn, .ps-editor-meta .ps-btn { min-height: var(--target); }
  .ps-ed-pane .ps-sugg .ps-btn--sm { min-height: var(--ctl-lg); min-width: var(--ctl-lg); }
}

@media (max-width: 767.98px) {
  .ps-ed-grid { display: block; overflow-y: auto; }
  .ps-ed-main { padding: var(--sp-4) var(--gutter); }
  .ps-editor { min-height: calc(var(--sp-24) * 2.5); flex: none; }
  .ps-ed-side { border-left: 0; border-top: var(--sp-px) solid var(--border); }
  /* ROUND 7: the first-line fallback, shown as a status line under an empty title rather than asserted in a tip. */
.ps-ed-fallback { display: flex; gap: var(--sp-2); align-items: flex-start; margin-top: var(--sp-2);
  max-width: var(--measure); color: var(--text-2); font-size: var(--fs-label); line-height: var(--lh-label); }
.ps-ed-fallback .ps-i { flex: none; color: var(--text-3); margin-top: var(--sp-half); }
.ps-ed-fallback strong { color: var(--text); font-weight: var(--fw-medium); }
.ps-ed-tabs { padding: var(--sp-0) var(--gutter); position: static; }
  .ps-ed-pane { padding: var(--sp-5) var(--gutter) var(--sp-8); }
  .ps-ed-hint { display: none; }
  .ps-ed .ps-dialog-foot .ps-end { width: 100%; }
  .ps-ed .ps-dialog-foot .ps-btn { flex: 1; }
  .ps-editor-meta { flex-wrap: wrap; }
  .ps-diffbar { flex-wrap: wrap; }
  .ps-diffbar > div { flex-basis: 100%; }

  .ps-fill-body { display: block; overflow-y: auto; }
  .ps-fill-fields { padding: var(--sp-4) var(--gutter); }
  .ps-fill-preview { border-left: 0; border-top: var(--sp-px) solid var(--border); padding: var(--sp-5) var(--gutter) var(--sp-8); }
  .ps-fill .ps-dialog-foot { flex-wrap: wrap; padding-left: var(--gutter); }
  .ps-fill .ps-dialog-foot .ps-end { width: 100%; order: -1; }
  .ps-fill .ps-dialog-foot .ps-split { flex: 1; }
  .ps-fill .ps-dialog-foot .ps-split .ps-btn:first-child { flex: 1; }
  .ps-fill .ps-dialog-foot .ps-btn--primary { flex: 1; }
  .ps-fill .ps-dialog-foot .ps-btn--primary .ps-kbds { display: none; }
  .ps-fill-skip { width: 100%; }
  .ps-seg-btn { height: var(--ctl-lg); }

  .ps-linkfield { flex-direction: column; }
  .ps-share-send { flex-direction: column; align-items: flex-start; }
  .ps-share-via { padding-left: var(--sp-2); }
  .ps-optgrid { grid-template-columns: 1fr; }
  .ps-choices .ps-fchip { height: var(--ctl-lg); }
  .ps-linkitem { grid-template-columns: 1fr; }
  .ps-linkitem-actions { margin-left: calc(var(--sp-2) * -1); }
  .ps-linkitem-note { flex-wrap: wrap; }
  .ps-share .ps-dialog-foot .ps-help { display: none; }
  .ps-share .ps-dialog-foot .ps-end, .ps-share .ps-dialog-foot .ps-btn { width: 100%; }

  /* a sheet, not a full-bleed takeover: it keeps a top edge, a visible Close and a tappable backdrop above it */
  .ps-palette { top: auto; bottom: var(--sp-0); left: var(--sp-0); transform: none; width: 100%; height: auto;
    max-height: calc(100dvh - var(--sp-16)); border-radius: var(--r-xl) var(--r-xl) var(--sp-0) var(--sp-0); border-width: var(--sp-px) var(--sp-0) var(--sp-0); }
  .ps-pal-esc { display: none; }
  .ps-pal-close { width: var(--target); height: var(--target); }
  .ps-pal-item { height: var(--sp-12); }
  .ps-pal-sub { display: none; }
  .ps-pal-label { max-width: none; flex: 1; }
  /* minor 9: keyboard hints on a device with no keyboard are 44px of noise */
  .ps-pal-foot { display: none; }
  .ps-pal-input input { font-size: var(--fs-input); }
  .ps-keys-grid { grid-template-columns: 1fr; gap: var(--sp-6); }
}

/* BL5-1 · the check's freshness line: a stored check names its date and offers a re-run; an unstored one must not
   imply permanence, so it says so and shows no date at all (API_CONTRACT 2.2.0 §Storage). */
.ps-checked { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-top: var(--sp-4);
  padding-top: var(--sp-3); border-top: var(--sp-px) solid var(--border); color: var(--text-3);
  font-size: var(--fs-meta); line-height: var(--lh-meta); }
.ps-checked-when { margin-right: auto; }
