/* ============================================================================
   commands.css - page layer for the Command Reference.

   Loads AFTER ook.css (tokens, reset, nav, footer, cards, chips, badges, .q,
   .more, focus and preference blocks) and after optimization/style.css (the
   tool-page vocabulary). Everything here belongs to this one page: the two-pane
   shell, the rail, the row's column tracks, and the myth list.

   The page exists to be scanned. 357 rows only scan if a row is a LINE - a
   name, one clause of what it does, and three tags that start and end on the
   same x all the way down the column. Before this file the summary was a flex
   bag with two competing flex:1 children, which gave a median collapsed row of
   93px at 1440 with ~400px of dead gutter beside it, and an eight-line wrap at
   390. Everything in section 6 is that fix.

   Nothing here redeclares a component ook.css already names.
   ========================================================================== */


/* ============================================================================
   1. PAGE FRAME
   The rail is sticky below 75em, so an anchor has to clear the nav AND the bar.
   app.js writes --stick-h from the measured bar (0 in the two-pane layout,
   where the rail is a column and nothing overlays the list).
   ========================================================================== */

html { scroll-padding-top: calc(var(--nav-h) + var(--stick-h, 0px) + var(--s4)); }

/* The second skip link steps aside so both stay legible when tabbed through. */
.skip-2:focus { left: calc(var(--s3) + 10.5rem); }


/* ============================================================================
   2. HERO PANEL AND THE EVIDENCE LEGEND
   The card is two stats and the build line now. The rest left the fold: the
   "read from a client" count is a counted sentence inside #how-sourced, the
   evidence split IS the legend's per-label counts, and the legend itself is
   #ev-legend-disc. The rules those elements needed went with them; the family
   count needs no figure because the rail lists the families.
   ========================================================================== */

/* Hero rhythm - the SAME two lines on all six sub-site surface pages (guide,
   config, audit, commands, binds, changes): a tighter band than the shared one,
   because every hero here is now a heading, one line and one action, and the
   tool or list under it is the point. Set page-locally rather than in
   ook.css because the gallery pages consume the shared band too. */
.hero { padding-block: clamp(32px, 3.5vw, 48px) var(--s5); }
main > .hero + section { margin-top: var(--s6); }
/* The caveat and its two disclosures sit against the reference they qualify
   instead of reading as a chapter of their own; every other section keeps the
   shared step. */
main > section[aria-labelledby="verify-head"] + section { margin-top: var(--s6); }

/* Reset takes every margin to 0, so the build line needs its own step away
   from the two numbers above it. */
.rail-card .stat-row + .source { margin-top: var(--s5); }

/* The legend is a definition list here, not the config tuner's value row, so it
   drops that component's left indent and sets as two columns of pairs. */
.ev-legend {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s3) var(--s5);
  margin: 0;
}

