/* Field Guide — Results page shell (Prompt 1 of 4). Reuses search.css's
   card-filter/category/date/data-provenance/region/ai-search/controls-map
   styling wholesale, unmodified (search.html and results.html both link
   it) — this file only holds what's genuinely new to this page: the
   two-column body layout, and the one override that turns the filter
   card from a floating map overlay into a normal sidebar in document
   flow. Page-scoped, not a components/ extraction — single consumer
   today, same NAMING.md call already made for search.css itself.

   This page reuses search.css wholesale for the filter card, but NOT
   its `html, body { height:100%; overflow:hidden }` rule — that
   constraint is real and correct for search.html's own full-bleed,
   viewport-pinned map shell, but search.css is a shared, unmodified
   file (linked by both pages, see the comment above) and its own
   html/body rule has no awareness of which page loaded it, so it
   silently applies here too once linked. Caught live, not assumed
   from reading the CSS alone: with Prompt 1's empty content column
   there was nothing to scroll to, so the bug had no visible symptom;
   it only became real once this pass added enough Card-datapoint
   content to actually overflow the viewport, and `window.scrollTo()`
   turned out to be a genuine no-op. Explicitly overridden below —
   results.css loads after search.css (results.html's own <link>
   order), so this same-specificity `html, body` rule wins the
   cascade and restores this page's own real behavior: an ordinary,
   normally-scrolling document like every other page in this project. */

html, body {
  height: auto;
  overflow: visible;
}

.results-shell {
  min-height: 100vh;
  background: var(--color-surface);
}

/* Sticky masthead (Phase 5 batch 1). Same proven mechanism as the two
   prior sticky-masthead fixes elsewhere in this project (search.css's
   stacked-mode-only rule, masthead.css's design-system-variant-only
   rule): position:sticky goes on #masthead-mount, the masthead's own
   bare JS-populated parent, not on .masthead itself — a sticky
   element's stuck range is bounded by its own parent's box, and
   #masthead-mount shrink-wraps to exactly the masthead's height with
   no spare room, so the child could never visibly stick regardless of
   how much this page scrolls. #masthead-mount's own parent here,
   .results-shell (min-height:100vh above, genuinely taller than the
   masthead once real content renders), has the spare room needed.
   Unlike both prior fixes, this one is page-scoped with no gating
   condition — search.html and results.html share identical
   data-masthead-variant="primary" markup, so masthead.css itself has
   no selector that can tell them apart; and unlike search.html's
   stacked-mode-only need, results.html scrolls at every width (an
   ordinary document, see the html/body override above), so this rule
   isn't wrapped in a media query. Scoped under .results-shell (not a
   blanket #masthead-mount rule) specifically because results.css is
   also linked by components.html, whose own #masthead-mount is a
   direct child of <body> inside a different shell (.sandbox-shell) —
   the ancestor-scoped selector guarantees this rule can only ever
   match this page's own masthead mount. */
.results-shell #masthead-mount {
  position: sticky;
  top: 0;
  z-index: 10;
}

/* Sidebar + content, side by side. Every inset here — the row's own
   top/left padding, the gap between columns, and the content column's
   own right padding below — is the same var(--space-6) value the
   filter card's own edge offset already used while floating over the
   map (search.css, Section 21's own "one consistent floating-UI
   margin" reasoning), so the sidebar's left edge and the content
   column's right edge both land flush with the full-width masthead's
   own wordmark/icon-group edges (identical var(--space-6) padding on
   .masthead-inner, Section 37) with no separate spacing value
   introduced anywhere on this page. Split across two rules rather than
   one uniform padding on .results-body alone specifically so the
   content column's own right inset lives with the element whose edge
   it actually describes (see .results-content below) — a single
   shared padding here would either omit that edge or double it. */
.results-body {
  display: flex;
  align-items: flex-start;
  gap: var(--space-6);
  padding: var(--space-6) 0 var(--space-6) var(--space-6);
}

