/* ==========================================================================
   T31 — Contact

   ONE ROUTE: `/contact/`. Body class read VERBATIM from the live pod, not derived by analogy —
   `contact-index-index page-layout-1column`. Harvest adds `hrv-page-t31` from the handle.

   GREENFIELD FOR HARVEST, NOT FOR BLANK. A CSSOM walk found zero Harvest rules naming
   `.contact-index-index`, but EIGHT rules match the live form, six of them Blank's — and one of
   those six is the reason this file exists in the shape it does. Nothing here can regress a
   closed page — but NOT for the reason an earlier version of this line gave. It claimed "every
   selector is scoped to `.hrv-page-t31` or `.contact-index-index`"; **13 of the 32 rules** are not
   (`.hrv-t31-grid`, its `:has()` variant, `.hrv-t31-grid > .form.contact`, and 11 `.hrv-t31-info*`
   rules carrying 12 selectors). The FIRST correction of this line said "12 of 33" and "9" — every
   figure wrong, in a sentence written to fix a wrong count. The isolation is real and comes from somewhere else: this stylesheet is
   registered on the `contact_index_index` handle ONLY, verified by grep across the theme, and the
   `hrv-t31-*` classes exist on no other page.

   ------------------------------------------------------------------------------------------
   REGISTER #84 — BLANK'S 600px FLOOR, AND WHY IT IS FATAL TO THE COMP'S GRID.

     .contact-index-index .column:not(.sidebar-additional) .form.contact { min-width: 600px }

   at (0,5,0), inside `@media (min-width: 768px)`. Measured live on the pod, five viewports:

     viewport   .column.main   form width   1.2fr track if grid applied   floor binds?
       375          343           343              174.00                  n/a (<768)
       768          720           600 <-- floored  379.64                  YES -> card gets 119.78px
      1024          960           600 <-- floored  510.55                  YES -> card gets 336px
      1188         1124           600 <-- floored  600.00                  exactly at crossover
      1440         1376           688 (= 50%)      737.45                  no

   So applying the comp's `1.2fr 1fr` naively leaves the info card 119.78px at 768 and the grid
   overflows `.column.main` by 24px (grid scrollWidth 744 vs column 720). An earlier version said
   96px, from `720 - 24 - 600`. That arithmetic ignores what `1fr` means: it is `minmax(auto, 1fr)`
   and its automatic minimum is the item's min-content, which the track cannot go below. The card
   does not shrink to 96 — it refuses, and the grid overflows instead. Same defect; the number was
   reached by subtraction rather than by measurement, and was wrong. The crossover is
   `(W-24)*1.2/2.2 = 600`, i.e. a column of 1124, i.e. a viewport of 1188: predicted by arithmetic
   BEFORE any CSS existed and then confirmed to the pixel by measurement. This is structurally
   T28's CRITICAL reached from the opposite direction.

   TWO THINGS ADDRESS IT, AND ONLY ONE IS LOAD-BEARING. An earlier version claimed "BOTH are
   load-bearing — dropping either reintroduces the defect". Tested: at 768 with the grid forced to
   two columns (fix 1 dropped) and `min-width: 0` retained, the tracks are 379.63 / 316.36 and
   nothing overflows. Fix 2 alone is sufficient.
     1. The grid engages only at >=1024. A DESIGN choice — a 380/316 split at 768 is cramped — not
        a structural necessity. Stating it as load-bearing was a guess dressed as a finding, and
        the counterfactual took one probe to run.
     2. Inside the grid the floor is neutralised outright: at 1024 the unconstrained track is
        510.53 and the floor WOULD still bind. Section 3 does this at (0,6,0). THIS is the fix.

   ------------------------------------------------------------------------------------------
   TWO DECLARED DELTAS FROM THE ARTBOARD. Both are stated here rather than left for a reviewer
   to discover by diffing the comp.

   (a) THE COMP DRAWS NO LABELS — placeholder-only fields. Not shipped. A placeholder is not a
       label: it disappears the moment the field has content, so a sighted user who tabs back to
       check what they typed has nothing to read, and WCAG 3.3.2 is about instructions remaining
       available. The usual rescue — a visually-hidden <label> plus a placeholder — fixes the
       screen-reader path and leaves the sighted-user path exactly as broken, which is worse for
       being harder to notice. So the labels stay VISIBLE, stacked above their fields (section 4).
       That also happens to match the comp's single-column rhythm; the delta is one of text
       present vs absent, not of layout.

   (b) THE COMP PROMISES "we reply within one business day". Not shipped — a service-level
       commitment is a business promise, not a design token, and Magento's own copy says "very
       soon". Register #83.

   SECTION 6 IS WRITTEN FOR BOTH STATES, and the card-absent one is the default: on a store with
   no Store Information configured, `StoreContact::hasContactDetails()` is false, the block emits
   nothing, and the grid must fall back cleanly to a single column rather than leaving a 1fr hole.
   Register #83 holds the per-tenant census; it is not restated here, because a row count is true
   of one store on one day. Section 3 uses `:has()` so the second track only
   exists when the card does — and BOTH states are verified live, because an unrendered branch
   hides every bug inside it.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Page frame

   `page-layout-1column`, so `.column.main` is the full content width. The cap matches the
   artboard's 1376 content column (= --hrv-container 1440 - 2x --hrv-page-pad 32).
   -------------------------------------------------------------------------- */