@media (min-width: 40em) {
  .ev-legend { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.ev-legend .val { display: grid; gap: 2px; align-content: start; }
.ev-legend dt { display: flex; align-items: center; gap: var(--s2); }
.ev-legend dd { margin: 0; color: var(--fg-2); font-size: var(--fs-sm); line-height: var(--lh-snug); }

/* How many entries wear the label, counted at load. A legend that leads with a
   tier covering two rows of 357 oversells the page; the number says so. */
.ev-n { color: var(--fg-3); font-size: var(--fs-xs); }


/* ============================================================================
   3. THE TWO-PANE SHELL
   >=75em: a sticky rail beside the reference. Below that the same form is a
   one-line sticky bar and its two sheets open as overlays.
   ========================================================================== */

.cmd-shell { margin-top: var(--s5); }
.ref-col { min-width: 0; }

@media (min-width: 75em) {
  .cmd-shell {
    display: grid;
    grid-template-columns: 17rem minmax(0, 1fr);
    gap: var(--s7);
    align-items: start;
  }
}


/* ============================================================================
   4. THE RAIL
   ========================================================================== */

.rail { display: flex; flex-direction: column; gap: var(--s4); }

/* -- Narrow: one control tall, and it stays that way ---------------------- */
@media (max-width: 74.99em) {
  .rail {
    position: sticky;
    top: var(--nav-h);
    z-index: 20;
    flex-direction: row;
    flex-wrap: nowrap;
    align-items: center;
    gap: var(--s3);
    padding-block: var(--s3);
    margin-bottom: var(--s4);
  }

  /* Full-bleed ground without vw maths: below 75em the wrap is always
     padding-limited, so one gutter each way reaches the screen edge. */
  .rail::before {
    content: "";
    position: absolute;
    inset: 0 calc(var(--gutter) * -1);
    z-index: -1;
    background: color-mix(in srgb, var(--bg-0) 88%, transparent);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid transparent;
    transition: border-color var(--dur-base) var(--ease-std),
                box-shadow var(--dur-base) var(--ease-std);
  }

  .rail.is-stuck::before {
    border-bottom-color: var(--line-1);
    box-shadow: 0 6px 20px -14px rgba(0, 0, 0, .9);
  }

  @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .rail::before { background: var(--bg-0); }
  }

  .rail-bar { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: var(--s3); }
  .rail-search { flex: 1 1 auto; min-width: 0; }
  .rail .count { flex: none; white-space: nowrap; }
  .rail-jump { display: none; }
}

/* At 390 the count would push the two sheet handles off the line; the reference
   count is restated inside the empty state and announced, so the bar keeps the
   two controls instead. */
@media (max-width: 34em) {
  .rail .count { display: none; }
}

/* -- Wide: a column that stays on screen ---------------------------------- */
@media (min-width: 75em) {
  .rail {
    position: sticky;
    top: calc(var(--nav-h) + var(--s5));
    max-height: calc(100dvh - var(--nav-h) - var(--s5) - var(--s3));
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--line-2) transparent;
    padding-right: var(--s2);
    gap: var(--s3);
  }

  .rail-bar { display: flex; flex-direction: column; align-items: stretch; gap: var(--s2); }
  .jump-sheet { display: none; }

  /* Orientation before filtering: the family index sits above the filters. */
  .rail-bar { order: 0; }
  .rail-jump { order: 1; }
  .filter-sheet { order: 2; }
}

/* -- Search field --------------------------------------------------------- */

/* The label stays in the accessibility tree and nowhere else: the placeholder
   already says what the box takes, and the entry count is on the fold twice. */
.rail-search .glabel {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Safari draws its own search furniture and ignores the box model otherwise. */
#search {
  -webkit-appearance: none;
  appearance: none;
  min-height: 40px;
  border-radius: var(--r-md);
}

#search::-webkit-search-decoration,
#search::-webkit-search-cancel-button,
#search::-webkit-search-results-button,
#search::-webkit-search-results-decoration { -webkit-appearance: none; }

#search:focus-visible { border-color: var(--accent-500); }

.rail .count { color: var(--fg-2); font-size: var(--fs-xs); }


/* ============================================================================
   5. SHEETS - filters and, on a phone, the family index
   Narrow: an overlay under the bar. Growing INSIDE a sticky element took the
   chrome to 501px of a 900px viewport with the filters open, and every deep
   link and jump landed behind it.
   ========================================================================== */

.sheet { margin-top: 0; }

.sheet > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 40px;
  color: var(--fg-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  white-space: nowrap;
}

.sheet > summary:hover { color: var(--fg-0); }
.sheet > summary .marker { color: var(--fg-3); }
.sheet[open] > summary .marker { color: var(--accent-400); }
#filter-count { color: var(--accent-300); }

