/* ============================================================
   Hidden Temple - set-page "composition" redesign (shared)
   ------------------------------------------------------------
   Generalized from the approved Daiichi Pan sample
   (<style id="daiichi-redesign-v1">). Linked LAST on every set
   page, after banner.css and mobile.css, so it wins the cascade
   (with !important where the page's inline block or mobile.css
   would otherwise take it).

   Nothing in any page's markup is added, removed or reworded.
   This file only decides where the words sit, how large they are
   and what marks them - carrying the approved composition:

     - one shared page axis (1200px measure, 32px inset) that the
       masthead, both section marks and the grid all hang on,
       left-ranged rather than centred. 1200px is the site-wide
       grid width used by ~630 set pages (the sample's own value);
       a handful of 1100px grids sit only ~50px inside it, so the
       masthead still ranges left directly over the grid;
     - the eyebrow becomes an engraved SECTION MARK: a short heavy
       bronze rule, the words in Plex Mono, then a stacked
       double-rule running out to the right edge;
     - Cinzel for the name, a Cormorant italic teal <em> for the
       descriptive part, a bronze drop-cap opening the standfirst;
     - three type voices, three jobs - Cinzel names, Cormorant
       prose, Plex Mono labels;
     - hover in which nothing moves: a bronze rule draws in - no
       lift, no scale, no shadow.

   SCOPING
   -------
   * Every body-level selector is prefixed
       html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page)
     so the three bespoke pages (Hyper Sticker Collection 1 and the
     two Topsun 3 pages) stay completely untouched even if the link
     is present.
   * The card restyle targets .set-tile:not(.pack-art-tile) only, so
     pack-art / product-shot tiles keep their .ph-f/.ph-b photo-slot
     layout; only standard grid tiles become engraved plates.
   ============================================================ */

:root {
  --dc-max: 1200px;
  --dc-inset: 32px;
  --dc-bronze: #d9b877;
  --dc-teal: #bfeeea;
  --dc-ink: #b9c8c6;
  --dc-rule: rgba(139, 115, 68, 0.34);
  --dc-rule-strong: rgba(139, 115, 68, 0.56);
}

/* ---------- 1. the shared page axis + masthead ---------- */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head {
  max-width: var(--dc-max) !important;
  margin: 0 auto !important;
  padding: clamp(10px, 1.6vw, 18px) var(--dc-inset) clamp(26px, 3.2vw, 38px) !important;
  text-align: left !important;
  position: relative;
  z-index: 2;
}