.hrv-page-t31 .page-main {
  max-width: var(--hrv-container);
  margin-left: auto;
  margin-right: auto;
  padding-bottom: 72px;
}

.hrv-page-t31 .page-title-wrapper {
  margin: 0 0 8px;
}

.hrv-page-t31 .page-title {
  font-family: var(--hrv-font-display);
  font-size: clamp(30px, 4.4vw, 44px);
  line-height: 1.14;
  letter-spacing: -0.01em;
  color: var(--hrv-text);
  margin: 0;
}

/* --------------------------------------------------------------------------
   2. The grid

   Single column below 1024 — see the header table: between 768 and 1023 the comp's 1.2fr track
   would be floored at 600 by Blank and starve the info card. Stacking is not a compromise here,
   it is the only arrangement that fits.
   -------------------------------------------------------------------------- */
.hrv-t31-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 32px;
  align-items: start;
}

@media (min-width: 1024px) {
  /* The second track exists only when the info card does. `StoreContact::hasContactDetails()` is false on a store
     with nothing configured, so the block emits no markup at all and a fixed `1.2fr 1fr` would
     leave a 1fr hole beside a form. Scoped with :has() rather than a body class because the
     condition is a property of the rendered subtree, not of the route. */
  .hrv-t31-grid:has(> .hrv-t31-info) {
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    gap: 24px;
  }
}

/* THE FORM IS CAPPED UNCONDITIONALLY, AND THE FIRST TWO ATTEMPTS AT THIS WERE BOTH WRONG.
   With no info card the single track is the whole column, so the form stretched to 1376px at 1440
   and every input with it — measured, not supposed. A 1376px-wide "Name" field is not a form
   anyone would ship, and it is the state this tenant is actually in, so it is what renders.

   737px is the comp's own form column at 1440: (1376 - 24) * 1.2 / 2.2 = 737.45.

   ATTEMPT 1 capped `.hrv-t31-grid` — the whole layout, not the form.
   ATTEMPT 2 capped `.hrv-t31-grid:not(:has(> .hrv-t31-info))`, i.e. the empty state only. A review
   found two defects in that, and both are fixed by moving the cap onto the form itself:
     - `:has()` and `:not(:has())` are strict complements only in a UA that IMPLEMENTS `:has()`.
       Where it is unsupported, `:has()` is an unknown pseudo-class and `:not()` takes a
       NON-FORGIVING selector list, so BOTH rules are dropped — landing on the uncapped 1376px
       state this rule exists to prevent. The failure mode was the regression itself.
     - The cap applied only when the card was ABSENT, but 768-1023 is single-column in BOTH states,
       so a store with contact details configured had an uncapped ~975px form at 1023.
   The old comment also claimed "below 1024 the column is already narrower than the cap (720 at
   768)". True at 768 only: the column passes 737 at roughly an 800px viewport, so the cap does
   bind across most of that range.

   On the form, the cap is correct in every state and needs no `:has()` at all. In the two-column
   layout the track is 737.453px, so the cap binds by 0.45px — measured 737.00. An earlier version
   said it "changes nothing": true of the cap alone, false of the rule as shipped, because the same
   block carries `margin-inline: auto` and until `width` moved to section 3 the combination sized
   the form at 414.27px in EVERY state.
   `:has()` now survives only on the two-track rule above, where losing it degrades gracefully to
   a stacked card. */