@media (max-width: 74.99em) {
  .sheet { position: static; }

  .sheet-body {
    position: absolute;
    left: calc(var(--gutter) * -1);
    right: calc(var(--gutter) * -1);
    top: 100%;
    z-index: 1;
    max-width: none;
    max-height: min(62vh, 26rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    margin-top: 0;
    padding: var(--s4) var(--gutter) var(--s5);
    background: var(--bg-1);
    border-bottom: 1px solid var(--line-1);
    box-shadow: 0 18px 30px -22px rgba(0, 0, 0, .95);
    scrollbar-width: thin;
  }
}

@media (min-width: 75em) {
  .filter-sheet { border-top: 1px solid var(--line-1); padding-top: var(--s2); }
  .sheet-body { max-width: none; }
}

/* -- Filter groups -------------------------------------------------------- */
.filter-groups { display: flex; flex-direction: column; gap: var(--s3); margin-top: 0; }

.filter-group {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

.filter-group .glabel { flex: 0 0 100%; font-weight: 600; }

.filter-group .chip {
  min-height: 28px;
  padding-inline: 10px;
  font-size: var(--fs-xs);
  background: var(--bg-2);
  border-color: var(--line-2);
}

.filter-group .chip:hover { background: var(--bg-3); border-color: var(--stroke); }

/* The "?" mark is 18px so it sits inside its label's line, and the design
   system already grows the target to 26px. In a filter sheet a thumb is
   crowding, so on a coarse pointer this instance opens to 44px. */
@media (pointer: coarse) {
  .q > summary::after { inset: -13px; }
  .filter-group .chip { min-height: 36px; }
}

/* The jump chips are links, and a chip is a control shape, not running text. */
.filter-group a.chip { text-decoration: none; }
.filter-group a.chip .jn { color: var(--fg-3); }

.reset-btn { margin-left: 0; margin-top: var(--s3); }

/* In the desktop rail the open sheet is taller than the column that holds it,
   so the one control that undoes the filtering is pinned to the rail's bottom
   edge instead of scrolling out of reach behind twenty-one chips. */
@media (min-width: 75em) {
  .filter-sheet .reset-btn {
    position: sticky;
    bottom: 0;
    display: block;
    width: 100%;
    margin-top: var(--s2);
    padding-block: var(--s2);
    border-top: 1px solid var(--line-1);
    background: var(--bg-0);
    text-align: left;
  }
}


/* ============================================================================
   6. RAIL JUMP LIST - the persistent family index, wide viewports only
   ========================================================================== */

.rail-jump { display: none; }

@media (min-width: 75em) {
  .rail-jump {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: var(--s3);
    border-bottom: 1px solid var(--line-1);
  }

  .rail-jump a {
    display: flex;
    align-items: flex-start;
    gap: var(--s2);
    min-height: 30px;
    padding: 6px var(--s2);
    border-radius: var(--r-sm);
    color: var(--fg-2);
    font-size: var(--fs-xs);
    font-weight: 500;
    line-height: var(--lh-snug);
    text-decoration: none;
    transition: background-color var(--dur-base) var(--ease-std),
                color var(--dur-base) var(--ease-std);
  }

  .rail-jump a:hover { background: var(--bg-2); color: var(--fg-0); }
  .rail-jump .jl { min-width: 0; }
  .rail-jump .jn { margin-left: auto; color: var(--fg-3); font-variant-numeric: tabular-nums; }
  .rail-jump a.is-empty { opacity: .4; pointer-events: none; }

  /* Scroll position as an information channel: the family you are reading. */
  .rail-jump a.is-current { background: var(--bg-2); color: var(--fg-0); box-shadow: inset 2px 0 0 var(--accent-500); }
}


/* ============================================================================
   7. FAMILY HEADS
   ========================================================================== */

.tier-head {
  margin: var(--s7) 0 var(--s4);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--line-1);
}

#reference > .tier-head:first-child { margin-top: 0; }
.tier-head > .shead { margin-bottom: 0; }
.tier-head h2 { margin-bottom: var(--s1); }

.fam-count {
  margin-left: var(--s2);
  color: var(--fg-3);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0;
  white-space: nowrap;
}


/* ============================================================================
   8. ROWS - one ruled list per family, with real column tracks
   The frame, the fill and the radius belong to the LIST; a row owns only the
   hairline above it. That is what turns a family into something you run your
   eye down instead of 40 separate objects of unequal height.
   ========================================================================== */

.ref-list {
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--bg-2);
  box-shadow: var(--hairline);
  overflow: clip;
}

.ref-list:empty { display: none; }

.ref-list .entry,
#myth-list .entry {
  border: 0;
  border-radius: 0;
  margin: 0;
  background-color: transparent;
  background-image: none;
  box-shadow: none;
}

.ref-list .entry + .entry:not([hidden]),
#myth-list .entry + .entry:not([hidden]) { border-top: 1px solid var(--line-1); }

.ref-list .entry[open],
#myth-list .entry[open] {
  background-color: var(--bg-1);
  border-color: transparent;
  box-shadow: inset 2px 0 0 var(--accent-500);
}

.ref-list .entry[open] > summary,
#myth-list .entry[open] > summary { border-bottom: 1px solid var(--line-1); }

/* -- The collapsed row: real tracks, aligned down the whole column ---------
   The name and the tag cluster share the first line; the clause sits under the
   name on the second. Side by side, the two would each get ~250px of a column
   that is already sharing its width with the rail - which is how a "what it
   does" line ends up reading "Anisotr...". Stacked, the tags still start and
   end on the same x on all 357 rows (that alignment is the whole point) and the
   clause gets the full width of the list. It is the guide's row shape, on the
   page a reader moves to from the guide. */