/* Sidebar-in-flow, not floating-over-map: the only thing this page
   changes about the filter card at all. left/bottom/z-index are left
   declared on the base .card-filter rule (search.css) rather than
   explicitly cleared here — the ones position:sticky doesn't use are
   already inert regardless of their computed values, the identical
   "nothing needed explicitly clearing" call the stacked/mobile reflow
   layout already made for this same property (Reference doc).
   flex-shrink:0 keeps the sidebar at its own real width
   (--card-filter-width, declared once on .card-filter itself and
   inherited by .card-filter-chip — unchanged, still the single source
   of truth for both) rather than letting the flex row compress it to
   make room for the content column.

   position: sticky; top: calc(45px + var(--space-6)) (Phase 5 batch 7,
   corrected post-Phase-5) — the sidebar now genuinely stays in view as
   the results column scrolls past it, rather than scrolling away with
   the page (the queue's own original "sticky filter card" item,
   Section 89's own note that Batch 1 addressed search.html instead,
   leaving this page's own copy of the item still open). 45px is the
   sticky masthead's own real rendered height on this page's primary-
   variant masthead — measured live, the identical literal value
   search.css's own sibling fix (Section 89, item 1) already established
   for the same masthead height in a different sticky context, reused
   rather than re-derived. Not JS-measured like components.html's own
   design-system-page nav offset: confirmed directly (masthead.css) that
   nothing in the primary variant's own narrow-viewport rule touches
   anything the primary masthead actually renders (that rule only ever
   hides .masthead-tag/.masthead-divider/.theme-toggle-label, none of
   which exist on this page's masthead to begin with, all removed by
   renderMasthead() for variant:'primary') — this masthead's own height
   is genuinely constant at every width, unlike the design-system
   variant's, so a literal value carries no real drift risk here.
   .results-body's own genuine spare height (results-content, 16 real
   cards tall, is far taller than the sidebar) is what gives this
   sticky child real room to stick within — the same shrink-wrapped-
   parent failure mode Section 39/89 both diagnosed doesn't apply here,
   confirmed live, not assumed. z-index intentionally omitted: the
   sidebar sits beside, not over, the scrolling content column (a plain
   flex row, not an overlay), so nothing here can ever visually compete
   with it the way the masthead/nav stickies needed to resolve.

   The + var(--space-6) term is a correction, not part of the original
   Batch 7 value — a bare top: 45px sticks the card flush against the
   masthead's own bottom edge, but the card's real resting position
   (.results-body's own padding-top: var(--space-6), 24px) starts 24px
   BELOW that. Confirmed live before fixing: scrolling from 0 made
   cardTop track scrollY 1:1 (69 → 59 → 45) until it hit the sticky
   floor at exactly scrollY 24, then held flush at 45 — a real, visible
   24px upward jump the instant sticky engaged, not "frozen in place at
   its original offset" as intended. Adding the same --space-6 the
   resting position already uses makes the sticky floor match the
   resting position exactly (69px, matching the unstuck value pixel for
   pixel), so the card holds at its true starting offset from scrollY 0
   onward with no jump ever, confirmed live post-fix. */
.results-body .card-filter {
  position: sticky;
  top: calc(45px + var(--space-6));
  flex-shrink: 0;
}

/* Real root-cause fix (reported multiple times across Batches 1/7/10
   without actually being resolved — this is the actual discrepancy,
   confirmed by direct comparison against search.html rather than
   another guess). This rule used to read max-height, not height — a
   real, meaningful difference this comment's own prior version got
   wrong ("constrains ... the same way an explicit height would"): a
   max-height is a CAP, engaging only once content would otherwise
   exceed it. On this page, the filter card's default state (most
   sections collapsed) is naturally far shorter than any real viewport,
   so the cap never engaged at all — the panel just shrink-wrapped to
   its own real content height and sat there, completely ignoring
   however much taller the actual browser window was. Confirmed live,
   not assumed: at a genuine 1400px window height, results.html's own
   panel measured 820px (≈ its real content height, 818px scrollHeight)
   while search.html's measured 1307px (genuinely filling the
   available space) — a ~490px gap at that one height alone, and this
   page's card never grew past its content height at ANY window height
   tested, unlike search.html's, which tracked window height 1:1 at
   every size tried.

   search.html's own real mechanism (search.css) is .card-filter itself
   using position:absolute with BOTH top and bottom set and no explicit
   height — the classic CSS "stretch between two edges" trick, which
   only works for absolutely/fixed-positioned elements. This page's own
   .card-filter is position:sticky (Batch 10's own fix, needed because
   this page has genuine document scroll and no absolute-positioned,
   non-scrolling frame the way search.html's single-screen app shell
   provides) — a sticky element's own height still comes from ordinary
   block sizing (its content), not from top+bottom stretch, so it can
   never adopt search.html's exact mechanism verbatim. The real,
   correct fix instead matches search.html's END RESULT — a panel that
   is genuinely, forcibly as tall as the available space, not merely
   capped at it — the same way search.css's own now-inert height:100%
   comment already intended, just with the property that actually
   forces it: height, not max-height.

   calc(100vh - 45px - var(--space-6) - var(--space-6)), TWO
   var(--space-6) terms, not the pre-existing single one — a second
   real bug, caught live in the same verification pass, not shipped
   unchecked. The card's own sticky top is
   calc(45px + var(--space-6)) — 69px total (the rule immediately
   above) — so the space actually available below it is
   100vh - 69px - (the bottom edge gap, var(--space-6)), i.e.
   100vh - 45px - var(--space-6) - var(--space-6). The single-term
   version this rule previously carried (a leftover from when it was
   still only a max-height cap that rarely engaged, so the extra 24px
   of slack was never visible) under-subtracted by exactly one
   var(--space-6): confirmed live at a real 700px window, the
   single-term formula rendered the panel 633px tall against
   search.html's own genuinely-matching 607px at the identical
   height — a real, measured 24-26px gap that only became visible
   once this property switched from a cap to a forced height (above).
   Fixed by adding the missing second term; reconfirmed live afterward
   at 700px, 1000px, and 1400px real window heights that results.html's
   panel now matches search.html's own measured panel height exactly —
   609/609, 909/909, 1309/1309 — pixel-for-pixel at all three, not
   merely close. */
