/* ==========================================================================
   Air Market - v9 mobile layer, the 44px tap-target floor
   (V9-MOBILE-SPEC.md section 3.6, acceptance bar AC6). Owner: T3a, after
   T2.5. CSS only, no markup or JS change.

   WHAT THE PROBE ACTUALLY MEASURES, because every rule below is shaped by
   it. tools/mobile-qa.mjs's AC6 probe walks `a, button, [role=button],
   input, select`, skips display:none / visibility:hidden and inline prose
   links, and then reads `el.getBoundingClientRect()`. So the number that
   has to reach 44 is the element's own BORDER BOX - not its offset size,
   not a pseudo-element's box, not the padded area of an ancestor. Two
   consequences the spec's own wording does not anticipate:

     - Section 3.6 says "where a visual can't grow (pager dots), a
       `::before` overlay extends the hit box". A ::before CANNOT satisfy
       this probe: the probe never looks at pseudo-elements, and a child
       box does not enlarge its parent's rect. So the technique is INVERTED
       throughout this file - the ELEMENT becomes the 44px box and its
       ::before paints the small visual that used to be the element. Same
       pixels on screen, same footprint in flow, and a rect the probe can
       see. Read that as an amendment to 3.6, not a deviation from it.
     - Both dimensions count (`r.width < 44 || r.height < 44`). A 290x37
       footer link fails on 7px of height; a 40x64 "See all" fails on 4px
       of width. Grep the offender census before assuming which axis is
       short.

   TWO TECHNIQUES, PICKED BY WHETHER THE CONTROL PAINTS ANYTHING.

     (a) Transparent controls - text links, ghost text buttons. Add padding
         and cancel it with an equal negative margin. The rect grows, the
         flow footprint is unchanged, and because there is no background
         and no border there is nothing to repaint. Zero pixel diff, and
         no ::before needed. Where the control has a border on ONE edge
         (.ql-grid a's hairline) the padding goes on the OPPOSITE edge only,
         so the border does not move relative to the text.
     (b) Painted controls - pills, chips, circles. The element takes the
         44px box, its own background/border are switched OFF, and a
         `::before` at a fixed inset repaints the original visual at the
         original size in the original place. A negative margin (in flow)
         or a shifted offset (when already absolute) keeps the footprint.
         Needs `position: relative; isolation: isolate` so the pseudo at
         `z-index: -1` paints above the ancestor's background and below the
         element's own text - `isolation` rather than a z-index of our own,
         because links.css:56 already assigns z-index 2 to these controls
         to keep them above the stretched card overlay, and this file has
         no business renumbering that.

   WHY T2.5'S VERSION OF THIS FILE MISSED, since four of the classes it
   reported as fixed were still failing when T3a measured them. It failed
   in two distinct ways, and both are worth knowing before adding a rule:

     1. SPECIFICITY. `button.get-btn` is (0,1,1). The declaration that
        actually sets that button's padding is store-v2.css:353,
        `:root:is([data-ui="v2"]…) .a-foot .get-btn`, at (0,4,0). The
        padding bump never applied - measured computed padding stayed
        `4px 15px`. Same story for `button.v6-dismiss` (0,1,1) against
        store-v6-rec.css:82 (0,2,0). A media query adds no specificity, and
        loading last does not help when the other rule is simply stronger.
     2. THE BOX MODEL. `store.css:76` is `* { box-sizing: border-box }`, and
        most of these controls also carry an explicit `height`. Under those
        two facts padding is absorbed and the border box - the only thing
        the probe reads - never moves. `.chrome-btn` proves it: T2.5's
        `padding-left/right: 7px` DID apply, and the button still measured
        exactly 30x30.

   And its negative margins were not paired with the padding that was
   supposed to offset them, which cost real pixels: `.a-foot` collapsed
   from 35px to 23px (margin -10px against a padding bump of +4px that lost
   the cascade), the card Get pill was repainted 54x24 -> 84x32, and the
   Stack chip's white pill was repainted 24px tall -> 46px tall. None of
   that is visible in a tap count, which is why this file's own bar is
   "measured computed style, then screenshot", not "the number went down".

   HARD RULE, identical across all seven v9 sheets: every declaration in
   this file lives inside `@media (max-width: 720px)` or
   `@media (max-width: 480px)`. A rule outside either query is a desktop
   regression by definition - the >= 861px byte-identity bar (AC2) is a
   structural guarantee only while that is true of all seven sheets.

   SCOPING: mirror the prefix of the rule you are overriding, checked in ITS
   source file - unprefixed for store.css and components.css,
   `:root:is([data-ui="v2"],[data-ui="v3"],[data-ui="v4"],[data-ui="v5"])`
   for the v2/v3-era sheets, `:root[data-ui="v5"]` for store-v5.css,
   `:root[data-v6="on"]` for the v6 sheets. Never !important.

   NOT THIS FILE'S: the top bar's own controls (T1, store-v9-nav.css - they
   already measure 44px and pass, and T1 also already sets the search
   input to 16px at <= 720px, so this file does not repeat it), and the
   browse facet disclosure panel (T2.3, store-v9-browse.css). T2.5's
   `#topbar .v3-link` / `.v3-brand` / `.v3-stack-btn` rules are gone: they
   were zero-net padding-plus-negative-margin pairs on controls that were
   not in the offender census in the first place, i.e. pure risk to T1's
   layout for no measured gain.
   ========================================================================== */

