/* listing.css -- P7.3, the product detail surface's own rules and NOTHING ELSE.
 *
 * WHY A FIFTH STYLESHEET. Same reason `seller.css` is the fourth: `components.css` is the P4.3
 * component sheet adopted VERBATIM and its sha256 is pinned by `base_template_check.py` rule B2.
 * A surface that needs a rule the sheet does not have adds its own file, loaded after the three
 * through base.html's `head_extra` block, and declares itself in that gate's PAGE_STYLESHEETS
 * allow-list. Every length and every colour here is a token; `lint_spacing.py` polices this file
 * exactly as it polices the other four and has no exemption for being new.
 *
 * PRODUCT-PAGE.md §LAYOUT declares exactly two additions to the component sheet, and they are
 * the first two rules below. Nothing else here is a component; the rest is page layout.
 */

/* ADDITION 1. The component sheet predates NO_DESIGNATION and has no class for it.
 *
 * 🚨 IT IS NOT MUTED, BECAUSE IT IS NOT AN ABSENCE. A laboratory examined this diamond and
 * issued no designation -- a reported outcome of an examination somebody paid for. Rendering it
 * in `--c-text-muted` beside "Not stated" would tell a buyer that a laboratory's finding is a
 * seller's oversight, which is the exact inversion this page exists to prevent. It keeps the
 * `--c-border-strong` start rule, because it shares with NOT_APPLICABLE the property of being
 * an answer rather than a value, and that rule is the signal that survives a user stylesheet
 * flattening `--c-text-muted` into `--c-text` (SC 1.4.1, SC 1.4.12).
 */
.attr-table__value--no-designation {
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--c-text);
  font-weight: var(--fw-regular);
  border-inline-start-style: solid;
  border-inline-start-width: 2px;
  border-inline-start-color: var(--c-border-strong);
  padding-inline-start: var(--sp-3);
}

/* ADDITION 2 IS DELIBERATELY NOT HERE. PRODUCT-PAGE.md §THE ATTRIBUTE TABLE specifies
 * `.attr-table__group-toggle`, a <button aria-expanded aria-controls> that collapses a group's
 * <tbody> behind `hidden`.
 *
 * 🚨 THIS BUILD HAS NO JAVASCRIPT, SO THAT BUTTON WOULD BE A CONTROL THAT LIES. P7.1 shipped no
 * script layer and P7.3 does not open one. A <button aria-expanded="false"> that nothing listens
 * to announces a collapsed region to a screen reader and then never expands it -- strictly worse
 * than no control at all, and it would pass every gate in this build. So P7.3 ships every group
 * OPEN, every row visible, and the census on every group heading regardless of state. The
 * decision is recorded as D7.3-5 with its reversal: `policy.display_groups` and the view model's
 * `open` flag are already computed and tested, so wiring the toggle is adding this rule and a
 * listener, not redesigning the table. Nothing is hidden, so nothing is hidden twice.
 *
 * The census line stays either way: "Finish -- 5 properties, none stated by the seller" is the
 * sentence that distinguishes the two ways a group can be empty, and a buyer needs it whether or
 * not the rows beneath it are visible. */
.attr-table__group-census {
  display: block;
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  font-weight: var(--fw-regular);
  color: var(--c-text-muted);
}

.attr-table__qualifier {
  display: block;
  max-width: var(--measure);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--c-text-muted);
}

/* ------------------------------------------------------------------ page layout */

.listing {
  display: flex;
  flex-direction: column;
  gap: var(--sp-7);
}

/* 🚨 `min-inline-size: 0`. A grid or flex child defaults to `min-content` in the inline axis, and
 * P7.5 lost six hours to exactly that: one unbreakable 40-character machine string made a whole
 * fieldset 770px wide at a 360px viewport while the page looked perfect at 1280. This page is
 * full of machine strings -- report numbers, rule ids, a verification URL -- so every box that
 * can hold one says 0 here. `check_viewport.js` measures it on the bytes the probe received. */
.listing__start,
.listing__end {
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
  min-inline-size: 0;
}

@media (min-width: 1280px) {
  .listing {
    display: grid;
    /* 🚨 PRODUCT-PAGE.md SPECIFIES `minmax(20rem, 1fr) minmax(24rem, 1.2fr)` AND THE P4.2 GATE
     * REFUSES IT: `20rem` and `24rem` are raw lengths, and `lint_spacing.py` R1 admits only
     * tokens. There is no token near either value and `tokens.css` cannot gain one -- its
     * sha256 is pinned to the P4.1 winner by `base_template_check.py` B2, which is the pin
     * working rather than the pin being in the way.
     *
     * The minimums are droppable without loss. They exist to stop a column collapsing below
     * its content, and this rule only applies at and above 1280px, where 1fr and 1.2fr of a
     * 1200px container minus a 48px gap are about 523px and 628px -- far above anything either
     * column needs. What actually protects these columns from a long machine string is
     * `min-inline-size: 0` on `.listing__start` / `.listing__end`, which P7.5 paid for.
     */
    grid-template-columns: 1fr 1.2fr;
    gap: var(--sp-7);
    align-items: start;
  }

  /* Stickiness is enhancement. The trust block's PRESENCE is not: it is in the same DOM
   * position at every width, so its absence would be conspicuous. */
  .listing__start {
    position: sticky;
    top: var(--sp-4);
  }
}

.listing__identity {
  max-width: var(--measure);
}

/* The media slot when there is nothing in it -- which is every seeded stone today. No decorative
 * illustration and no generic diamond: zewbie never renders a photograph of a different stone,
 * so there is no code path that puts a stock image above a price. */
.listing__media {
  aspect-ratio: 1 / 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-5);
  background-color: var(--c-surface);
  border-style: solid;
  border-width: 1px;
  border-color: var(--c-border-strong);
  border-radius: var(--radius);
  min-inline-size: 0;
}

.listing__price {
  font-size: var(--fs-2xl);
  line-height: var(--lh-2xl);
  font-weight: var(--fw-semibold);
  color: var(--c-text);
  font-variant-numeric: tabular-nums;
}

/* Arithmetic, not a valuation. The moment a derived quotient is styled with `--c-ok` it has
 * become an appraisal, and zewbie does not appraise stones -- so this is muted body text and
 * carries its own label saying what it is. */
.listing__per-unit,
.listing__per-unit-note {
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--c-text-muted);
  max-width: var(--measure);
  font-variant-numeric: tabular-nums;
}

.listing__sentence {
  max-width: var(--measure);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
}

.listing__census {
  max-width: var(--measure);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--c-text-muted);
  font-variant-numeric: tabular-nums;
}

.listing__owner-bar {
  border-style: solid;
  border-width: 1px;
  border-color: var(--c-border-strong);
  border-radius: var(--radius);
  padding: var(--sp-3);
  max-width: var(--measure);
}

/* An unavailable action keeps its tab stop and says why: `aria-disabled` plus a wired
 * `aria-describedby`, never the `disabled` attribute, which removes it from the tab order and
 * takes the explanation with it. */
.btn[aria-disabled="true"] {
  cursor: not-allowed;
}

.listing__unavailable {
  max-width: var(--measure);
  font-size: var(--fs-sm);
  line-height: var(--lh-sm);
  color: var(--c-text-muted);
}

/* A machine string -- a report number, a rule id, a URL -- must be allowed to break, or it sets
 * the minimum width of whatever contains it. See the note on `.listing__start` above. */
.listing__machine {
  overflow-wrap: break-word;
  font-variant-numeric: tabular-nums;
}