.hrv-t31-grid > .form.contact {
  /* THE WIDTH THAT MAKES THIS WORK LIVES IN SECTION 3, NOT HERE, AND THAT COST TWO ATTEMPTS.
     Auto margins on a grid item absorb the free space in that axis and suppress the default
     `justify-self: stretch`, so the item is sized to its FIT-CONTENT width rather than its track.
     Shipped measurement at 1440: form 414.27px, inputs 414.27px, `max-width: 737px` never binding
     because 414.27 < 737 — the cap and the five-viewport argument above described a form that did
     not exist.
     The obvious repair, `width: 100%` on THIS rule, also failed: this selector is (0,3,0) and
     section 3's `width: auto` is (0,6,0), so my own override beat my own fix. The width is
     therefore set in section 3, where the contest with Blank's `width: 50%` already lives.
     `max-width` and the centring stay here, on the rule that owns the cap. */
  max-width: 737px;
  /* CENTRED, because the capped state is the one that actually ships. Measured dead gutter to the
     right of the form before this line: 0 at 375 and 768, 238px (24%) at 1023, 639px (46%) at 1440
     — a page that reads as though its right column failed to load, which is the precise shape this
     design exists to avoid. An unconfigured Store Information is the out-of-the-box state of every
     fresh Magento tenant, so this is the default rendering, not an edge case.
     Safe in both states: in the two-column layout the track is 510.53px at 1024 and 737.45px at
     1440, so `auto` resolves to 0 and 0.225px respectively and the form does not move. */
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   3. Neutralising Blank's 600px floor  — REGISTER #84

   Weight: .hrv-page-t31(1) .contact-index-index(1) .column(1) :not(.sidebar-additional)(1)
           .form(1) .contact(1) = (0,6,0), against Blank's (0,6,0)... no: Blank's is
           .contact-index-index(1) .column(1) :not(.sidebar-additional)(1) .form(1) .contact(1)
           = (0,5,0). Adding the theme's own body class makes this (0,6,0) and it wins on
           SPECIFICITY, not on document order. That distinction matters: _t31.css and
           styles-l.css are separate <link>s, and relying on their relative order would make the
           fix hostage to head-block ordering that no rule in this theme controls.

   `:not(.sidebar-additional)` is carried over verbatim rather than dropped. It contributes its
   ARGUMENT's specificity, so removing it would silently cost a class and drop this to (0,5,0) —
   a tie, decided by load order, which is the thing this rule is written to avoid.

   `width` is reset alongside `min-width` because Blank also sets `width: 50%` at >=768 (measured:
   the form is 688 of a 1376 column at 1440). As a grid item that 50% would resolve against the
   TRACK, halving the form inside its own column.
   -------------------------------------------------------------------------- */
.hrv-page-t31.contact-index-index .column:not(.sidebar-additional) .form.contact {
  min-width: 0;
  /* `100%`, not `auto`. `auto` was enough to beat Blank's `width: 50%`, but it also lets the auto
     margins in section 2 shrink the grid item to fit-content (measured: 414.27px at every width
     from 768 up). `100%` resolves against the track, section 2's `max-width` caps it at 737, and
     the auto margins then centre only what is left over. */
  width: 100%;
  /* No `float: none` here. The first draft had one; it was DEAD twice over. Blank's own rule
     already declares `float: none` alongside the `width: 50%` this overrides (measured on the
     live page before any Harvest CSS existed: computed float was already `none` at 375 and 768),
     and the element is a grid item, where float does not apply at all. A review flagged it as
     unverifiable without vendor source; it was verifiable from the pre-change measurement, and
     the answer was that it never did anything. */
}

/* --------------------------------------------------------------------------
   4. The form — labels out of Blank's 25.8% gutter

   Measured at >=768 before this file existed: the label floats left at 154.8px (768) / 177.5px
   (1440) — 25.8% — right-aligned, with the control floated beside it at 74.2%. The legend and the
   actions-toolbar carry the same 25.8% left margin. That is Blank's classic desktop form, and it
   is not the comp's.

   Weights, each verified against the rule it replaces rather than assumed:
     label   .hrv-page-t31 .form.contact .fieldset > .field > .label  = (0,6,0) beats (0,4,0)
     control same shape                                              = (0,6,0) beats (0,4,0)
     (These two read (0,5,0) until a review recounted them: six classes, not five. The
     conclusion held either way, but a file whose argument IS the arithmetic has to get it
     right, or the next reader inherits a wrong number stated confidently.)
     legend  .hrv-page-t31 .form.contact .fieldset > .legend          = (0,5,0) beats (0,2,0)
     toolbar .hrv-page-t31 .form.contact .actions-toolbar             = (0,4,0) beats (0,3,1)
   -------------------------------------------------------------------------- */
.hrv-page-t31 .form.contact .fieldset {
  margin: 0;
  padding: 0;
  border: 0;
  /* Blank sets `letter-spacing: -0.31em` on .fieldset as an inline-block gap hack and resets it
     on `> *`. Harmless while it holds, but the children here are block-level, so the hack has
     nothing to collapse and the negative tracking can only leak into stray text nodes. */
  letter-spacing: normal;
}

.hrv-page-t31 .form.contact .fieldset > .legend {
  float: none;
  width: auto;
  margin: 0 0 6px;
  padding: 0;
  border: 0;
  font-family: var(--hrv-font-display);
  font-size: 22px;
  line-height: 1.2;
  color: var(--hrv-text);
}

/* CORE's form.phtml emits `<br>` after the legend (an earlier comment credited Blank); Blank
   supplies the float it exists to clear. With the float gone the break
   only adds a stray line box. */
.hrv-page-t31 .form.contact .fieldset > .legend + br {
  display: none;
}

/* `> .fieldset > .field.note`, not `.field.note`. Core emits the note as a DIRECT child
   of .fieldset, so the bare form tied with `.fieldset > .field { margin: 0 0 18px }` at
   (0,5,0) and LOST on document order — the 24px below was inert, and nothing looked
   broken because only the margin differed. */
.hrv-page-t31 .form.contact .fieldset > .field.note {
  margin: 0 0 24px;
  color: var(--hrv-text-muted);
  font-size: 15px;
  line-height: 1.55;
  max-width: 52ch;
}

.hrv-page-t31 .form.contact .fieldset > .field {
  margin: 0 0 18px;
}

.hrv-page-t31 .form.contact .fieldset > .field > .label {
  float: none;
  width: auto;
  padding: 0 0 6px;
  text-align: left;
  box-sizing: border-box;
  display: block;
  font-family: var(--hrv-font-body);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--hrv-text);
}