.results-body .card-filter__panel {
  height: calc(100vh - 45px - var(--space-6) - var(--space-6));
}

/* Right-hand content column — holds the Card-datapoint results feed
   (Prompt 2) and, later, the right-edge inspection modal this column's
   own right edge is already positioned to accommodate. Its own right
   padding is var(--space-6) — the filter card's own edge-offset value
   (search.css), reused directly rather than a second literal. Left
   comes from .results-body's own padding/gap above.

   No padding-top here (reverted, post-Phase-5) — Phase 5 batch 7 had
   added padding-top: var(--space-3), reasoning that it aligned this
   column's H1 with the sidebar's own visible "Search & Filter" text,
   which .card-filter__topbar's own padding-top: var(--space-3)
   (search.css) pushes down from the card's border. That match was
   never exact (line-height differences between the H1's larger type
   and the topbar's title text leave a real few-px gap either way,
   confirmed live) and it came at the cost of a real, more visible
   regression: it pushed the H1 var(--space-3) (12px) below the filter
   card's own top edge, even though both columns' boxes start perfectly
   flush (.results-body's shared padding-top, unchanged). The task that
   added this padding-top prioritized text-baseline alignment with the
   sidebar's inner title; matching the two columns' own top edges is
   the correct target — removed entirely rather than replaced with a
   smaller literal, since 0 is genuinely what "flush with the box above"
   requires, not a tuned value.

   max-width: 760px is field-guide.css's own .sandbox-shell value —
   colors.html/design-system.html's real, established central-content-
   column width, reused exactly rather than a new literal (Reference
   doc, bug fix). Prompt 1's own build here dropped that cap entirely,
   reasoning it was "tuned for a single centered column of prose, not a
   wide results grid" — that reasoning was wrong against the task's own
   original spec, which asked for this exact width specifically so
   real negative space would sit on the right (general layout balance,
   and less occlusion when the future inspection modal opens over it).
   No margin: auto here, unlike .sandbox-shell's own centered use — this
   column is a flex child sitting immediately right of the sidebar, not
   a lone centered block on an otherwise empty page, so capping its
   max-width while leaving flex's own default flex-start alignment is
   what actually produces "flush against the sidebar, negative space
   trailing on the right" rather than centering that space on both
   sides of a narrower column. flex: 1 1 auto still lets the column grow
   up to that cap and shrink below it on a narrower viewport; min-width:
   0 is unchanged from before, still needed so it can shrink past its
   content's own intrinsic width without the row overflowing. */
.results-content {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 760px;
  padding-right: var(--space-6);
}

/* Footer's second row — Clear filters + Save search sharing equal
   width, Reference doc (Prompt 3). flex: 1 1 0% on each button
   overrides .card-filter__btn's own width:100% (search.css) for real —
   width has no effect on a flex item's main-axis size once flex-basis
   isn't auto, so this isn't fighting that rule, just superseding it the
   way flex sizing always supersedes width in its own container. Row by
   default; stacks to a column below the 592px breakpoint (see that
   media query) rather than a second, independently-tuned width — "the
   same narrow layout already defined for this page," not a new one. */
.results-footer-row {
  display: flex;
  gap: var(--space-2);
}

.results-footer-row .card-filter__btn {
  flex: 1 1 0%;
}