.entry > summary {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr) max-content;
  grid-template-areas:
    "mark title badges"
    "mark what  what";
  align-items: center;
  gap: 2px var(--s3);
  padding: var(--s2) var(--s4);
  min-height: 48px;
  border-radius: 0;
  flex-wrap: nowrap;
}

.entry > summary > .marker { grid-area: mark; align-self: center; color: var(--fg-3); opacity: .55; }

.entry > summary:hover > .marker,
.entry > summary:focus-visible > .marker,
.entry[open] > summary > .marker { opacity: 1; color: var(--accent-400); }

.entry > summary::marker { content: ""; }
.entry > summary::-webkit-details-marker { display: none; }

.entry .etitle {
  grid-area: title;
  min-width: 0;
  margin: 0;
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: var(--lh-snug);
  overflow-wrap: anywhere;
}

.entry .etitle code {
  font-size: inherit;
  background: transparent;
  padding: 0;
  color: var(--accent-300);
}

/* One clause of what the setting does, on ONE line with an ellipsis. The full
   sentence is the first line of the open body, so nothing is lost to the clamp
   - and a row that cannot grow past its line is what makes 357 of them
   scannable. */
.entry .rec-label {
  grid-area: what;
  min-width: 0;
  flex: none;
  color: var(--fg-2);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* An OPEN row is a panel, not a line in a list, so its clause stops being a
   scan line and sets in full. That is where the truncated sentence comes back -
   restating it as the first paragraph of the body printed the same words twice,
   two lines apart, on every row wide enough not to have been clipped. */
.entry[open] > summary .rec-label {
  display: block;
  white-space: normal;
  overflow: visible;
  -webkit-line-clamp: none;
  color: var(--fg-1);
}

/* Three fixed sub-columns, so the default, the evidence dot and the impact pill
   each start and end on the same x on every row. Order matches the guide:
   provenance of the value first, then how far we trust the advice, then how
   much it matters. */
.entry .badges {
  grid-area: badges;
  display: grid;
  grid-template-columns: 4.75rem 5.5rem 5.5rem;
  align-items: center;
  gap: var(--s2);
  flex-wrap: nowrap;
}

.entry .badges > * { width: 100%; min-width: 0; }

.entry .badges .chip.is-static {
  min-height: 24px;
  padding-inline: var(--s2);
  justify-content: center;
  font-size: var(--fs-xs);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  display: block;
  line-height: 22px;
  text-align: center;
}

.entry .badges .badge { justify-content: center; padding: 2px 7px; font-size: 11px; }
.entry .badges .ev-label { justify-content: flex-start; }

.entry > summary:hover {
  background: var(--bg-3);
  background: color-mix(in srgb, var(--bg-2) 92%, var(--accent-500) 8%);
}

.entry > summary:focus-visible { outline-offset: -3px; }

/* -- Narrow: title, then the clause, then the tags -------------------------
   Three stacked rows at 390 with every metric on its floor: the flex layout it
   replaces set a twelve-word sentence over eight lines beside a badge trio
   eating 130px of a 350px card, for a median row of 215px. */
@media (max-width: 47.99em) {
  .entry > summary {
    grid-template-columns: 16px minmax(0, 1fr);
    grid-template-areas:
      "mark title"
      "mark what"
      "mark badges";
    align-items: start;
    gap: 2px var(--s2);
    padding: var(--s2) var(--s3);
  }

  .entry > summary > .marker { align-self: start; margin-top: 2px; }

  /* Two lines and an ellipsis: enough to rule a row in or out with a thumb,
     never the eight-line paragraph the flex layout produced at 390. */
  .entry .rec-label {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    white-space: normal;
  }

  .entry .badges {
    grid-template-columns: max-content max-content max-content;
    justify-content: start;
    gap: var(--s2) var(--s3);
    margin-top: 1px;
  }

  .entry .badges > * { width: auto; }

  .entry .badges .chip.is-static {
    display: inline-block;
    min-height: 20px;
    line-height: 18px;
    font-size: var(--fs-2xs);
  }
}

/* -- The open body -------------------------------------------------------- */
.entry-body { padding: var(--s3) var(--s4) var(--s5) calc(var(--s4) + 16px + var(--s3)); }
.entry-body > * { max-width: var(--measure); }
.entry-body .entry-foot { max-width: none; }
.entry-body p:first-child { margin-top: 0; }
.entry-body .rec-vals { margin-left: 0; }

/* One icon SLOT, not two icons: the link mark and the copied check occupy the
   same 14px box and cross-fade. Without this the button prints both, stacked,
   above its label - the design system only styles this for .copy-code. */
.copylink { display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); min-width: 7.5rem; }
.copylink .ci { position: relative; flex: none; width: 14px; height: 14px; }
.copylink .ci svg { position: absolute; inset: 0; transition: opacity var(--dur-base) var(--ease-std); }
.copylink .ci-check { opacity: 0; color: var(--ok); }
.copylink[data-copied="true"] { border-color: var(--ok); color: var(--ok); }
.copylink[data-copied="true"] .ci-copy { opacity: 0; }
.copylink[data-copied="true"] .ci-check { opacity: 1; }
.copylink[data-copied="fail"] { border-color: var(--warn-line); color: var(--warn-fg); }
a.copylink { text-decoration: none; }
.entry-foot { border-top: 1px solid var(--line-1); }