.hrv-page-t31 .form.contact .fieldset > .field > .control {
  float: none;
  width: auto;
}

/* Blank's clearfix on `.fieldset > .field` generates ::before/::after table boxes to contain the
   floats it no longer has. Left in place they are two empty rows in the field's flow. */
.hrv-page-t31 .form.contact .fieldset > .field::before,
.hrv-page-t31 .form.contact .fieldset > .field::after {
  content: none;
}

/* `width`, `box-sizing` and `min-height` are NOT repeated here. The S7 gate removed each in turn
   and measured no change: `components/_forms.css` already sets them, so they were four
   declarations asserting things that were already true. Left in, they read as load-bearing to the
   next person and would survive a deletion of the component rule without anyone noticing. */
.hrv-page-t31 .form.contact .fieldset > .field .input-text {
  padding: 12px 14px;
  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: 15px;
  line-height: 1.4;
  /* Blank ships inputs at height:32px, under the 44px touch target the responsive bar requires at
     375. `height: auto` releases that so the box can be sized by its own padding and line-height.
     MEASURED RESULT: 47px — 12+12 padding, ~21px line box, 2px border. An earlier comment credited
     a `min-height: 46px` for the guarantee; the gate showed it never binds, because the padded
     height already exceeds it. The 44px floor holds, but not by the stated mechanism, and a
     mechanism nobody has tested is the kind of comment this file has already been wrong in twice. */
  height: auto;
}

.hrv-page-t31 .form.contact .fieldset > .field textarea.input-text {
  /* `resize: vertical` likewise comes from `components/_forms.css`; only the taller floor is T31's. */
  min-height: 148px;
}