/* .card-filter__btn--secondary (search.css) has no :disabled rule of its
   own — search.html's own "Clear filters" is deliberately enabled-but-
   inert there (its own Reference doc entry: disabling would overstate
   what's missing, since clicking it is always a valid no-op elsewhere).
   This page's own "Clear filters" used to be a real, deliberate
   deviation from that — genuinely disabled, matching "View results" —
   but that's reversed as of Phase 5 batch 6: both of this page's real
   secondary buttons ("Save search," "Clear filters") are enabled-but-
   inert now, matching each other and search.html's own convention, so
   neither uses this rule live any more. Left in place, not removed — a
   real style still needed by components.html's own Buttons showcase
   (results.css is loaded there too), which keeps a disabled-secondary
   example for its own "every real button treatment" purpose independent
   of whether any current live footer happens to use it. Formula still
   reuses .card-filter__btn--primary:disabled's own exact one (search.css)
   rather than inventing a second disabled look. */
.card-filter__btn--secondary:disabled {
  cursor: not-allowed;
  border-color: var(--color-hairline);
  background: var(--color-surface-sunken);
  color: var(--color-faint);
}

/* Stacked-mode floating jump-to-filter button (Reference doc, Prompt 3)
   — visually matches the map page's icon-stack chrome exactly
   (background/border/radius/shadow copied from .controls-map,
   search.css, not aliased to it: that class is position:absolute,
   anchored to .map-frame, which doesn't exist on this page; this needs
   position:fixed, anchored to the real viewport, so it can't reuse the
   same rule unmodified). The inner icon reuses .controls-map-icon
   (search.css) directly, unmodified — same sizing/inheritance
   mechanism as every other vendored icon in this system, no page-
   specific icon rule needed. Hidden above the breakpoint by default —
   the sidebar card is already always visible there, so a jump
   affordance would have nothing useful to do; the media query below is
   what actually reveals it, the only place this class's display
   changes. */
.results-jump-fab {
  display: none;
  position: fixed;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 10;
  box-sizing: border-box;
  width: var(--space-8);
  height: var(--space-8);
  align-items: center;
  justify-content: center;
  padding: 0;
  border: var(--border-width-hairline) solid var(--color-hairline);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  color: var(--color-ink-secondary);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
  cursor: pointer;
}

.results-jump-fab:hover {
  background: var(--color-surface-sunken);
  color: var(--color-ink);
}

.results-jump-fab:focus-visible {
  outline: var(--border-width-active) solid var(--color-ink-secondary);
  outline-offset: -2px;
}

/* "Back to map view" (Reference doc, Prompt 4) — a real, working
   navigation link, deliberately styled far quieter than the primary/
   secondary footer buttons right above it: muted body text, no border/
   background of its own (only a hairline rule above it, separating it
   from the footer as its own distinct region), centered rather than
   left-aligned like a normal inline link, since this reads as a single
   quiet utility action closing out the card rather than body copy.
   Genuinely functional — a plain <a href="search.html">, not a <button>
   with a JS listener — so it keeps working with zero script involvement
   and behaves exactly like any other link (new-tab via cmd/ctrl-click,
   right-click "open in new tab," etc.) for free. */
.card-filter__back-link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  border-top: var(--border-width-hairline) solid var(--color-hairline);
  font-family: var(--font-ui);
  font-size: var(--ui-caption-size);
  font-weight: var(--w-medium);
  color: var(--color-muted);
  text-decoration: none;
}

.card-filter__back-link:hover {
  color: var(--color-ink-secondary);
  background: var(--color-surface-sunken);
}

.card-filter__back-link:focus-visible {
  outline: var(--border-width-active) solid var(--color-ink-secondary);
  outline-offset: -2px;
}

.card-filter__back-icon {
  width: var(--space-4);
  height: var(--space-4);
  display: flex;
  flex-shrink: 0;
}

.card-filter__back-icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* Header block (Reference doc) — H1 report title, report-command row
   (Share/Print/Export), then the summary metrics row as its own last
   child, not a standalone element anymore. A flex column with one
   shared `gap` is what actually makes ".results-body's own top padding
   now applies to the top of the whole block, not re-applied per
   element" true: that padding (var(--space-6) on .results-body itself,
   unchanged, unrelated to this file) already only ever applied to
   whichever element happened to be first inside #results-content —
   wrapping the title/commands/stats together as one flex child simply
   makes that "whichever element is first" now the whole block at once,
   with no new padding/margin introduced at the block's own outer top
   edge. gap: var(--space-4) (16px) is the internal, cohesive-group
   spacing between the three pieces — deliberately less than
   var(--space-6) (24px), the value separating this whole block from
   the page edge, so the three read as one related unit rather than
   three independent page sections. */