@media (max-width: 720px) {
  /* ---- 1. The "Get" pill: 419 of 727 offenders at 390px ------------------
     store.css:536 is `height: 24px`, so EVERY Get pill in the store fails,
     and 404 of them are the one on a card foot. Technique (b): the pill
     keeps painting at 24px and the button's box becomes 44px.

     One variable drives the whole thing. `--v9-pill-y` is how far the
     visible pill is inset inside the hit box; the negative margin that
     hides the growth from the flow is derived from it, and so is the
     pseudo's inset. That is not decoration: it makes opting a control OUT
     a single declaration (see the v5 hero below) instead of four rules that
     have to stay in sync.

     `--v9-pill` carries the pill's own colour, because `background: inherit`
     cannot work here - the element's background is exactly what we just
     switched off. The variant list below has to name each state selector
     explicitly: `:hover` and `:active` are class-level in the specificity
     algebra, so `.get-btn.primary:active` is (0,3,0) and would otherwise
     out-rank a (0,2,0) reset and repaint the full 44px box. */
  .get-btn {
    --v9-pill-y: 10px;
    --v9-pill: var(--color-action-secondary);
  }
  .get-btn.primary { --v9-pill: var(--color-action-primary); }
  .get-btn:active { --v9-pill: var(--color-action-secondary-active); }
  .get-btn.primary:active { --v9-pill: var(--color-action-primary-active); }
  .story-hero .banner .get-btn { --v9-pill: rgba(255, 255, 255, .92); }

  .get-btn,
  .get-btn:hover,
  .get-btn:active,
  .get-btn.primary,
  .get-btn.primary:hover,
  .get-btn.primary:active,
  .story-hero .banner .get-btn {
    position: relative;
    isolation: isolate;
    height: 44px;
    margin-block: calc(0px - var(--v9-pill-y));
    background: none;
  }
  .get-btn::before {
    content: "";
    position: absolute;
    inset: var(--v9-pill-y) 0;
    z-index: -1;
    border-radius: inherit;
    background: var(--v9-pill);
  }
  /* store.css:554 draws the focus ring as an inset shadow on the element,
     which would now trace the 44px box instead of the pill. Move it. */
  .get-btn:focus-visible { box-shadow: none; }
  .get-btn:focus-visible::before { box-shadow: inset 0 0 0 1px var(--color-border-focus); }

  /* The v5 listing hero's CTA is the one Get pill that was ALREADY 44px
     (store-v5.css:302) and it has its own shadow and focus treatment. Zero
     inset means zero negative margin and a pseudo that covers the whole
     box, so it renders exactly as before - and this is the single
     declaration that says so. */
  :root[data-ui="v5"] .v2-hero-cta .get-btn.primary { --v9-pill-y: 0px; }

  /* ---- 2. The card "+ Stack" chip: the other 404 ------------------------
     Same count as the Get pill, and the one class T2.5's technique did move
     the number on - but at the price of repainting the white pill 24px ->
     46px tall on every card in the store. Technique (b) instead, and it is
     the easy case: the chip is already `position: absolute; bottom: 8px`
     (store-v3-stack.css:108), so shifting the anchor down 10px and insetting
     the pseudo 10px puts the visible pill back on the exact pixel it was on
     while the button's box grows upward into the artwork - which is dead
     space, so there is nothing there to steal a tap from. */
  :root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .a-card .v3-stack-chip {
    isolation: isolate;
    height: 44px;
    bottom: -2px;
    background: none;
    border-color: transparent;
  }
  /* 9px and -1px, not 10px and 0. An absolutely positioned child is offset
     from its containing block's PADDING box, and this chip keeps its 1px
     border reserved (as transparent) so its width math does not move - so
     the padding box is inset 1px from the border box on every side. Insetting
     the pseudo a flat 10px painted the pill 65.4x22 where the design has
     67.4x24: two pixels short in each axis, invisible to the tap count and
     caught only by diffing the rendered card against the same card with this
     sheet disabled. Every technique-(b) control with a border pays this 1px;
     the ones without a border (.get-btn, .chrome-btn, .ql-btns button) do
     not, which is why their insets read as round numbers. */
  :root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .a-card .v3-stack-chip::before {
    content: "";
    position: absolute;
    inset: 9px -1px;
    z-index: -1;
    border: 1px solid var(--v3-line);
    border-radius: var(--radius-full);
    background: var(--v3-paper);
  }
  /* The pressed ("in the Stack") state is ink, store-v3-stack.css:143. Its
     selector is (0,4,1) with the attribute, so the element-level reset above
     at (0,4,0) does NOT cover it - repaint it on the pseudo AND neutralise
     it on the element, or a pressed chip paints a 44px black slab. */
  :root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .a-card .v3-stack-chip[aria-pressed="true"] {
    background: none;
    border-color: transparent;
  }
  :root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .a-card .v3-stack-chip[aria-pressed="true"]::before {
    border-color: var(--color-action-primary);
    background: var(--color-action-primary);
  }
  :root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .a-card .v3-stack-chip:focus-visible::before {
    border-color: var(--color-border-focus);
  }

  /* ---- 3. Sticky chrome bar buttons ------------------------------------
     store.css:374 hard-codes 30x30 with a painted circle and a drop shadow,
     which is why T2.5's padding (which did apply - computed `0px 7px`)
     bought nothing: border-box plus an explicit width and height leaves the
     border box exactly where it was. Technique (b). No vertical margin is
     needed because .chrome-bar is a fixed 52px row with align-items:center,
     so a 44px child changes no height; the horizontal margin keeps the back
     button's 30px footprint so .chrome-title stays centred.

     `flex: none` because at 320px the bar's row (back button + centred
     .chrome-title) is over budget, and a flex item with a width but no
     flex-basis lock shrinks: the button measured 39x44, short on the axis
     it had just been given. The title is `flex: 1` and shrinks in its
     place. */
  .chrome-btn {
    position: relative;
    isolation: isolate;
    flex: none;
    width: 44px;
    height: 44px;
    margin-inline: -7px;
    background: none;
    box-shadow: none;
  }
  .chrome-btn::before {
    content: "";
    position: absolute;
    inset: 7px;
    z-index: -1;
    border-radius: 50%;
    background: rgba(255, 255, 255, .9);
    box-shadow: 0 1px 4px rgba(0, 0, 0, .18);
  }
  /* store.css:383 drops the circle once the bar is scrolled and opaque. */
  .chrome-bar.scrolled .chrome-btn::before {
    background: none;
    box-shadow: none;
  }

  /* ---- 4. The recommendation row's dismiss chip -------------------------
     76x23, store-v6-rec.css:82, absolutely positioned over a card's top
     right corner and (correctly) kept small - "small, honest, and out of
     the way" is the v6 §7.2 argument for it. T2.5 targeted it as
     `button.v6-dismiss` (0,1,1) against a (0,2,0) rule and never landed.
     Technique (b), growing DOWNWARD only: `.v6-rec-cards` is an
     `overflow-x: auto` rail, so its overflow-y computes to auto too and a
     box that reached above the chip's 8px offset would be clipped or would
     summon a vertical scrollbar. The cost is honest and worth stating: a
     ~76x21 band under the pill now belongs to Dismiss rather than to the
     card's own stretched link. A 23px-tall control on a touch screen is
     the worse of the two problems.

     This is the only technique-(b) control here whose visual is NOT centred
     in its hit box - it is pinned to the top - so it is the only one that has
     to say where its label goes. A <button> centres its content box
     vertically by UA behaviour whatever its `display` computes to, so the
     44px box quietly dropped the label 19px down the card - 1484 pixels of
     diff against the same cell with this sheet disabled, and the diff image
     showed "Not for me" printed twice. `display: flex` with `align-items:
     flex-start` puts it back against the 2px top padding; `justify-content:
     center` replaces the horizontal centring the UA was doing. That failure
     is the argument for diffing rendered pixels and not only reading the tap
     count: the count was already green when the label was 19px out of
     place. */
  :root[data-v6="on"] .v6-dismiss,
  :root[data-v6="on"] .v6-dismiss:hover {
    isolation: isolate;
    height: 44px;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    background: none;
    border-color: transparent;
  }
  /* -1px on three edges for the same padding-box reason as the Stack chip
     above. The height is STATED rather than derived from a bottom offset
     because this pill's own height is fractional - 22.7969px, from a 0.75rem
     caption at line-height 1.4 plus 2px of padding either side
     (store-v6-rec.css:82) - and a rounded 23px pill does not sit on a rounded
     22.8px one: the mismatch shows up as anti-aliasing along the arcs. So the
     pseudo is told the same two numbers the base rule uses, 1.4em of line box
     and 4px of padding, and the browser resolves it back to 22.7969. The
     pseudo is content-box (the `*` reset does not match pseudo-elements), so
     the 1px border lands outside that height. */
  :root[data-v6="on"] .v6-dismiss::before {
    content: "";
    position: absolute;
    top: -1px;
    right: -1px;
    left: -1px;
    height: calc(1.4em + 4px);
    z-index: -1;
    border: 1px solid var(--color-border-default);
    border-radius: var(--radius-full, 999px);
    background: var(--color-surface-default);
  }

  /* 4b. THE SAME PSEUDO, IN THE COMPARISON TABLE. Section 4's `::before` is
     `position: absolute` with `left: -1px; right: -1px`, which resolves
     against the nearest POSITIONED ancestor. On a card that is the dismiss
     chip itself (store-v6-rec.css:82 keeps it absolutely positioned), so the
     pill lands where the comment above says it does. In a compare row it is
     not: store-v6-rec.css:156 deliberately returns that copy of the button to
     `position: static`, and the nearest positioned ancestor is then
     `.v6-compare-row` (`position: relative`, store-v6-rec.css:125). The pill
     stretched to the full width of the row and sat across its top edge - at
     375px, a full-width rounded outline printed straight through the listing
     name of the row BELOW it, which is what "UI/UX Pro Max" looked cut in
     half by. `position: relative` gives the pseudo back the containing block
     section 4 assumed it had; nothing else about the button moves. */
  :root[data-v6="on"] .v6-compare-row .v6-dismiss {
    position: relative;
  }

  /* ---- 5. Footer quick-link CTA pills ----------------------------------
     store.css:1085, 94x34 and 181x34, a painted 20px-radius pill. Technique
     (b). These are static in flow and get no stacking context from anything
     else, hence the explicit position/isolation - without it the pseudo at
     z-index -1 would paint behind .store-footer's own background and simply
     vanish. */
  .ql-btns button {
    position: relative;
    isolation: isolate;
    min-height: 44px;
    margin-block: -5px;
    background: none;
  }
  .ql-btns button::before {
    content: "";
    position: absolute;
    inset: 5px 0;
    z-index: -1;
    border-radius: 20px;
    background: var(--color-action-secondary);
  }

  /* ---- 6. Chip strips: the one place growth IS the fix ------------------
     80 offenders at 28px tall across three strips - the browse facet chips
     (.v3-fb-chips), the category row (.chips) and the search scope row
     (.scope-chips), all three the same Air_DS Tabs component
     (components.css:237, `height: 28px`). This is the one class where
     technique (b) is unavailable rather than merely awkward: every one of
     these strips is a horizontal scroller, so its overflow-y computes to
     auto (T1 pins it to `hidden` outright at store-v9-nav.css:545). A chip
     whose box overhangs the strip has the overhang CLIPPED - it would
     measure 44 for the probe and still not be tappable, which is worse than
     failing honestly.

     So the chips genuinely grow, in both axes: `min-width` because the
     narrow ones ("All", 33px) fail on width, not height. The enclosed
     group's sunken background grows with them. That is what spec 3.6 asks
     for by name ("facet rows"), and a 44px chip rail is the ordinary phone
     treatment of a chip rail. Selector mirrors components.css's own
     unprefixed `.tabs--enclosed`, which is where the strip is defined.

     `flex: none` is not tidiness, it is the fix for what min-width broke on
     first measurement: the chips are flex items that shrink by default, so
     widening the narrow ones pushed the strip over 320px and the WIDE ones
     ("MCP Servers", "Bundles") shrank and clipped their own nowrap text -
     two fresh AC4 failures on the search route, caused by an AC6 fix. Held
     at their content width the strip overflows instead, which is what a
     scroller is for, and the rail exemption in both probes then applies.
     T1 already made exactly this declaration for the facet strip
     (store-v9-nav.css:549); this generalises it to the other two. */
  .tabs--enclosed .tab {
    flex: none;
    min-height: 44px;
    min-width: 44px;
    justify-content: center;
  }

  /* The sort control next to them. A select is a form control: it grows,
     full stop - 30px is not a touch target and there is no visual here
     worth preserving at the cost of one. */
  :root:is([data-ui="v3"],[data-ui="v4"],[data-ui="v5"]) .v3-fb-sort select {
    min-height: 44px;
  }

  /* ---- 7. Listing hero secondary CTAs ----------------------------------
     store-v5.css:225, 40px tall, so 4px short. Grown rather than repainted:
     the delta is 2px of border on each edge of a ghost button and the row is
     centred, so nothing else moves. Repainting a 4px difference through a
     pseudo-element would be machinery with no reader left to thank for it. */
  :root[data-ui="v5"] .cta-secondary .save-btn,
  :root[data-ui="v5"] .cta-ghost {
    min-height: 44px;
  }

  /* ---- 8. Transparent text controls: technique (a) ----------------------
     Nothing below paints a background, so padding plus an equal negative
     margin is invisible twice over - no repaint, no reflow. */

  /* Footer quick links, 290x37 (store.css:1079). 100 offenders, the largest
     `a` class in the census by far - and NOT the prose links or the
     links.js card overlays they were first assumed to be (see this task's
     report). The padding goes on the TOP only and the negative margin
     matches it, because the 1px bottom hairline is painted: cancel on the
     same edge you pad and the hairline slides 7px down the row. */
  .ql-grid a {
    padding-top: 16px;
    margin-top: -7px;
  }

  /* Footer legal row, 112x15 (store.css:1124). */
  .foot-legal a {
    padding-block: 15px;
    margin-block: -15px;
  }

  /* The footer's AIR mark, 61x34 (app.js storeFooter). The anchor wraps an
     image, so the usual text-link growth applies to it the same way. */
  .foot-copy a {
    display: inline-block;
    padding-block: 5px;
    margin-block: -5px;
  }

  /* Developer links on a listing, 330x18 (store.css:821), plus the "who
     made this" link in the same column and the developer name in the
     description grid. */
  .dev-links a,
  .dev a {
    padding-block: 13px;
    margin-block: -13px;
  }

  /* The description's "more"/"less" toggle, 29x17 (app.js desc-toggle), the
     info card's Version History link and the quality card's See Full Report
     link, both 17px text rows on the listing page. Same growth idiom. The
     toggle's selector mirrors store.css:857 (.desc-grid .desc .more) exactly:
     that rule sets padding: 0 at (0,3,0), so anything weaker loses the padding
     and keeps the negative margin - a smaller target than doing nothing. */
  .desc-grid .desc .more,
  [data-section="whats-new"] a,
  .q-side a {
    padding-block: 14px;
    margin-block: -14px;
  }
  /* The toggle is also only 29px WIDE ("more"), and the gate flags either
     dimension. The links above are wide enough already. */
  .desc-grid .desc .more {
    padding-inline: 8px;
    margin-inline: -8px;
  }

  /* "See all" on a section head. Inline padding with a matching negative
     margin, so the label does not move inside the space-between row it sits
     in.

     `white-space: nowrap` and `flex: none` are the point of this rule, not
     trim. `.section-head` is a flex row and the base sheet leaves this link
     at the default `flex: 0 1 auto`, so a long heading ("Skills and Agents
     We Love Right Now") wins the space contest and squeezes the link until
     "See All" breaks across two lines at 53px wide. A two-word affordance
     that reads as two stacked words is worse than a heading that wraps,
     which is what happens instead now: the link keeps its content width and
     the heading takes the remainder.

     The base sheet already does exactly this for `.vids-head .see-all` and
     `.vids-empty .see-all` (store.css:1279, :1292); the section-head
     instance simply never got it, and this file's first pass papered over
     the symptom by widening the padding until the wrapped box measured 44px
     rather than asking why it was wrapping. One line is 18px, so 13px of
     block padding still clears the touch floor, and nowrap takes the width
     to about 75px, well past it on both axes. */
  .section-head .see-all,
  .vids-head .see-all,
  .vids-empty .see-all,
  a.see-all {
    padding: 13px 10px;
    margin: -13px -10px;
    white-space: nowrap;
    flex: none;
  }

  /* Editorial strip "See all" (v6). T2.5's rule, kept as written - it lands
     and the census confirms it: 3 offenders without it, 0 with. */
  :root[data-v6="on"] .v6-strip-all {
    padding: 13px 3px;
    margin: -13px -3px;
  }

  /* "Why you're seeing this", 135x18 (store-v6-rec.css:42), and the listing
     name in a compare row, 296x18. Same specificity as the base rules and
     later in the cascade, so the padding longhand beats their `padding: 0`
     shorthand. */
  :root[data-v6="on"] .v6-rec-why,
  :root[data-v6="on"] .v6-compare-name {
    padding-block: 13px;
    margin-block: -13px;
  }

  /* The quality card's "See Full Report" link, 42x68 - two pixels short on
     width, which is the kind of thing only a census finds. */
  .q-side a {
    padding-inline: 2px;
    margin-inline: -2px;
  }

  /* Search route's filter disclosure, 49x18 (app.js:2694, no CSS of its
     own). T2.3's disclosure button is `.v9-browse-filters-toggle` and a
     different control; this one is the search page's. */
  .search-tools .filters-toggle {
    padding-block: 13px;
    margin-block: -13px;
  }

  /* The saved-card remove button, 24x24. T2.5's rule, kept: content-box is
     correct here because nothing more specific sets this button's padding,
     so the box really does grow, and the census confirms it (1 offender
     without, 0 with). */
  button.sc-x {
    box-sizing: content-box;
    padding: 10px;
    margin: -10px;
  }
}
