/**
 * Harvest — Quick View modal (T13).
 *
 * Styles ONLY the content Harvest injects into the native `Magento_Ui/js/modal/modal`
 * widget (the widget owns the overlay, close button, focus-trap, ESC and its own
 * z-index — we do not restyle its scrim/positioning). Everything here is scoped
 * under the `.hrv-quickview-modal` modalClass passed to the widget, plus the
 * `.hrv-quickview` content root, so it cannot bleed onto any other modal (minicart,
 * auth, etc.).
 *
 * Token-only: every value is a --hrv-* custom property, so all 5 palettes + dark
 * Midnight work with no rebuild. No hardcoded hex.
 *
 * Responsive: two-column media|info from 768px up; single column below. The widget
 * caps its own width; here we keep the body usable and scrollable at 375/768/1440
 * with no horizontal overflow.
 */

/* Widget dialog surface (the widget renders .modal-inner-wrap inside .modal-popup). */
.hrv-quickview-modal .modal-inner-wrap {
  background: var(--hrv-surface);
  border-radius: var(--hrv-radius);
  max-width: 860px;
  margin: auto;
}
.hrv-quickview-modal .modal-header {
  padding: 18px 20px 8px;
}
.hrv-quickview-modal .modal-header .modal-title {
  font-family: var(--hrv-font-display);
  font-weight: 600;
  font-size: 16px;
  color: var(--hrv-text);
  border: 0;
}
.hrv-quickview-modal .modal-content {
  padding: 8px 20px 22px;
}

/* Recolour the widget's own close (X) button to the palette. */
.hrv-quickview-modal .action-close {
  color: var(--hrv-text-muted);
}
.hrv-quickview-modal .action-close:hover,
.hrv-quickview-modal .action-close:focus-visible {
  color: var(--hrv-accent);
}

/* ---------- The TRIGGER button --------------------------------------------------------
 * `web/js/quick-view.js` injects `<button class="hrv-quickview-trigger">Quick view</button>`
 * into every `.product-item-info`.
 *
 * IT USED TO CARRY `hrv-quickview` — the modal content root's class — so the content-root
 * rule below landed on the button: a 200px control became `display:grid;
 * grid-template-columns:1fr 1fr; gap:24px`, computing to two 72px columns, and the label
 * split across two lines inside its own box.
 *
 * MEASURED, DERIVED PER ROUTE RATHER THAN TYPED — 10 triggers per category page:
 *     T5 list  1440: 10/10 wrapped   768: 10/10 wrapped   375: 0/10
 *     T4 grid  1440:  0/10           768: 10/10 wrapped   375: 0/10
 *
 * RETRACTED BY basil-T13: "search (grid AND list): 0 triggers — `quick-view-init` is attached
 * only by `Magento_Catalog/layout/catalog_category_view.xml`, so search renders none." The
 * OBSERVATION was true and the MECHANISM is no longer. That handle-scoping was the defect
 * basil-T13 fixed: the block now lives in `Magento_Theme/layout/default.xml`, and the two
 * search routes render 9/9 and 7/7 triggers at 1440, 768 and 375. This sentence is kept rather
 * than deleted so the correction can be checked against what was actually said — and it is
 * retracted HERE, in the file that carried it, rather than only in the commit that fixed it,
 * because a correction that lands in one home and not another is this sprint's most repeated
 * defect.
 *
 * That is 40 wrapped labels across two routes, one of which (T4) is a CLOSED page. The
 * line count is from text-range client rects, not `height / lineHeight` — that derivation
 * counts padding and shipped a wrong figure on T16 — and the counter returned 1 on a
 * known single-line control in 11 of the 12 cells before any of this was believed.
 *
 * FIXED BY RENAMING AT THE SOURCE, NOT BY A `:not(button)` GUARD. The first attempt used
 * one and it worked, but a guard asserts a NEGATIVE: it stops working the day the trigger
 * becomes an `<a role="button">` or gains a wrapper, silently and with nothing to catch it.
 * The rename removes the collision instead of routing around it.
 *
 * THE SKIN IS TOKENS, WHICH IT WAS NOT BEFORE. With no rule of its own the button fell to
 * Blank's generic `button`, and `_buttons.css` has no bare `button` selector — so it painted
 * `#f2f2f2` / `#333` / `#cdcdcd` / `3px` in ALL FIVE palettes, off-palette and against this
 * file's own token-only header. That also fooled a contrast probe: Luma grey-on-grey scores
 * 11.29:1, a comfortable PASS on a control that was completely palette-blind.
 *
 * `min-height: 44px` is CLAUDE.md 11.4's tap-target floor. The control measured 32px tall
 * before this rule existed, so the floor is a fix, not a precaution. */