/* the back-link: a quiet Plex Mono label with a rule that draws
   in on hover - it never boxes itself in */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .relics-back {
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
  font-family: 'IBM Plex Mono', monospace !important;
  font-size: 10px !important;
  letter-spacing: 0.3em !important;
  text-transform: uppercase !important;
  color: #8a9896 !important;
  text-decoration: none !important;
  margin: 0 0 clamp(18px, 2.2vw, 26px) !important;
  padding: 5px 0 !important;
  border: 0 !important;
  position: relative !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .relics-back::after {
  content: '' !important;
  position: absolute !important;
  left: 0 !important;
  bottom: 0 !important;
  width: 100% !important;
  height: 1px !important;
  background: linear-gradient(90deg, #c9a968, rgba(201, 169, 104, 0.05)) !important;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.4s cubic-bezier(0.22, 0.8, 0.3, 1) !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .relics-back:hover {
  color: var(--dc-teal) !important;
  border-color: transparent !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .relics-back:hover::after { transform: scaleX(1); }

/* the eyebrow becomes the engraved section mark:
   short heavy rule -> the words -> stacked double rule to edge */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .eyebrow {
  display: flex !important;
  align-items: center !important;
  gap: clamp(11px, 1.3vw, 18px) !important;
  font-family: 'IBM Plex Mono', monospace !important;
  font-size: 13px !important;
  font-weight: 500 !important;
  letter-spacing: 0.42em !important;
  text-transform: uppercase !important;
  color: var(--dc-bronze) !important;
  margin: 0 0 clamp(16px, 2vw, 22px) !important;
  line-height: 1.35 !important;
  white-space: normal !important;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.9) !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .eyebrow::before {
  content: '' !important;
  flex: none !important;
  width: clamp(20px, 2.6vw, 38px) !important;
  height: 2px !important;
  margin: 0 !important;
  background: var(--dc-bronze) !important;
  font-size: 0 !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .eyebrow::after {
  content: '' !important;
  flex: 1 1 auto !important;
  height: 7px !important;
  margin: 0 !important;
  font-size: 0 !important;
  background:
    linear-gradient(90deg, var(--dc-rule-strong), rgba(139, 115, 68, 0.06)) top left / 100% 1px no-repeat,
    linear-gradient(90deg, rgba(139, 115, 68, 0.30), rgba(139, 115, 68, 0.03)) bottom left / 100% 1px no-repeat !important;
}

/* the name: Cinzel, with the descriptive part in Cormorant italic teal */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .page-title {
  font-family: 'Cinzel', serif !important;
  font-weight: 900 !important;
  font-size: clamp(26px, 3.4vw, 40px) !important;
  line-height: 0.98 !important;
  letter-spacing: 0.02em !important;
  color: #e6efed !important;
  margin: 0 0 clamp(16px, 2vw, 22px) !important;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.9) !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .page-title em {
  font-family: 'Cormorant Garamond', serif !important;
  font-style: italic !important;
  font-weight: 400 !important;
  color: var(--dc-teal) !important;
  text-shadow: 0 0 46px rgba(109, 181, 176, 0.28) !important;
}

/* the standfirst: Cormorant prose, opened by a bronze drop-cap */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .page-sub {
  font-family: 'Cormorant Garamond', serif !important;
  font-size: clamp(15px, 1.15vw, 18px) !important;
  line-height: 1.5 !important;
  font-weight: 500 !important;
  color: #d5e0de !important;
  max-width: 66ch !important;
  margin: 0 !important;
  text-align: left !important;
  text-wrap: pretty;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .page-sub::first-letter {
  float: left;
  font-family: 'Cinzel', serif;
  font-weight: 900;
  font-size: 2.3em;
  line-height: 0.82;
  margin: 0.05em 0.16em 0 0;
  color: var(--dc-bronze);
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.95), 0 0 30px rgba(201, 169, 104, 0.20);
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .page-sub strong {
  color: var(--dc-bronze) !important;
  font-weight: 600 !important;
}

/* ---------- 2. meta-badges -> engraved chips ---------- */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .meta-badges {
  display: flex !important;
  flex-wrap: wrap !important;
  justify-content: flex-start !important;
  gap: 8px !important;
  margin-top: clamp(16px, 2vw, 22px) !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .meta-badges .meta-badge {
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
  padding: 6px 12px !important;
  border: 1px solid var(--dc-rule) !important;
  border-radius: 0 !important;
  background: rgba(10, 20, 22, 0.55) !important;
  font-family: 'IBM Plex Mono', monospace !important;
  font-size: 10px !important;
  letter-spacing: 0.22em !important;
  text-transform: uppercase !important;
  color: #8a9896 !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .meta-badges .meta-badge .k { color: var(--dc-bronze) !important; }
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .meta-badges .meta-badge .v { color: var(--dc-teal) !important; font-weight: 600 !important; }

/* ---------- 3. section headers -> engraved section marks ---------- */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sticker-head {
  max-width: var(--dc-max) !important;
  margin: clamp(36px, 4.5vw, 56px) auto clamp(14px, 1.8vw, 20px) !important;
  padding: 0 var(--dc-inset) !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sticker-head h2 {
  display: flex !important;
  align-items: center !important;
  gap: clamp(11px, 1.3vw, 18px) !important;
  font-family: 'IBM Plex Mono', monospace !important;
  font-weight: 500 !important;
  font-size: 13px !important;
  letter-spacing: 0.32em !important;
  text-transform: uppercase !important;
  color: var(--dc-bronze) !important;
  padding: 0 !important;
  border: 0 !important;
  line-height: 1.35 !important;
  white-space: normal !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sticker-head h2::before {
  content: '' !important;
  flex: none !important;
  width: clamp(20px, 2.6vw, 38px) !important;
  height: 2px !important;
  background: var(--dc-bronze) !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sticker-head h2::after {
  content: '' !important;
  flex: 1 1 auto !important;
  height: 7px !important;
  background:
    linear-gradient(90deg, var(--dc-rule-strong), rgba(139, 115, 68, 0.06)) top left / 100% 1px no-repeat,
    linear-gradient(90deg, rgba(139, 115, 68, 0.30), rgba(139, 115, 68, 0.03)) bottom left / 100% 1px no-repeat !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sticker-head .sh-sub {
  font-family: 'IBM Plex Mono', monospace !important;
  font-size: 10px !important;
  letter-spacing: 0.22em !important;
  color: #8a9896 !important;
  text-transform: uppercase !important;
  margin-top: 8px !important;
}

/* ---------- 4. grid cards -> engraved plates, hover draws a rule ----------
   sharp corners, a thin bronze border, a dark fill; on hover
   nothing moves - a bronze rule draws in along the bottom edge.

   SCOPE (two selector forms, see below):
     F1  .set-tile:not(.pack-art-tile)
         - standard grid tiles: plain checklists AND families whose
           tiles carry per-sticker .ph-f/.ph-b photo slots
           (ensky / merlin / carddass etc.). These are NEVER given
           the pack-art-tile class by parent-pack-art.js.
     F2  .set-tile.pack-art-tile.has-parent-thumb
         - grid tiles that parent-pack-art.js enriched with an
           injected parent thumbnail (.set-tile-thumb) and tagged
           pack-art-tile + has-parent-thumb. This is EVERY tile on
           the approved Daiichi sample, so it must be engraved to
           match the signed-off look.

   What stays UNTOUCHED: the real product-shot tiles
   (.set-tile.pack-art-tile WITHOUT has-parent-thumb, i.e. the
   static .ph-f/.ph-b photo-slot product shots). Those live in the
   separate .pack-art section outside .sets-wrap, and the extra
   has-parent-thumb guard protects them even if one ever sits in a
   grid. This is a deliberate refinement of the sample's requested
   ":not(.pack-art-tile)": that literal form would have stripped the
   engraving from the entire Daiichi grid, because the sample page's
   tiles are all runtime pack-art-tiles. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sets-wrap .set-tile:not(.pack-art-tile),
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sets-wrap .set-tile.pack-art-tile.has-parent-thumb {
  position: relative !important;
  border: 1px solid var(--dc-rule) !important;
  border-radius: 0 !important;
  background: rgba(10, 20, 22, 0.5) !important;
  padding: 14px !important;
  overflow: hidden !important;
  transition: border-color 0.25s ease, background 0.3s ease, color 0.25s ease !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sets-wrap .set-tile:not(.pack-art-tile)::after,
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sets-wrap .set-tile.pack-art-tile.has-parent-thumb::after {
  content: '' !important;
  position: absolute !important;
  left: 0 !important;
  bottom: 0 !important;
  width: 100% !important;
  height: 2px !important;
  background: linear-gradient(90deg, var(--dc-bronze) 0%, rgba(201, 169, 104, 0.06) 100%) !important;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.42s cubic-bezier(0.22, 0.8, 0.3, 1) !important;
  z-index: 2 !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sets-wrap .set-tile:not(.pack-art-tile):hover,
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sets-wrap .set-tile.pack-art-tile.has-parent-thumb:hover {
  border-color: var(--dc-rule-strong) !important;
  background: rgba(15, 28, 30, 0.72) !important;
  transform: none !important;
  box-shadow: none !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sets-wrap .set-tile:not(.pack-art-tile):hover::after,
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sets-wrap .set-tile.pack-art-tile.has-parent-thumb:hover::after { transform: scaleX(1); }

/* ---------- 5. the checklist grid joins the page axis ----------
   The masthead, both section marks and the pack-art block all hang on the
   1200px measure above, but the numbered checklist did not: an auto-generated
   <style id="AUTO-checklist-width"> block on ~1430 pages releases .sets-wrap to
   max-width:none with a clamp(20px,2.5vw,48px) inset, so above ~1264px the grid
   ran full-bleed from x32 to x1568 while the h1 above it started at x345. Three
   competing left edges on one page.

   These two rules put the grid back on the shared axis, and the three bespoke
   pages stay exempt through the same html body:not(...) prefix as everything
   else here.

   About `:is(#ht-set-axis, .sets-wrap)`: 1146 of the 1431 AUTO blocks scope
   themselves by the section's id (`html body.<page> #<slug>-checklist`), which
   no id-free selector can out-rank however many classes it names. `:is()`
   takes the specificity of its most specific argument, so naming a sentinel id
   alongside the real class lifts these rules to (1,3,2) - above the AUTO
   block's (1,1,2) - while still matching on `.sets-wrap` alone. #ht-set-axis
   is not an element on any page and is not meant to become one; it exists only
   to carry that weight. The remaining 285 AUTO blocks use the plain
   `.sets-wrap` form and were already out-ranked.

   The column count has to come with it. The AUTO block asks for six columns
   above 1300px, which was already tight at full bleed (the two photo wells in
   a tile wrap onto separate lines rather than sitting side by side) and would
   be ~181px per tile inside a 1200px measure. Four columns give each tile
   ~276px on the axis - wider than the six-up tiles were before - so the change
   buys legibility as well as alignment. Widths below 1301px are untouched:
   there the viewport inset and the axis inset resolve within a few px of each
   other anyway. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) {
  max-width: var(--dc-max) !important;
  margin-left: auto !important;
  margin-right: auto !important;
  padding-left: var(--dc-inset) !important;
  padding-right: var(--dc-inset) !important;
}
@media (min-width: 1301px) {
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
  }
}

/* ---------- 6. the pack-art block names itself once ----------
   A .pack-art section prints its own heading ("Pack Art") and then a single
   product tile whose .sn / .snm carry the same words. Every page therefore
   hides that tile's labels in its own inline block - and mobile.css undid it
   below 600px with `.set-tile .snm{display:block !important}`, so phones got
   the heading twice: the eyebrow at the top of the block and a second, larger
   "Pack Art" sitting under the wells.

   Re-assert the page's intent, scoped two ways so it can only ever hit the
   duplicate: the section must already carry a .pack-art-head (no heading, no
   duplication, labels stay), and the tile must be a real product pack-art tile
   rather than a checklist tile that parent-pack-art.js tagged (those live in
   .sets-wrap, never in .pack-art). HSC1's promo-tile is excluded twice over -
   by the body prefix and by class. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .pack-art:has(> .pack-art-head) .set-tile.pack-art-tile:not(.promo-tile) > .sn,
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .pack-art:has(> .pack-art-head) .set-tile.pack-art-tile:not(.promo-tile) > .snm {
  display: none !important;
}

/* ---------- 7. a meta chip that holds a sentence reads as a note ----------
   The chips are built for a word or two ("Year: 1998"), but some pages put a
   whole sentence in one ("Distribution: Booster packs and lottery packs, 1
   promo holo with the Perfect Album 3"). Unwrapped, that chip ran ~900px on
   its own row at desktop and stacked four lines of centred pill at 390px.
   Cap the measure and let a long value wrap as prose inside the chip: short
   chips are shorter than the cap and do not move at all. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .meta-badges .meta-badge {
  max-width: min(100%, 420px) !important;
  align-items: flex-start !important;
  white-space: normal !important;
  line-height: 1.55 !important;
  text-align: left !important;
  padding: 7px 12px !important;
}
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .meta-badges .meta-badge .k {
  flex: none !important;
}

/* ---------- mobile: hold the grid's 18px inset, ease spacing ---------- */
@media (max-width: 600px) {
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head {
    padding-left: 18px !important;
    padding-right: 18px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sticker-head {
    padding-left: 18px !important;
    padding-right: 18px !important;
  }
  /* the checklist keeps the same 18px inset as the masthead and the section
     marks (mobile.css gives it 11px, which left the grid a few px outside
     every heading above it) */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) {
    padding-left: 18px !important;
    padding-right: 18px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .eyebrow {
    font-size: 11px !important;
    letter-spacing: 0.28em !important;
    gap: 10px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .sticker-head h2 {
    font-size: 11px !important;
    letter-spacing: 0.26em !important;
    gap: 10px !important;
  }
  /* A phone has no width to spare, and 0.22em between every letter of a
     sentence-length chip value is what turned it into a four-line slab. Close
     the tracking up for the value only: short chips are a word or two and
     barely move, a long one reads as a note. */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) .page-head .meta-badges .meta-badge .v {
    letter-spacing: 0.08em !important;
  }
}

/* ============================================================
   9. PHONES: the checklist plate at half height
   ------------------------------------------------------------
   A checklist tile measured 372-410px on a 390px phone: one card
   filled the screen and a 194-entry set ran 86 screens. The height
   was not the picture - it was everything around it. Two ~156px
   square wells, a ~50px strip reserved under each for the
   contributor credit, the item reference and the name on two
   full-width rows at 13/18px, a like row, and then a
   clamp(60px,16vw,70px) - 62px - dead band at the foot reserved for
   a 44px anvil icon that only needed the corner. Roughly 44 pages
   also pin their tiles to a min-height floor (352px is the common
   value in the astryx card blocks), so trimming content alone would
   have changed nothing on them.

   This block halves the plate: wells capped and centred in their
   columns, the credit strip cut to the line it holds, the reference
   chip shrunk to its words, the name at 15px, and the anvil icon
   moved into the like row's own band so the 62px reserve goes away.
   Everything an eye or a finger needs is kept - the anvil icon
   still carries a 44px hit area through a transparent ::after, and
   the like chip keeps the one it already had.

   SPECIFICITY
   -----------
   mobile.css's phone locks reach (0,9,1) and ~44 page blocks add
   their own !important floors, so these rules borrow the
   `:is(#ht-set-axis, .sets-wrap)` device documented in section 5:
   the sentinel id (which is on no page and is not meant to become
   an element) lifts every selector here into id territory, above
   both. It also scopes the whole block to the numbered checklist -
   pack-art and product-shot grids live outside .sets-wrap and are
   untouched.

   The three bespoke pages keep the same html body:not(...) prefix
   used by every other rule in this file, so HSC1 and the two
   Topsun 3 pages never see any of it.

   2026-08-26 outlier sweep: a handful of checklist pages hold their
   .sets-grid in a wrapper other than .sets-wrap, so this phone block
   never reached them and their tiles stayed 318-671px. The narrow,
   checklist-only wrappers are folded into the :is() list for THIS
   block only (not section 5's base rules nor section 10's tablet
   block, so >=601px is left exactly as it was): .intake-wrap
   (kakumen retsuden part 1/2) and .verified-list (kakumen retsuden
   kai 1/2). The playing-cards decks and amada-accessories carry a
   bare .sets-grid with no safe wrapper and are shrunk by their own
   page-scoped <slug>-shrink-20260826 blocks. Bear Walker COA
   (.coa-wrap) is deliberately left out: its own inline style records
   that the shared sheet was measured and rejected there because it
   collapses the landscape COA photo slots and truncates ~37 labels,
   so that page keeps its bespoke layout like the hsc1/tg3/tsg3 set.
   ============================================================ */
@media (max-width: 600px) {

  /* --- the grid: tiles sit closer together --- */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid {
    gap: 8px !important;
  }

  /* --- the plate: no artificial floor, tighter inset and rows --- */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile {
    /* one dial for every photo well on the plate; it tracks the
       viewport so a 600px phone is not left with capped wells and a
       lake of empty plate beside them */
    --tm-well: clamp(84px, 26vw, 150px);
    min-height: 0 !important;
    height: auto !important;
    padding: 6px 7px 8px !important;
    row-gap: 3px !important;
    column-gap: 6px !important;
  }
  /* the 62px band that only existed to hold a 44px icon */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile:has(.anvil-toggle.anvil-img) {
    padding-bottom: 8px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile.ht-anvil-pad {
    padding-right: 7px !important;
  }

  /* --- the wells: square, capped, centred in their column ---
     Capping the width rather than squashing the box keeps the well
     square, so a portrait card and a landscape sticker are both
     shown whole (background-size:contain) at the new height. Empty
     wells take exactly the same size as filled ones. */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-b,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f1,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f2,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .body > .ph-f,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .body > .ph-b {
    width: 100% !important;
    max-width: var(--tm-well) !important;
    height: auto !important;
    min-height: 0 !important;
    aspect-ratio: 1 / 1 !important;
    justify-self: center !important;
    margin-left: auto !important;
    margin-right: auto !important;
    margin-top: 0 !important;
    padding: 3px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-b.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f1.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f2.has-img {
    padding: 0 !important;
  }
  /* the strip under a filled well is the credit line, not a margin:
     one 10px line plus air, in place of clamp(48px,13vw,56px) */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-b.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f1.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f2.has-img {
    margin-bottom: 15px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f:not(.has-img),
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-b:not(.has-img),
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f1:not(.has-img),
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .ph-f2:not(.has-img) {
    margin-bottom: 0 !important;
  }

  /* --- captioned photo columns (the ht-card fp2/fp3/fp4 family) ---
     Front / 1st Back / 2nd Back sit in a single row of small wells;
     the caption becomes a label again rather than a headline. */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-cols {
    gap: 5px !important;
    margin-bottom: 0 !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-col {
    gap: 2px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-col > .ph-f,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-col > .ph-b {
    max-width: var(--tm-well) !important;
    height: auto !important;
    min-height: 0 !important;
    margin-bottom: 0 !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-cl {
    font-size: 8px !important;
    line-height: 1.15 !important;
    letter-spacing: 0.03em !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-meta {
    gap: 2px !important;
  }

  /* --- one contributor-credit voice, at label size --- */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .ht-credit,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .ph-f .ht-credit,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .ph-b .ht-credit,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-col > .ht-credit {
    font-size: 10px !important;
    line-height: 1.2 !important;
    min-height: 0 !important;
    padding: 1px 2px !important;
    letter-spacing: 0 !important;
  }

  /* --- the reference chip shrinks to its words --- */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .sn,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .num,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .body .sn,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-nl .sn {
    font-size: 10px !important;
    line-height: 1.2 !important;
    padding: 2px 6px !important;
    letter-spacing: 0.1em !important;
    width: auto !important;
    max-width: 100% !important;
    justify-self: start !important;
  }

  /* --- the name --- */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .snm,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .body .snm,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-nl .snm {
    font-size: 15px !important;
    line-height: 1.15 !important;
  }

  /* --- the type / print pill and any Japanese line --- */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .sty,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .jp,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .body .sty,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .body .jp,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-type {
    font-size: 9px !important;
    line-height: 1.25 !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid > .set-tile > .body {
    gap: 3px !important;
    margin-top: 0 !important;
  }

  /* --- the like chip and the anvil share one band at the foot ---
     The chip keeps the invisible ::after that already grows it to a
     44px target; the row simply reserves the corner the icon sits in. */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .ht-like-row {
    margin-top: 1px !important;
    padding-right: 40px !important;
    min-height: 26px !important;
    align-items: center !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .ht-like-chip {
    font-size: 10px !important;
    letter-spacing: 0.06em !important;
    padding: 3px 8px !important;
    min-height: 22px !important;
    gap: 5px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .ht-like-chip .ht-like-heart {
    font-size: 11px !important;
  }

  /* the anvil icon reads at 30px and is hit at 44px */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .anvil-ctl .anvil-toggle.anvil-img.anvil-img {
    width: 30px !important;
    height: 30px !important;
    min-width: 30px !important;
    min-height: 30px !important;
    padding: 1px !important;
    right: 6px !important;
    bottom: 6px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .anvil-ctl .anvil-toggle.anvil-img.anvil-img::after {
    content: '' !important;
    position: absolute !important;
    inset: -7px !important;
  }

  /* --- the "+ Photo" invitation, sized for the smaller well ---
     On TCG pages the well already holds the official card scan and the
     button sits over its foot, so at 44px it would have covered nearly
     half the art once the well came down to ~100px. 36px keeps a
     comfortable thumb target and gives the card back its face. */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not([class*="karuta-"]) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .ht-addphoto {
    font-size: 10px !important;
    min-height: 36px !important;
    width: min(100%, 86px) !important;
    padding: 5px 2px !important;
    letter-spacing: 0.04em !important;
    line-height: 1.1 !important;
  }
}

/* ---------- 10. small tablets / narrow windows (601-760px) ----------
   The phone block stops at 600px, and above it the same ~44 page
   min-height floors were holding a 2-up tile at 357px around an 85px
   pair of wells - most of the plate was reserved emptiness. Release
   the floor and close the rows up; the wells are already trimmed to
   100px here by ht-set-grid.css, so they are left alone. */
@media (min-width: 601px) and (max-width: 760px) {
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile {
    min-height: 0 !important;
    height: auto !important;
    padding: 10px 10px 12px !important;
    row-gap: 6px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile > .snm,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile > .body .snm {
    font-size: 17px !important;
    line-height: 1.2 !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid .set-tile .ht-credit {
    font-size: 10px !important;
    line-height: 1.2 !important;
    min-height: 0 !important;
  }
  /* 44px was reserved under every filled well for a caption that is one
     10px line tall */
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile > .ph-f.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile > .ph-b.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile > .ph-f1.has-img,
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile > .ph-f2.has-img {
    margin-bottom: 18px !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile > .ph-f:not(.has-img),
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap) .sets-grid > .set-tile > .ph-b:not(.has-img) {
    margin-bottom: 0 !important;
  }
}

/* ============================================================
   11. EMPTY / LOADING PHOTO-WELL PLACEHOLDER  (shared)
   ------------------------------------------------------------
   Kills the "wall of black empty tiles". A photo well with no
   photo yet used to be a flat near-black void; every genuinely
   empty or still-loading well now reads as a mounted, empty plate
   - a subtle teal / near-black mat (the same tone filled wells use
   behind a letterboxed photo, HT_PHOTO_MAT) with a faint centred
   temple (torii) mark, and, WHILE a photo is actively loading, a
   soft bronze shimmer sweep.

   STATE MODEL (judged entirely from markup the producers set, so
   no page needs editing):
     - painted photo        -> .ph-*.has-img (neither ph class)
                               : the real photo, no placeholder.
     - deferred, queued but
       not yet painted      -> .ph-*.has-img.ht-ph-load
                               (banner-anvil-cart.js htLazyPaint adds it,
                                htPaintSlot drops it) : STATIC mat +
                                ghost, no animation - so a set with
                                hundreds of below-the-fold wells never
                                runs hundreds of shimmers.
     - actively downloading -> .ph-*.has-img.ht-ph-fetch
                               (htPaintSlot adds it while the real bytes
                                load, and clears it when the <img> decodes
                                or fails) : mat + ghost + shimmer sweep.
     - genuine empty void   -> .ph-*:not(.has-img) with no injected
                               image and no "+ Photo" button
                               : mat + ghost, no shimmer.
     - "+ PHOTO" affordance  -> .ph-*:not(.has-img):has(.ht-addphoto)
                               : gets the SAME quiet mat + ghost so it
                               is no longer a black void, but the "+
                               Photo" button is never removed, hidden,
                               or obscured - it keeps sitting clearly
                               on top, so the contributor affordance is
                               fully preserved (only the black fill
                               behind it changes). The active shimmer is
                               reserved for genuinely loading wells, so
                               a +photo slot never animates.
     - inline fallback art   -> .ph-*:has(img) (e.g. the TCG
                               pokemontcg.io .ht-apifb card scan on
                               Crown Zenith) : LEFT UNTOUCHED - it
                               already shows art, it is not a void.

   SCOPE: standard grid tiles only (.set-tile:not(.pack-art-tile)),
   never the bespoke hand-drawn pages (hsc1 / tg3 / tsg3 - the Topsun
   puzzle wells each paint a slice of ONE image, so a ghost there
   would be wrong) and never the decochara pokedex checklist, which
   frames and paints its own wells. Reduced-motion drops the shimmer
   and leaves only the static ghost.
   ============================================================ */

/* one place for the three background pieces; defining them on every
   well is inert until a state rule below actually paints them. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not(.decochara-pokedex-page)
  .set-tile:not(.pack-art-tile) :is(.ph-f, .ph-b, .ph-f1, .ph-f2) {
  --ht-ph-mat: linear-gradient(160deg, rgba(22, 40, 42, 0.90), rgba(9, 19, 21, 0.96));
  --ht-ph-mark: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 100 100%27%3E%3Cg fill=%27none%27 stroke=%27%23c9a968%27 stroke-opacity=%270.15%27 stroke-width=%276%27 stroke-linecap=%27round%27 stroke-linejoin=%27round%27%3E%3Cpath d=%27M13 32 H87%27/%3E%3Cpath d=%27M21 46 H79%27/%3E%3Cpath d=%27M31 32 V80%27/%3E%3Cpath d=%27M69 32 V80%27/%3E%3C/g%3E%3C/svg%3E");
  --ht-ph-shimmer: linear-gradient(100deg, rgba(201, 169, 104, 0) 40%, rgba(201, 169, 104, 0.13) 50%, rgba(201, 169, 104, 0) 60%);
}

/* JOB 2 - reserve the box before the image lands. A defensive square
   fallback: wells that already carry an explicit height (nearly all,
   on desktop) keep it because a set height wins over aspect-ratio; a
   well left at auto height gets a reserved square so the grid never
   reflows as async photos arrive. No !important, so no page is
   overridden. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not(.decochara-pokedex-page)
  .set-tile:not(.pack-art-tile) > :is(.ph-f, .ph-b, .ph-f1, .ph-f2) {
  aspect-ratio: 1 / 1;
}

/* Empty well (a genuine void OR a "+ Photo" slot): mat + ghost, no shimmer
   (it is not loading). Wells that already carry inline fallback art - the
   TCG API card scan (.ht-apifb) - are excluded with :not(:has(img)); they
   are not voids. The "+ Photo" button, when present, is a child that keeps
   painting on top of this background untouched. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not(.decochara-pokedex-page)
  .set-tile:not(.pack-art-tile) :is(.ph-f, .ph-b, .ph-f1, .ph-f2):not(.has-img):not(:has(img)) {
  background-image: var(--ht-ph-mark), var(--ht-ph-mat) !important;
  background-repeat: no-repeat !important;
  background-position: center, center !important;
  background-size: 44% auto, cover !important;
}

/* Deferred (queued, below the fold): the SAME static mat + ghost as an
   empty well, so a not-yet-painted photo slot is never a black void while
   the visitor scrolls toward it. No animation - hundreds of these can exist
   at once on a big set. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not(.decochara-pokedex-page)
  .set-tile:not(.pack-art-tile) :is(.ph-f, .ph-b, .ph-f1, .ph-f2).ht-ph-load {
  background-image: var(--ht-ph-mark), var(--ht-ph-mat) !important;
  background-repeat: no-repeat !important;
  background-position: center, center !important;
  background-size: 44% auto, cover !important;
}

/* Actively downloading: the same mat + ghost, plus the bronze shimmer
   sweep on top. htPaintSlot clears .ht-ph-fetch the instant the photo
   decodes, so only the handful of wells genuinely fetching at once
   animate, and the real photo then replaces the placeholder cleanly. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not(.decochara-pokedex-page)
  .set-tile:not(.pack-art-tile) :is(.ph-f, .ph-b, .ph-f1, .ph-f2).ht-ph-fetch {
  background-image: var(--ht-ph-shimmer), var(--ht-ph-mark), var(--ht-ph-mat) !important;
  background-repeat: no-repeat !important;
  background-position: 150% 0, center, center !important;
  background-size: 200% 100%, 44% auto, cover !important;
  animation: ht-ph-shimmer 1.35s ease-in-out infinite !important;
}
@keyframes ht-ph-shimmer {
  0%   { background-position: 150% 0, center, center; }
  100% { background-position: -150% 0, center, center; }
}

/* Soft fade as the real photo (the SEO <img class="ph-img">) arrives
   over the retained plate mat, so the placeholder does not snap. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not(.decochara-pokedex-page)
  .set-tile:not(.pack-art-tile) :is(.ph-f, .ph-b, .ph-f1, .ph-f2) > img.ph-img {
  animation: ht-ph-imgin 0.45s ease both;
}
@keyframes ht-ph-imgin { from { opacity: 0; } to { opacity: 1; } }

/* Reduced motion: no shimmer, no fade - just the static ghost. The
   shimmer highlight is parked off the well so no bright band is frozen
   mid-sweep. */
@media (prefers-reduced-motion: reduce) {
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not(.decochara-pokedex-page)
    .set-tile:not(.pack-art-tile) :is(.ph-f, .ph-b, .ph-f1, .ph-f2).ht-ph-fetch {
    animation: none !important;
    background-position: 150% 0, center, center !important;
  }
  html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page):not(.decochara-pokedex-page)
    .set-tile:not(.pack-art-tile) :is(.ph-f, .ph-b, .ph-f1, .ph-f2) > img.ph-img {
    animation: none !important;
  }
}

/* ============================================================
   12. LABEL CONTAINMENT  (shared, every width)   2026-08-26
   ------------------------------------------------------------
   Two label boxes are capped to the box they belong to - the
   "+ Photo" chip inside a captioned photo column is held to
   max-width:calc(100% - Npx) of its slot, and the .fp-cl print
   caption is as wide as the column it labels - yet both were
   also set white-space:nowrap. The words were then wider than
   the box that draws their border: "+ Photo" crossed the
   chip's own border on both sides, and "1st Print" ran out of
   its plate into the next column's caption, so the row read
   "1ST PRINT2ND PRINT".
   Allowing them to wrap is containment only. A label that
   already fits is unaffected - nowrap and normal render the
   same when there is room - and a label that does not fit
   takes a second line INSIDE its own box. No tile, well, grid
   or column changes size, and the three bespoke pages keep
   their own rules.
   Deliberately NOT applied to the plain `.ph-f > .ht-addphoto`
   chip: that one is auto-width and hangs under its well, where
   wrapping would break a line that fits today.
   ============================================================ */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-col .ht-addphoto,
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(#ht-set-axis, .sets-wrap, .intake-wrap, .verified-list) .sets-grid .set-tile .fp-cl {
  white-space: normal !important;
}

/* Same fault, second home: on the product-shot and pack-art bands the
   generated page blocks seat the chip INSIDE the well with
   width:max-content capped by max-width:100%, and pin white-space:nowrap
   at (0,11,2). On a narrow phone well the cap bites and "+ Photo" paints
   past the chip's border and the well's. width:max-content means a chip
   with room still never wraps, so this only ever acts where the cap bites.
   The repeated class is the house trick (see .anvil-img.anvil-img above)
   for outranking those page blocks without inventing a page id. */
html body:not(.hsc1-page):not(.tg3-page):not(.tsg3-page) :is(section.sticker-head, .pack-art) .sets-grid .set-tile :is(.ph-f, .ph-b, .ph-f1, .ph-f2) .ht-addphoto.ht-addphoto.ht-addphoto.ht-addphoto {
  white-space: normal !important;
}