.hrv-page-t31 .form.contact .fieldset > .field .input-text:focus {
  border-color: var(--hrv-accent);
  outline: 2px solid var(--hrv-focus-ring);
  outline-offset: 1px;
}

/* --------------------------------------------------------------------------
   5. Submit

   The toolbar carries Blank's 25.8% left margin and floats `.primary` left. Both go.

   `.actions-toolbar > .primary` is an inline-block WRAPPER around the button — a `width: 100%`
   on the button resolves against that wrapper, which is why an earlier task on this repo set a
   full-width button and measured 119px. The wrapper is what has to change, so it is what changes
   here.
   112.17px wrapper / 107.17px button are the PRE-FIX BASELINE — Blank's inline-block wrapper
   hugging the button before this section set `display: block`. An earlier version printed them
   after the words "Verified live", in the sentence position of a post-fix confirmation, which is
   how any reader would take them. SHIPPED, measured on 0.1.114: wrapper 737.00 / button 180.00 at
   1440, and 343.00 / 343.00 at 375.
   -------------------------------------------------------------------------- */
.hrv-page-t31 .form.contact .actions-toolbar {
  margin: 24px 0 0;
  width: auto;
}

.hrv-page-t31 .form.contact .actions-toolbar > .primary {
  float: none;
  display: block;
  width: auto;
}

.hrv-page-t31 .form.contact .actions-toolbar > .primary .action.submit {
  width: auto;
  min-width: 180px;
  justify-content: center;
}

@media (max-width: 767px) {
  /* Full-bleed CTA on mobile, matching every other Harvest form. `.primary` is the box that has
     to stretch; the button's own width is auto and follows it. */
  .hrv-page-t31 .form.contact .actions-toolbar > .primary .action.submit {
    width: 100%;
  }
}

/* --------------------------------------------------------------------------
   6. The info card

   Renders only when the merchant has configured something — see the header and the template's
   own docblock. Styled for the populated state; the empty state is the absence of this whole
   subtree, which section 2's `:has()` handles.
   -------------------------------------------------------------------------- */
.hrv-t31-info {
  background: var(--hrv-surface);
  border: 1px solid var(--hrv-border);
  border-radius: var(--hrv-radius);
  padding: 28px;
}

.hrv-t31-info__title {
  font-family: var(--hrv-font-display);
  font-size: 20px;
  line-height: 1.25;
  margin: 0 0 20px;
  color: var(--hrv-text);
}

.hrv-t31-info__group + .hrv-t31-info__group {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid var(--hrv-border);
}

.hrv-t31-info__label {
  font-family: var(--hrv-font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--hrv-text-subtle);
  margin: 0 0 6px;
}

.hrv-t31-info__address {
  font-style: normal; /* UA default italicises <address>; the element is chosen for meaning. */
  margin: 0;
}

.hrv-t31-info__line {
  display: block;
  font-size: 15px;
  line-height: 1.6;
  color: var(--hrv-text);
}

.hrv-t31-info__value {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--hrv-text);
}

/* `pre-line` IS SCOPED TO HOURS, AND THE FIRST VERSION PUT IT ON THE SHARED CLASS.
   The hours field is one free-text string a merchant typed, so its line breaks are honoured. But
   `.hrv-t31-info__value` is also the phone row's class, and that row's template body spans several
   lines of PHP — under `pre-line` those source newlines are PRESERVED (only spaces and tabs
   collapse), and nothing strips a leading break inside a `<p>`; the `<pre>`/`<textarea>` "drop the
   first newline" rule does not apply. The result was an empty ~24px line box between the PHONE
   label and the number.

   It only appeared in the POPULATED state — the branch this tenant never renders — and I had
   photographed that state at 1440 and 768 without seeing it. A review found it by reading the
   emitted markup instead of the picture. This theme's own register already carries the shape:
   one class, two content types, styled for one of them. */
.hrv-t31-info__value--hours {
  white-space: pre-line;
}

.hrv-t31-info__link {
  color: var(--hrv-accent);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.hrv-t31-info__link:hover,
.hrv-t31-info__link:focus-visible {
  border-bottom-color: currentColor;
}