.hrv-quickview-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 8px 16px;
  border: 1px solid var(--hrv-border);
  border-radius: var(--hrv-radius-md);
  background: var(--hrv-surface);
  color: var(--hrv-text);
  font-family: var(--hrv-font-body);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease, background-color 0.15s ease;
}
.hrv-quickview-trigger:hover,
.hrv-quickview-trigger:focus-visible {
  border-color: var(--hrv-accent);
  color: var(--hrv-accent);
  background: var(--hrv-accent-tint);
}
.hrv-quickview-trigger:focus-visible {
  outline: 2px solid var(--hrv-focus-ring);
  outline-offset: 2px;
}

/* The loading state the modal shows while the PDP is being fetched. `render()`'s sibling
   `open()` emits `<p class="hrv-quickview-loading">`, and nothing styled it — so the one
   frame every shopper sees first was unstyled Blank body text inside a themed dialog. */
.hrv-quickview-modal .hrv-quickview-loading {
  color: var(--hrv-text-muted);
  text-align: center;
  padding: 24px 0;
  margin: 0;
}

/* ---------- Content layout — THE ARTBOARD'S TWO-COLUMN DIALOG, AND IT NOW PAINTS ----------
 *
 * RETRACTED: "this block and the `.hrv-quickview__*` rules under it describe a modal body that
 * `quick-view.js` DOES NOT BUILD", and RETRACTED: "The NINE `__`-suffixed classes below …
 * across fifteen rules counting the `max-width:767px` block, match nothing." Both were TRUE
 * when written and are false as of basil-T13, which changed `render()` to build this contract
 * instead of its single-hyphen twin. The wording is kept rather than deleted so a reviewer can
 * check the correction against what was actually said (playbook, Record accuracy, rules 2-3).
 *
 * RETRACTED, AND IT WAS WRONG WHEN WRITTEN, NOT MERELY SUPERSEDED: "Counted, not estimated —
 * an earlier draft of this comment said 'eight' and was wrong." The count of `__`-suffixed
 * classes was right; the SET was not. A mechanical census of every `.hrv-quick*` token in this
 * file and in `_product-card.css`, cross-referenced against every `.phtml`/`.js`/`.xml`/`.html`
 * the theme ships WITH COMMENTS STRIPPED, found **thirteen** dead classes, not nine and not
 * register #168's "eight": the nine `__` names, PLUS `.hrv-quickview` itself — the content root,
 * which this very comment asserted matched nothing while not counting it — PLUS the three
 * `.hrv-quick-view-trigger` names in `_product-card.css`. Comment-stripping is load-bearing:
 * the first version of that census scored two classes LIVE on hits inside `quick-view.js`'s own
 * docblock, and a class named in prose is not a class emitted by code.
 *
 * WHAT basil-T13 DID WITH THEM, per class rather than per family:
 *     LIVE NOW   .hrv-quickview, __media, __media-empty, __info, __name, __name-link,
 *                __price, __view          — `render()` builds them; this is the comp's
 *                                            `grid-template-columns: 1fr 1fr` dialog
 *     DELETED    .hrv-quickview-image, -title, -full   — the single-hyphen stack `render()`
 *                                            used to build, superseded by the above
 *     DELETED    __atc, __atc-btn         — the comp's "Add to basket". NOT built: the card's
 *                                            button is driven by a `catalogAddToCart` widget
 *                                            bound at page init, and a clone without that
 *                                            binding is a control that lies. Declared comp
 *                                            delta, not an oversight.
 *     NOT BUILT  the comp's unit price `€24.00/L`. ADDED BY THE S8 GATE, which found it was
 *                                            the ONE comp element absent from the render and
 *                                            absent from this list - the rating, size select
 *                                            and Add-to-basket were all declared, so a reader
 *                                            checking this block against the artboard would
 *                                            have concluded the divergences were fully
 *                                            enumerated. An undeclared omission is worse than
 *                                            a declared one precisely because the list looks
 *                                            complete. Not built because unit price is a
 *                                            catalogue attribute this tenant does not carry;
 *                                            recorded so the next reader knows it was seen.
 *     DELETED    the three `.hrv-quick-view-trigger*` names in `_product-card.css` — a THIRD
 *                                            generation describing a 40x40 ICON-ONLY button
 *                                            with a visually-hidden label, a DIFFERENT DESIGN
 *                                            from the text button this file ships, emitted by
 *                                            nothing and reachable by nothing.
 * Register #168 is closed by that split, in the playbook, with the census output behind it. */