.results-header {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* Static demo text (Reference doc) — in a real product this would be
   system-generated per the active query/filters, the same "generated,
   not authored" framing this page's own System-derived Card-datapoint
   rows already establish for computed values; no actual generation is
   wired here; results.js's own comment on this string says the same.
   .text-h1 (tokens.css) is reused completely unmodified for
   typography — the identical "genuinely portable, base-scale utility
   class" precedent .text-data-value/.text-data-label already set for
   the summary stats just below (Section 59) — this rule only adds the
   one thing that utility class doesn't set (color) plus a margin
   reset (a bare <h1> carries real browser default margins that would
   otherwise fight this block's own `gap`). */
.results-header-title {
  margin: 0;
  color: var(--color-ink);
}

/* Report-command row — Share/Print/Export, tertiary/inert (Reference
   doc). Flex row, comfortable gap between the three real buttons. */
.results-header-commands {
  display: flex;
  gap: var(--space-5);
}

/* Same tertiary, icon-preceded treatment as .card-filter__back-link
   (search.css convention reused here under a page-scoped name, not a
   fresh visual language) — muted text, no border/plate at rest, a
   sunken-surface hover tint. Padding + border-radius here (that link
   doesn't need its own, since it already sits full-width inside a
   bordered card) give the hover tint a real, visible box now that
   these three sit loose in an open row instead. Styled and focusable,
   no click handler — the same "Layers/Draw" real-but-unwired
   precedent this project already established (Section 11) and has
   reused repeatedly since (Save Search, the profile menu's own
   placeholder items, the citation modal's own pagination/zoom
   controls). */
.results-command-btn {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-1) var(--space-2);
  border: none;
  border-radius: var(--radius-card);
  background: none;
  font-family: var(--font-ui);
  font-size: var(--ui-caption-size);
  font-weight: var(--w-medium);
  color: var(--color-muted);
  cursor: pointer;
}

.results-command-btn:hover {
  color: var(--color-ink-secondary);
  background: var(--color-surface-sunken);
}

.results-command-btn:focus-visible {
  outline: var(--border-width-active) solid var(--color-ink-secondary);
  outline-offset: -2px;
}

.results-command-icon {
  width: var(--space-4);
  height: var(--space-4);
  display: flex;
  flex-shrink: 0;
}

.results-command-icon svg {
  display: block;
  width: 100%;
  height: 100%;
}

/* Summary metrics row (Reference doc, Prompt 4) — reuses the Type
   Scale reference page's real "Data Value + Label" stat convention
   exactly (design-system.html, field-guide.css's .data-card-demo/.cell,
   tokens.css's .text-data-value/.text-data-label), not an approximation
   of it. .text-data-value/.text-data-label are reused unmodified,
   directly from tokens.css — genuinely portable, base-scale utility
   classes, not reference-kit-specific. The container/cell layout rules
   themselves (.data-card-demo/.cell) live in field-guide.css instead,
   which this page deliberately doesn't link (same "pulls only from
   tokens.css, no dependency on field-guide.css" rule search.css and
   every components/*.css file already follow, since field-guide.css is
   reference-kit chrome only) — so their exact declarations are
   duplicated here under page-scoped names rather than pulling in that
   whole stylesheet for two rules, the identical precedent card-
   datapoint.css already set duplicating .tag-source/.tag-source-shape
   rather than importing sandbox.css (Section 10). */
.results-summary-stats {
  display: flex;
  gap: var(--space-7);
  padding: var(--space-6);
  border: var(--border-width-hairline) solid var(--color-hairline);
  border-radius: var(--radius-card);
  /* Was --space-5 before the Collapse all/Expand all control (below)
     existed between this row and the first card — bumped to --space-6
     so the two elements read as deliberately, comfortably separated
     rather than the control looking wedged into the original single
     gap (Reference doc, standalone task). Originally paired with that
     control's own margin-bottom for one larger combined gap down to
     the first card; that control is now right-aligned with its own
     margin-bottom tightened instead (Phase 5 batch 7), so it reads as
     governing the card feed rather than floating between two sections
     — this rule's own --space-6 stays as the real gap between the
     stats row and the control immediately below it, no longer part of
     a two-part sum. */
  margin-bottom: var(--space-6);
}

.results-summary-stat {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

/* Collapse all / Expand all (Reference doc, standalone task) — tertiary
   text-button, same visual family as .card-filter__back-link (muted
   body text, no plate/background, underline-on-hover rather than a
   color-only affordance so it reads as a real link-like control even
   for anyone not distinguishing the two muted tones). No border-top
   rule the way that link has one, unlike that control — this one isn't
   closing out a bordered card, it's a free-standing line between two
   already-bordered elements (the stats row above, the first Card-
   datapoint below), so its own hairline would be a third, redundant
   division line in a small vertical span.

   Right-aligned, margin-bottom reduced to var(--space-3) (Phase 5
   batch 7) — confirmed live first, per the task's own instruction:
   this control was left-aligned (a plain inline-block child of
   #results-content, which is ordinary block flow — nothing had ever
   pulled it to the right edge) with a full var(--space-7) gap beneath
   it, the same "deliberately separated" spacing originally meant to
   read as two distinct elements rather than one wedged into the
   other's own margin. That reasoning is reversed here: right-aligning
   the control now reads it as governing the card feed specifically
   (matching where a reader's eye actually lands after the full-width
   stats row above), so the tight var(--space-3) gap beneath it now
   correctly signals "this belongs with the cards below," not floating
   between two unrelated sections. display:block + width:fit-content +
   margin-left:auto (not text-align:right on the parent, which would
   also reach every other real child of #results-content — the H1,
   the stats row, every card) — scoped to this one control only. */
.btn-collapse-all {
  display: block;
  width: fit-content;
  margin-left: auto;
  margin-bottom: var(--space-3);
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-ui);
  font-size: var(--ui-caption-size);
  font-weight: var(--w-medium);
  color: var(--color-muted);
  cursor: pointer;
}

.btn-collapse-all:hover {
  color: var(--color-ink-secondary);
  text-decoration: underline;
}

.btn-collapse-all:focus-visible {
  outline: var(--border-width-active) solid var(--color-ink-secondary);
  outline-offset: 2px;
}

/* ===================================================================
   STACKED/MOBILE REFLOW — Reference doc (Prompt 3). Same 592px
   breakpoint search.css's own reflow already derived and uses
   (2 × (248px card floor + 24px var(--space-6) edge offset)) — reused
   verbatim, not re-derived, since this page's own sidebar is the exact
   same .card-filter, sharing the exact same --card-filter-width floor.
   Built now, deliberately, rather than deferred a third time: the
   pattern is already fully proven on search.html (Section 39), so
   there's no open design question left to defer. */
@media (max-width: 592px) {
  /* Card stacks BELOW the results content column, not above — the
     inverse of search.html's own map-then-card DOM/visual order,
     because here the results feed is the page's primary content (the
     map's role there), not the sidebar. DOM order is unchanged
     (.card-filter first, .results-content second — desktop's own
     sidebar-left reading order) — order is used explicitly here rather
     than flex-direction:column-reverse specifically so the visual
     stacking is a readable, named property instead of a side effect of
     reversing the container's own main axis. */
  /* align-items: stretch, overriding the desktop rule's own flex-start
     (Phase 5 batch 5) — a real bug found while stress-testing
     Card-datapoint at narrow widths (Reference doc), not a Card-datapoint
     defect itself. flex-start's own meaning silently flips when
     flex-direction switches to column, just below: on the desktop ROW
     layout it means "top-align the sidebar and content columns" (its
     real intent); on this STACKED COLUMN layout the same value instead
     means "don't stretch cross-axis (width) to fill the container — size
     to content instead," which nothing here ever intended. Confirmed
     live: without this override, .results-content (the only child with
     no explicit width of its own — .card-filter already forces its own
     width:100% below, so this never affected it) grew to whatever width
     its own widest child's content preferred rather than the real ~305px
     available, up to 370px in one measured case — wide enough to push
     real Card-datapoint text (e.g. "2012 statewide table (p.27)")
     visibly past the true viewport edge. stretch restores the
     column-layout-correct behavior: .results-content always fills the
     real available width, so its own children shrink/wrap within it
     instead of silently overflowing. */
  .results-body {
    flex-direction: column;
    align-items: stretch;
    padding: var(--space-6);
  }

  .results-content {
    order: 1;
    padding-right: 0;
  }

  .card-filter {
    order: 2;
  }

  /* Card stops floating — identical mechanism to search.css's own
     stacked rule (Reference doc, Section 39): position:static makes
     top/left/right/bottom inert regardless of their computed desktop
     values, so nothing needs explicitly clearing; width:100% replaces
     the desktop clamp() sizing, which is a floating-mode concern only.

     .results-body .card-filter, not a bare .card-filter (Phase 5 batch
     7) — a real specificity bug caught live, not assumed: the desktop
     sticky rule above is .results-body .card-filter (two classes,
     specificity 0,2,0), higher than this bare single-class selector's
     own 0,1,0. Both used to set the identical value (static), so the
     mismatch was invisible; the instant the desktop rule became
     position:sticky, this lower-specificity override stopped winning
     even though its own @media condition matched — confirmed live at
     a genuinely narrow real width, position stayed "sticky" instead of
     switching to "static." Matching the desktop rule's own selector
     exactly is what makes source order (this block comes later in the
     file) the actual deciding factor again, as intended. */
  .results-body .card-filter {
    position: static;
    width: 100%;
  }

  .card-filter__panel {
    height: auto;
  }

  /* This page's own footer stays a normal, in-flow sibling of
     .card-filter__scroll in every mode — unlike search.html's, it never
     becomes position:fixed here. That reanchoring exists there
     specifically to keep a LIVE action bar reachable through a long
     independently-scrolling section list; every control in this
     footer is already dead/inert by this prompt's own design (Part A),
     so there is no live action this page needs to keep pinned on
     screen through scroll — an ordinary static footer under the
     card's own content is the honest treatment for controls that don't
     do anything yet. */
  .results-footer-row {
    flex-direction: column;
  }

  /* Collapse-all suppressed — identical reasoning and identical
     specificity-matched override pair as search.css's own stacked rule
     (Reference doc, Section 39): no map to reveal by collapsing, no
     benefit to the feature once the card is already a full-width block
     rather than something floating over other content. Individual
     section chevrons (native <details>/<summary>) are a separate
     mechanism, untouched by any of this. */
  .card-filter__collapse-btn {
    display: none;
  }

  .card-filter.card-filter--collapsed .card-filter__chip {
    display: none;
  }

  .card-filter.card-filter--collapsed .card-filter__panel {
    display: flex;
  }

  /* The floating jump-to-filter button is only ever visible in this
     mode — this media query is the one place its display changes at
     all (base rule above is display:none, unconditionally). */
  .results-jump-fab {
    display: flex;
  }
}

/* ===================================================================
   PDF EXPORT — real hyperlinks on citations, screen-side pieces (PDF
   export plan, Steps 2-4). The print-only presentation itself (byline,
   parameters table, forced-open Card-datapoint disclosures) lives in
   the @media print block at the very end of this file — these rules
   are the on-screen-visible half of the same feature: the citation
   link wrapper and its doc-1 edition-mismatch footnote, both real
   regardless of media, plus hiding the two new print-only blocks
   on-screen (results.js appends them unconditionally; nothing on
   screen should ever show them). */

.results-print-byline,
.results-print-parameters,
.results-print-appended-documents {
  display: none;
}

/* display:contents — the injected <a> (results.js's own
   wireCitationLinks()) wraps a citable row's existing children
   (source tag, field, value) without adding a box of its own, so this
   citation link changes zero visual/layout behavior on screen: the
   row's own hover tint, cursor, and flex layout (card-datapoint.css)
   all still apply exactly as before, since as far as layout is
   concerned this element isn't here. It's still a completely real,
   functional <a href> in the DOM regardless of display:contents —
   what a browser prints/exports to PDF reflects the DOM itself, not
   this element's own layout participation. */
.card-datapoint-citation-link {
  display: contents;
}

/* Doc 1's own small edition-mismatch marker (wireCitationLinks(),
   results.js) — appended only on the two real citations that link to
   ODFW's current State Wildlife Action Plan page rather than a
   confirmed-identical original edition. flex-wrap only on a row that
   actually has one (:has(), not a blanket rule on every citable row)
   so this doesn't change any other row's own single-line layout;
   flex-basis:100% is the standard flex trick that drops one specific
   item onto its own new line within a now-wrapping row, rather than
   competing for space beside the field/value text on the same line. */
.card-datapoint-row-citable:has(.card-datapoint-citation-note) {
  flex-wrap: wrap;
}

.card-datapoint-citation-note {
  flex-basis: 100%;
  font-family: var(--font-ui);
  font-size: var(--ui-caption-size);
  font-style: italic;
  color: var(--color-muted);
}

/* ===================================================================
   PRINT — PDF export (PDF export plan, Steps 2-4). Read live before
   writing, per the task's own instruction: every selector below was
   confirmed against this page's own real, current structure (masthead,
   sidebar filter card, header block, all 16 Card-datapoint instances,
   footer) rather than assumed from an earlier build pass.
   =================================================================== */
@media print {
  /* Colors survive printing — browsers strip backgrounds and force
     print-safe text colors by default unless told otherwise; without
     this, every confidence-tag dot, source-tag shape fill, and summary-
     pill background would print blank/grayscale regardless of which
     theme was active on screen. Scoped to *, not just html/body: several
     of the colors that matter here (group borders, tag-source shape
     fills, confidence dots) are set via inline custom properties on
     deeply-nested elements, not a simple inherited background-color —
     a narrower scope risks missing one of them. Nothing else is needed
     for "colors render correctly regardless of which theme was active
     on-screen when printed" (the task's own explicit requirement):
     tokens.css's own color values already resolve from whichever
     data-theme happened to be set at print time exactly as they do on
     screen; this rule only stops the browser from discarding whatever
     that resolved to. */
  * {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* ---- Chrome that doesn't belong in a printed/exported document ---- */
  #masthead-mount,
  #card-filter,
  .results-header-commands,
  .results-jump-fab,
  .btn-collapse-all {
    display: none !important;
  }

  /* ---- Results content expands to the full page width — no sidebar
     left to sit beside, and no cap tuned for that two-column layout
     (.results-content's own max-width:760px, needed on screen so
     negative space sits deliberately on the right of the sidebar). ---- */
  .results-body {
    display: block;
    padding: 0;
  }

  .results-content {
    max-width: none;
    padding-right: 0;
  }

  /* ---- Every Card-datapoint's SOURCES detail forced open, regardless
     of its real on-screen open/closed state — a static export has no
     click to restore it with, so "open" is the only state that can
     ever show the real content. .card-datapoint-groups is the native
     <details>'s own real content (everything but the <summary>); the
     browser's own UA stylesheet hides that content by display when the
     <details> lacks [open], which is otherwise the most specific rule
     in play here (an attribute-absence condition effectively baked
     into the UA sheet) — !important is what actually beats it
     regardless of the real element's own [open] state at print time.
     The chevron affordance is removed outright: nothing in a static
     export can be clicked, so a rotate-on-open indicator pointing at a
     state that can no longer change is just noise. */
  .card-datapoint-groups {
    display: block !important;
  }

  .card-datapoint-disclosure-chevron {
    display: none !important;
  }

  /* Citable rows keep their real content but lose the one purely
     interactive affordance CSS can still show in a print/PDF context
     — the pointer cursor. (The hover tint needs no rule: nothing can
     hover a printed page.) */
  .card-datapoint-row-citable {
    cursor: default;
  }

  /* A card splitting across a page boundary mid-row is a real, ugly
     print-quality defect a screen reader of this same markup never
     has to worry about — kept each card whole wherever the printed
     page has room to fit it without producing an even worse gap; on
     the rare card taller than one whole page, the browser's own real
     fallback (splitting anyway rather than leaving a page blank) is
     the correct behavior, which avoid, not the stronger avoid-page,
     already permits. */
  .card-datapoint {
    break-inside: avoid;
  }

  /* ---- Print-only report byline (below the H1) and the closing
     search-parameters table (after all 16 cards) — hidden on screen
     (rule above), shown here, exactly the reverse of every other rule
     in this block. */
  .results-print-byline {
    display: block;
    margin: 0 0 var(--space-4);
  }

  .results-print-byline-line {
    margin: 0;
    font-family: var(--font-ui);
    font-size: var(--ui-caption-size);
    color: var(--color-muted);
  }

  .results-print-parameters {
    display: block;
    margin-top: var(--space-6);
    padding-top: var(--space-6);
    border-top: var(--border-width-hairline) solid var(--color-hairline);
  }

  .results-print-parameters-heading {
    margin: 0 0 var(--space-3);
    font-family: var(--font-ui);
    font-size: var(--ui-h3-size);
    font-weight: var(--w-semibold);
    color: var(--color-ink);
  }

  .results-print-parameters-table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-ui);
    font-size: var(--ui-body-sm-size);
  }

  .results-print-parameters-table th,
  .results-print-parameters-table td {
    padding: var(--space-2) var(--space-3);
    text-align: left;
    vertical-align: top;
    border: var(--border-width-hairline) solid var(--color-hairline);
  }

  .results-print-parameters-table th {
    width: 30%;
    font-weight: var(--w-semibold);
    color: var(--color-ink);
    background: var(--color-surface-sunken);
  }

  .results-print-parameters-table td {
    color: var(--color-ink);
  }

  .results-print-appended-documents {
    display: block;
    margin-top: var(--space-6);
    padding-top: var(--space-6);
    border-top: var(--border-width-hairline) solid var(--color-hairline);
  }

  .results-print-appended-documents-heading {
    margin: 0 0 var(--space-3);
    font-family: var(--font-ui);
    font-size: var(--ui-h3-size);
    font-weight: var(--w-semibold);
    color: var(--color-ink);
  }

  .results-print-appended-documents-list {
    margin: 0;
    padding-left: var(--space-5);
    font-family: var(--font-ui);
    font-size: var(--ui-body-sm-size);
    color: var(--color-ink);
  }

  .results-print-appended-documents-list li {
    padding: var(--space-1) 0;
  }

  /* Summary metrics row (5 Sources / 16 Datapoints extracted / 9
     Cross-referenced / 7 Single source) stays visible — real content,
     not UI chrome (the task's own explicit requirement). No rule
     needed here: nothing above touches .results-summary-stats, and it
     carries no display:none of its own to override — left as an
     explicit, documented no-op rather than a silent omission. */
}