@media (max-width: 47.99em) {
  .entry-body { padding-left: calc(var(--s3) + 16px + var(--s2)); padding-right: var(--s3); }
}


/* ============================================================================
   9. MYTHS - the same row, two columns
   A myth has no default and no impact: the name, the claim, and one tag.
   ========================================================================== */

#myth-list {
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: var(--bg-2);
  box-shadow: var(--hairline);
  overflow: clip;
}

#myth-list .entry > summary {
  align-items: start;
  padding-block: var(--s3);
}

#myth-list .entry > summary > .marker { align-self: start; margin-top: 2px; }
#myth-list .entry .etitle { font-family: var(--font-mono); overflow-wrap: anywhere; }

/* 33 rows, not 357, and the claim is the thing being corrected - it gets two
   lines rather than one. */
#myth-list .entry .rec-label {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  white-space: normal;
}

#myth-list .entry .badges { grid-template-columns: max-content; justify-content: end; align-self: start; margin-top: 2px; }
#myth-list .entry .badges > * { width: auto; }

@media (max-width: 47.99em) {
  #myth-list .entry .badges { justify-content: start; }
}


/* ============================================================================
   10. EMPTY STATE
   ========================================================================== */

.empty {
  display: grid;
  justify-items: center;
  gap: var(--s3);
  margin-top: var(--s5);
  padding: var(--s7) var(--s5);
  border: 1px dashed var(--line-2);
  border-radius: var(--r-lg);
  color: var(--fg-2);
  text-align: center;
  /* The reader has to be able to SEE this when a query matches nothing, so it
     is tall enough to fill the space the reference left behind. */
  scroll-margin-top: calc(var(--nav-h) + var(--stick-h, 0px) + var(--s4));
}

.empty p { margin: 0; max-width: 52ch; }
.empty .empty-why { color: var(--fg-0); font-size: var(--fs-body-lg); line-height: var(--lh-snug); }
.empty .empty-more { font-size: var(--fs-sm); }
.empty .reset-btn { margin-top: 0; border: 1px solid var(--line-2); }
.empty[hidden] { display: none; }


/* ============================================================================
   11. PREFERENCE AND OUTPUT BLOCKS
   ========================================================================== */

@media (forced-colors: active) {
  .ref-list,
  #myth-list,
  .sheet-body { border: 1px solid CanvasText; }

  .ref-list .entry + .entry,
  #myth-list .entry + .entry { border-top: 1px solid CanvasText; }

  .rail-jump a.is-current { outline: 2px solid Highlight; outline-offset: -2px; }
}

/* A short viewport cannot afford a sticky bar at all. */
@media (max-height: 34rem) and (max-width: 74.99em) {
  .rail { position: static; }
}

@media print {
  .rail,
  .skip,
  .copylink,
  .copy-code .ci { display: none !important; }

  .cmd-shell { display: block; }

  .ref-list,
  #myth-list { border: 0; background: none; box-shadow: none; overflow: visible; }

  .entry {
    break-inside: avoid;
    border: 1px solid #bbb;
    margin-bottom: 8pt;
  }

  /* On paper the clamp would drop the sentence the row is about. */
  .entry .rec-label {
    white-space: normal;
    overflow: visible;
    display: block;
    -webkit-line-clamp: none;
  }
}