.hrv-quickview {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  align-items: start;
}

.hrv-quickview__media {
  border-radius: var(--hrv-radius-md);
  overflow: hidden;
  background: color-mix(in oklab, var(--hrv-text) 5%, var(--hrv-surface));
  aspect-ratio: 1 / 1;
}
/* RETRACTED IN FULL, BY THE PASS THAT WROTE IT. This block said `contain`, NOT `cover`, AND
   THIS IS A DELIBERATE DIVERGENCE FROM THE CARD GRID, and justified it with: "This catalogue's
   photos are 750x1000 - 3:4 PORTRAIT, not square - and in the 1/1 box `cover` was measured
   discarding 25.0% of the source at 1440, 768 AND 375". The arithmetic was right and it was
   ABOUT THE WRONG THING, so the conclusion drawn from it was wrong and the rule is back to
   `cover`.

   AMENDED: THERE ARE TWO MASTER FAMILIES AND THIS PARAGRAPH MEASURED ONLY ONE. Counted in
   the pod across all 1,275 non-cache catalog images: 800 are 768x768 - the Harvest FOOD
   catalogue, the products this theme exists for - and 475 are 800x600, the
   bags-accessories filler. For the food family the padding is 125/125, the photograph sits
   at y=125..874, and the 398x398 tile ends up 100.0% FILLED: margin 0px, not the ~93px the
   800x600 numbers below imply. 0.00% of the photograph is lost on EITHER family, so the
   conclusion and `cover` both stand - but a rule declared to apply theme-wide was measured
   on the family this theme uses least. Same measure-one-sample-and-generalise error the
   paragraph below exists to retract, committed inside the retraction. The 800x600 figures
   that follow are correct FOR THAT FAMILY and are kept for it.

   WHAT THE 25% ACTUALLY WAS, ON THE ACCESSORIES FAMILY. The source master FOR THAT FAMILY is
   800x600 - LANDSCAPE (the food catalogue's is 768x768; see the amendment above). The 750x1000 file the
   dialog loads is Magento's `keepFrame` resize, which PADS the photograph out to the image
   role's exact box. Measured in the pod with GD, with an all-white control returning a null
   content box and a known 10/20/80/60 inset returning itself exactly: in that 750x1000 file the
   photograph occupies y=210..784 (h=574), with 210px of white padding above and 216px below and
   NONE left or right. `cover` into the 398x398 tile crops 125 canvas px off each of top and
   bottom - entirely inside the padding. **0.00% of the photograph is lost.**

   HOW THE ERROR WAS CAUGHT: by LOOKING at the capture. Every number passed, and the picture
   showed the photo occupying under half the tile with grey letterbox bands beside it and white
   padding above and below it - which is what `contain` does to an already-padded canvas. The
   probe that produced the 25% had also kept computing the COVER formula after the rule was
   switched, and reported "CROPS 25%" while `object-fit` computed `contain`; it now branches on
   the real value.

   SO `cover` IS RIGHT HERE, and for the reason the first version dismissed as "an argument, not
   a measurement": it fills the comp's square tile, it matches `_product-card.css` on every card
   in the store, and on this catalogue it discards padding rather than product. Register #197 is
   corrected to say this. The general rule survives and is sharper - crop is a property of the
   PAIR, and on a padded resize the pair to measure is the box against the CONTENT BOX, never
   against the file. */
.hrv-quickview__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* `--hrv-text-muted`, NOT `--hrv-text-subtle`, and the swap is the whole point of touching
   this rule. Register #191 measured `--hrv-text-subtle` at 3.50:1 — a WCAG AA failure — and
   this rule had never painted, so nothing had ever caught it. Making a dead rule live is
   adding a `color:` declaration, and #191's standing rule is that any such addition must be
   checked at the rule index rather than trusted to the whole-page sweep, which bands by
   painted colour and is blind to a NEW consumer of an already-banded one.

   RETRACTED: "`--hrv-text-muted` is 5.49:1 on basil (#194)". That number is register #194's, and
   #194 measured it against `--hrv-bg`. THIS element paints on
   `color-mix(in oklab, var(--hrv-text) 5%, var(--hrv-surface))` — a different ground, so the
   citation was half a ratio imported from another pair, which is #194's OWN failure mode
   reproduced in the comment that cites it. Caught by the S1 record-accuracy review.

   MEASURED HERE INSTEAD, on this element's real backdrop, with the theme's canvas instrument
   (`contrast-sweep.js`, self-tests green at both ends: black/white 21.00, grey/white 4.54,
   oklab accepted, transparent reads alpha 0), in the state a shopper reaches — the dialog open
   with the image-less branch on screen:
       .hrv-quickview__media-empty   fg oklab(0.498994 …) on bg oklab(0.962292 …)
       13px, required 4.5           -> 5.39   PASS
   The conclusion is unchanged and the number is not. */
.hrv-quickview__media-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--hrv-text-muted);
  font-size: 13px;
}

.hrv-quickview__info {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* 24px / 700 / 1.12 are the artboard's own values for this `h2`
   (design/store-theme/03-harvest-food/colors/Basil/pages/"T13 Quick View.dc.html", the
   `Single-Grove Olive Oil 1L` heading). The rule previously said 22px / 600, which was never
   measured against anything because the rule had never painted. Read off the comp, not
   derived. */
.hrv-quickview__name {
  margin: 0;
  font-family: var(--hrv-font-display);
  font-weight: 700;
  font-size: 24px;
  line-height: 1.12;
}
.hrv-quickview__name-link {
  color: var(--hrv-text);
  text-decoration: none;
}
.hrv-quickview__name-link:hover {
  color: var(--hrv-accent);
}

/* Price — inherit the card's price-box typography (cloned markup carries
   .price-box / .price, already themed by _product-card.css). Just sizes it up. */
.hrv-quickview__price .price-box .price {
  font-size: 22px;
}

/* `.hrv-quickview__atc` and `__atc-btn` WERE HERE and are deleted — see the split at the top
   of this section. The comp's "Add to basket" is a declared delta, not an omission. */
.hrv-quickview__view {
  font-weight: 600;
  font-size: 13px;
  color: var(--hrv-accent);
  text-decoration: none;
}
.hrv-quickview__view:hover {
  color: var(--hrv-accent-hover);
  text-decoration: underline;
}

/* ---------- Responsive ---------- */
@media (max-width: 767px) {
  /* CORRECTED — an earlier draft of this comment claimed this block "re-applied a grid to
     the trigger below 768px, which is where T4's 10/10 wrap was measured." BOTH HALVES WERE
     FALSE, and the table 60 lines above disproves the second one: this block sets only
     `grid-template-columns` and `gap`, never `display:grid` (that came from the base rule,
     which applied at every width), and T4's 10/10 wrap was measured AT 768, where
     `max-width:767px` cannot apply — at 375, where it does apply, T4 measured 0/10.
     The rename at source now keeps this block off the trigger regardless. */
  .hrv-quickview {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .hrv-quickview__media {
    max-width: 320px;
    margin: 0 auto;
  }
  .hrv-quickview__name { font-size: 19px; }
}

/* ---- The FAILURE state ------------------------------------------------------------------
 * `open()`'s `.fail()` branch — the screen a shopper reaches when the product fetch dies, and
 * the only screen in this feature that exists purely because something went wrong. It shared
 * `.hrv-quickview-loading`'s look by accident of proximity and nothing named it, so it is
 * given its own class here and its own centred treatment. Exercised, not assumed: the T13
 * probe swaps `$.get` for one that rejects and asserts a human-readable message AND an escape
 * link pointing at the CLICKED card, because "did not crash" and "said something useful" are
 * different outcomes (CLAUDE.md 3.10). */
.hrv-quickview-modal .hrv-quickview-error {
  color: var(--hrv-text);
  text-align: center;
  padding: 24px 0 8px;
  margin: 0;
}

/* ---- RETRACTED AND SUPERSEDED: "T13: constrain the modal image" -------------------------
 * The three rules that stood here — `.hrv-quickview-modal .hrv-quickview-image`, `… -title`
 * and `… -full` — are deleted, because `render()` no longer emits those elements. Their
 * comment is kept, because the LESSON in it survives the rules and is the reason this task
 * screenshotted the new layout at three widths before believing any of its numbers:
 *
 *     "FOUND BY LOOKING, NOT BY MEASURING. Every numeric check passed — modal opens, real
 *      title, real price, real image src, correct PDP link — and the screenshot showed the
 *      product photo filling almost the entire dialog, pushing the title and price to the very
 *      bottom of a ~950px-tall popup."
 *
 * `max-height: 42vh` was the fix for that, and the constraint has NOT been dropped — it has
 * moved into the geometry. `.hrv-quickview__media` is one `1fr` track of a two-column grid in
 * a dialog capped at 860px, with `aspect-ratio: 1 / 1`, so the photo is bounded by the
 * COLUMN's width rather than by a viewport fraction; below 768 the column collapses to one and
 * `__media` is capped at 320px. Measured, not assumed — see the task record's dialog heights
 * at 1440 / 768 / 375. */
