/** Shopify CDN: Minification failed

Line 3639:51 Unexpected "*"
Line 3643:76 Unterminated string token

**/
/* ==========================================================================
   Vellatini design tokens + type register
   ==========================================================================
   Source of truth: plans/260823-1055-vellatini-theme-port/research/
     spec-10-brand-token-sheet.md (colors, type register, component laws)
     spec-16-section-setup-sheet.md ch.0 (shared components, spacing tokens)

   Hooked in layout/theme.liquid immediately AFTER theme-styles-variables /
   color-palette so --vt-* tokens can layer on top of Horizon's :root sheet.
   Additive only — never edit theme-styles-variables.liquid or
   color-palette.liquid (spec-12 §4.3).

   Breakpoint: mobile-first. Base rules below are the 390 artboard values;
   `@media (min-width: 990px)` overrides to the 1440 artboard values, per
   Horizon's own structural breakpoint (assets/base.css:55 — the same point
   where .page-wrapper becomes the scroll container and the header collapses
   from drawer to full-row mode), so the type register changes hands at the
   same viewport as the rest of the chrome.
   ========================================================================== */

/* Jost 300/400/500 — the boards register (spec-10 §2, supersedes the
   Marcellus/Inter homepage-only register per authority rule, F1).
   Not wired through Shopify's font_picker: font_picker font IDs cannot be
   verified against Shopify's live font library from this environment, so
   Jost is loaded independently here via Google Fonts so every Vellatini
   utility class below renders correctly regardless of what settings_data's
   type_body_font/type_heading_font resolve to. settings_data.json is still
   pointed at jost_n3/jost_n4 as a best-effort match (see phase-01 report) —
   if Shopify's font_picker doesn't carry Jost, only dormant/stray Horizon-
   native blocks using --font-body--family etc. are affected, never the
   classes in this file. Follow-up: replace this @import with true
   self-hosted woff2 files under assets/ once the binaries are sourced. */
/* @import removed (code-review M1, 2026-08-23): Jost IS in Shopify's font
   library — settings_data's jost_n3/jost_n4 make Shopify's CDN serve the
   family with proper preloads via snippets/fonts.liquid; the Google embed
   was a duplicate origin, a render-blocking chain, and a GDPR exposure
   (visitor IPs to Google). If font_picker resolution ever fails on this
   store, restore Jost via self-hosted woff2 under assets/, never the
   Google embed. */

:root {
  /* ---- color · grounds & plates (spec-10 §1) ---- */
  /* --vt-canvas is the mock-artboard surround only — never use inside a
     rendered section; every designed surface sits on --vt-page. */
  --vt-canvas: #e9e7e3;
  --vt-page: #f7f1e8;
  --vt-ground: #f8f1e7; /* packshot tiles — object-fit: contain only, never cover */
  --vt-plate: #e4dcd1; /* editorial/lifestyle plates — cover-cropping legal here only */
  --vt-footer: #f2ebdf; /* PDP footer tile, the only footer in the corpus */

  /* ---- color · text & ink ---- */
  --vt-ink: #141210;
  --vt-body: #55504a;
  --vt-taupe: #8a7968;
  --vt-accent: #7b4423; /* buy-path links only (PDP/homepage) — never on boards nav pages */
  --vt-muted: #a99c8c; /* struck prices, counts, whispers */
  --vt-placeholder: #c8bcad;
  --vt-separator: #c9bfb2;

  /* ---- color · functional hairline ladder (spec-10 §1a) ---- */
  --vt-scrim: rgba(20, 18, 16, 0.32); /* search-overlay veil */
  --vt-hair-structural: rgba(20, 18, 16, 0.14); /* cart item rows */
  --vt-hair-accordion: rgba(20, 18, 16, 0.16); /* PDP accordion rules */
  --vt-hair-soft: rgba(20, 18, 16, 0.1); /* attach/offer row top rules */
  --vt-rule-strong: rgba(20, 18, 16, 0.55); /* searchline underline, active tab, selected-swatch outline */
  --vt-dot-inactive: rgba(20, 18, 16, 0.25); /* PDP mobile pager dots */
  --vt-underline-quietlink: rgba(20, 18, 16, 0.45);
  --vt-underline-hairlink: rgba(123, 68, 35, 0.4); /* also .attach-add */
  --vt-underline-txtlink: rgba(123, 68, 35, 0.35);
  --vt-underline-taupe: rgba(138, 121, 104, 0.5); /* .iqty a (Remove/Add) */
  --vt-underline-taupe-soft: rgba(138, 121, 104, 0.35); /* drawer meta links */
  --vt-underline-newsletter: rgba(20, 18, 16, 0.3); /* footer email field */

  /* ---- type ---- */
  --vt-font: 'Jost', sans-serif;
  /* Type scale + weight ladder (owner 2026-09-07, Lark "Website Improvements"
     Part 4: "+10% size, ~+20% visual weight, everything else unchanged").
     Every px font-size in the Vellatini register is authored as
     calc(<spec px> * var(--vt-ts)) and every weight as one of these two
     tokens, so the whole site retunes from this one block. Spec values stay
     readable in the rules below; 1 / 300 / 400 restores the boards register. */
  --vt-ts: 1.1;
  --vt-w-light: 400; /* was 300 */
  --vt-w-regular: 500; /* was 400 */

  /* ---- spacing constants (spec-10 §5 / spec-16 ch.0) ---- */
  --vt-artboard-d: 1440px;
  --vt-artboard-m: 390px;
  --vt-drawer-width: 480px;
  --vt-margin-d: 56px;
  --vt-margin-m: 20px; /* structural (headers, image grids) */
  --vt-margin-m-text: 24px; /* text sections */
  --vt-gutter-d: 8px;
  --vt-gutter-m: 6px;
  --vt-row-gap-d: 40px;
  --vt-row-gap-m: 22px; /* utility + ads pages */
  --vt-row-gap-m-lp: 26px; /* Debut LP — intentionally different, spec-16 G14 */
  --vt-cta-pad-inline: 17px 54px;
  --vt-cta-pad-block: 17px 0;
}

/* ==========================================================================
   Base reset — the canvas default-blue trap (spec-10 §6 law 8)
   :where() keeps this at zero specificity so any Horizon-native component
   style (which already sets its own color via CSS custom properties) wins
   without a specificity fight; it only catches anchors nobody else colored.
   ========================================================================== */
:where(.vt-hd a),
:where(.quietlink, .filterlink, .hairlink, .attach-add, .txtlink, .tab, .cta, .dw-cta, .dw-add) {
  text-decoration: none;
  color: inherit;
}

/* ==========================================================================
   SC-1 · Product card grammar — tile, packshot, caption
   ========================================================================== */
.ground {
  background-color: var(--vt-ground);
}

.plate {
  background-color: var(--vt-plate);
}

.cell-pack {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  aspect-ratio: 3 / 4;
}

.caption {
  text-align: center;
  padding-top: 11px;
}

.cap-name,
/* Horizon's native product-title block (spec-13 restyle-in-place ruling —
   the shared card is Horizon's own chain, wired via stable structural
   selectors rather than a fork; ref="productTitleLink" is the theme's own
   markup contract, safe to hang CSS on). */
.product-card__content a[ref='productTitleLink'] p {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9.5px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-ink);
  margin: 0;
}

.cap-mat {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(8px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  margin-top: 6px;
}

.cap-price,
.product-card__content product-price .price,
.product-card__content product-price .price-item__group.price {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.1em;
  color: var(--vt-ink);
  font-variant-numeric: tabular-nums;
  margin-top: 5px;
}

/* PDP buy-box / related-card context runs price in taupe at a wider tracking
   — a deliberate second token, not a unification bug (spec-10 §9 F3). Wired
   two ways: the class itself (available for any future consumer that can add
   a literal class) AND an ancestor-scoped selector onto Horizon's native
   <product-price> element inside the buy box (`.pdp-bb`, blocks/_product-details.liquid)
   — the native price block has no custom-class setting, so this is how the
   PDP buy-box price (spec-16 5.3: D 12/0.12em, M 11/0.12em) gets the token
   without forking blocks/price.liquid. */
.cap-price--pdp,
.pdp-bb product-price,
.pdp-bb product-price .price,
.pdp-bb product-price .price-item__group.price {
  color: var(--vt-taupe);
  font-size: calc(11px * var(--vt-ts, 1));
  letter-spacing: 0.12em;
}

.pdp-bb product-price {
  display: block;
  margin-top: 14px;
}

@media (min-width: 990px) {
  .cap-price--pdp,
  .pdp-bb product-price,
  .pdp-bb product-price .price,
  .pdp-bb product-price .price-item__group.price {
    font-size: calc(12px * var(--vt-ts, 1));
  }

  .pdp-bb product-price {
    margin-top: 18px;
  }
}

.cap-was,
/* Struck price — ads-surface only (spec-04 §5.1 concern #1: the offer
   register is ads-only; organic collection/material/story walls never show
   compare-ats even though every SKU carries one). Gate lives in
   snippets/product-card.liquid (template.suffix check) via the
   .product-card--ads modifier; hidden by default just below. */
product-card.product-card--ads .product-card__content product-price .compare-at-price {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.08em;
  color: var(--vt-muted);
  text-decoration: line-through;
  font-variant-numeric: tabular-nums;
  margin-left: 6px;
}

.product-card__content product-price .compare-at-price {
  display: none;
}

product-card.product-card--ads .product-card__content product-price .compare-at-price {
  display: inline;
}

@media (min-width: 990px) {
  .cell-pack {
    aspect-ratio: 3 / 4;
  }

  .caption {
    padding-top: 14px;
  }

  .cap-name,
  .product-card__content a[ref='productTitleLink'] p {
    font-size: calc(10.5px * var(--vt-ts, 1));
    letter-spacing: 0.24em;
  }

  /* PDP variant runs one step larger/wider — keep both (spec-10 §9 F4). */
  .cap-name--pdp {
    font-size: calc(11px * var(--vt-ts, 1));
    letter-spacing: 0.3em;
  }

  .cap-mat {
    font-size: calc(9px * var(--vt-ts, 1));
    letter-spacing: 0.16em;
  }

  .cap-price,
  .product-card__content product-price .price,
  .product-card__content product-price .price-item__group.price {
    font-size: calc(11px * var(--vt-ts, 1));
    letter-spacing: 0.1em;
    margin-top: 6px;
  }

  .cap-was,
  product-card.product-card--ads .product-card__content product-price .compare-at-price {
    font-size: calc(10px * var(--vt-ts, 1));
    letter-spacing: 0.08em;
    margin-left: 8px;
  }
}

/* ==========================================================================
   SC-1b · Card wiring — connects the SC-1 caption grammar above to Horizon's
   native `_product-card` chain (product-title + price theme blocks) and adds
   the material line, which has no native block (spec-13 §3 the material-dots
   ruling is PDP-only; here it's a plain metafield read). Everything below is
   structural (layout/order/visibility), not typography — the type rules stay
   in SC-1 so a single edit there repaints every consumer (Phase 2 grids
   included, per phase-03 handoff — this file is the shared substrate).
   ========================================================================== */
product-card .product-card__content.product-grid__card {
  /* stretch, not center: the flex children are blockified, so text-align
     handles caption centering; align-items:center shrink-wraps the auto-width
     .card-gallery to 0px and collapses every tile image on every grid. */
  align-items: stretch;
  text-align: center;
}

/* Horizon's text/price blocks add `text-{alignment}` (default "left"); the
   card grammar is always centered regardless of the per-instance block
   setting inherited from either template — override at equal-or-higher
   specificity instead of relying on editors to flip every block's alignment
   setting by hand across every section that renders this card. */
.product-card__content .text-left {
  text-align: center;
}

.product-card__content a[ref='productTitleLink'] {
  order: 1;
}

/* Owner 2026-09-07 (Lark "Website Improvements" Part 2): Horizon's text block
   caps the title <p> at `max-inline-size: min(100%, var(--max-width))`
   (341px for the "normal" width setting). Inside the stretch flex column the
   capped block sits at the left edge, so on any card wider than ~341px
   (≥1700 viewports, 4-up walls) the name read ~6px left of the material and
   price lines. Uncapped, all three lines share the card centre. */
.product-card__content a[ref='productTitleLink'] p {
  max-inline-size: none;
  width: 100%;
}

.product-card__content .cap-mat {
  order: 2;
}

.product-card__content product-price {
  order: 3;
  display: block;
  margin-top: 0;
}

/* code-review M6: `product_card_gap: 0` on the merchandised wall (main-
   collection) and the Leather Stories shop strip leaves the packshot tile
   flush against the caption below it; SC-1 wants 11px mobile / 14px desktop
   of clearance there. Scoped to those two consumers only — the homepage
   index grids (vt_convertible_grid / vt_slg_grid) own their own spacing via
   the H2 counter-overrides in sections/vellatini-home-hero.liquid and must
   not pick this up. */
/* .product-grid__card doubled to (0,3,0): the stock bundle's own doubled-class
   rule `.product-grid__card.product-grid__card { padding-block… }` loads after
   this file and ties a two-class selector — the caption clearance never applied. */
.vt-wall .product-card__content.product-grid__card,
.vt-story-strip__grid .product-card__content.product-grid__card {
  padding-top: 11px;
}

@media (min-width: 990px) {
  .vt-wall .product-card__content.product-grid__card,
  .vt-story-strip__grid .product-card__content.product-grid__card {
    padding-top: 14px;
  }
}

/* ==========================================================================
   Grid primitives — the merchandised wall (spec-04 §1 `.grid4`) + its mobile
   derivation (spec-16 ch.2 `.grid2`, gap 6/rows mt 22). Structural, so they
   live here rather than per-section stylesheets: Collection A, the four
   material pages, and every Leather Stories shop strip all consume both.
   ========================================================================== */
.grid4 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--vt-row-gap-m) var(--vt-gutter-m);
  /* consumers include <ul> walls (LP family walls) — kill markers/indent */
  list-style: none;
  margin: 0;
  padding-left: 0;
}

.grid4 > li {
  list-style: none;
}

@media (min-width: 990px) {
  .grid4 {
    grid-template-columns: repeat(4, 1fr);
    gap: var(--vt-row-gap-d) var(--vt-gutter-d);
  }
}

/* `.product-grid.vt-wall` — forces Horizon's native product-grid (main-
   collection settings `vt_wall_mode`) onto the exact spec-04 geometry
   instead of its own auto-fill card-size sizing. Two chained classes
   (specificity 0,2,0) beat product-grid.liquid's own `.product-grid` rule
   (0,1,0) regardless of {% stylesheet %} bundling order — no !important
   (dev-rules ban on cascade traps). */
.product-grid.vt-wall {
  grid-template-columns: repeat(2, 1fr);
  gap: var(--vt-row-gap-m) var(--vt-gutter-m);
}

@media (min-width: 990px) {
  .product-grid.vt-wall {
    grid-template-columns: repeat(4, 1fr);
    gap: var(--vt-row-gap-d) var(--vt-gutter-d);
  }
}

/* ==========================================================================
   Tab row — taxonomy row (spec-04 §4) + material switcher (spec-05 A2) share
   this component. Mobile = single-line horizontal scroll (collection-
   flagship-A.html mobile artboard, no corpus precedent before 2026-08-23).
   Full `.tab` type declaration (incl. letter-spacing) lives with the rest of
   the component further down this file (code-review L1: this file used to
   carry two separate `.tab` rules — this mobile-first stub plus a later
   unconditional one with a different letter-spacing value — and the later
   rule always won the cascade, silently killing the approved 0.24em mobile
   artboard value everywhere).
   ========================================================================== */

.m-tabs {
  display: flex;
  gap: 24px;
  overflow-x: auto;
  white-space: nowrap;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-bottom: 5px;
}

.m-tabs::-webkit-scrollbar {
  display: none;
}

.m-tabfade {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 36px;
  background: linear-gradient(to right, rgba(247, 241, 232, 0), var(--vt-page));
  pointer-events: none;
}

@media (min-width: 990px) {
  .m-tabs {
    gap: 28px;
    overflow-x: visible;
    white-space: normal;
    padding-bottom: 0;
  }

  .m-tabfade {
    display: none;
  }
}

/* ==========================================================================
   Material collection page — one-line story + cross-link (spec-05 A1)
   ========================================================================== */
.mat-line {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  letter-spacing: 0.02em;
  line-height: 1.85;
  color: var(--vt-body);
  max-width: 560px;
  margin: 16px auto 0;
  text-align: center;
}

.story-link {
  color: var(--vt-taupe);
  border-bottom: 1px solid var(--vt-underline-taupe-soft);
  padding-bottom: 3px;
}

@media (min-width: 990px) {
  .mat-line {
    font-size: calc(13.5px * var(--vt-ts, 1));
    line-height: 1.9;
    margin-top: 22px;
  }
}

/* ==========================================================================
   Leather Stories editorial (spec-05 Part B) — eyebrow/lede/body/care/close
   register + the 620px split component. Mobile = stacked full-bleed plate
   (About split pattern, per phase-03 task authority); desktop = the 620px/1fr
   two-column grid, direction flipped via `order` so DOM stays media-first at
   every breakpoint (no !important, no duplicated markup for `.rev`).
   ========================================================================== */
.ed-eyebrow {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

/* Story H1 (spec-05 B1/B2: 13px on the mobile board, 17px desktop). Scoped under
   .vt-story because the bare .sec-h rule further down this file is declared later
   and, at equal specificity, silently won: the H1 rendered at 12/13px on every
   story page until 2026-09-04. */
.vt-story .sec-h--story {
  font-size: calc(13px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  line-height: 2;
  margin-top: 14px;
}

.ed-lede {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(14px * var(--vt-ts, 1));
  letter-spacing: 0.02em;
  line-height: 2;
  color: var(--vt-body);
  max-width: 640px;
  margin: 24px auto 0;
  text-align: center;
}

.body-p {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  letter-spacing: 0.02em;
  line-height: 2;
  color: var(--vt-body);
  margin: 0 0 20px;
}

.body-p:last-child {
  margin-bottom: 0;
}

.care-h {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.close-line {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(13.5px * var(--vt-ts, 1));
  letter-spacing: 0.06em;
  line-height: 1.9;
  color: var(--vt-ink);
}

.matnav {
  display: flex;
  justify-content: center;
  gap: 18px;
}

.ed-split {
  margin-top: 48px;
}

.ed-split__media {
  display: block;
  overflow: hidden;
  background-color: var(--vt-plate);
  aspect-ratio: 2 / 3;
}

.ed-split__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.ed-split__text {
  padding: 34px 24px 0;
}

@media (min-width: 990px) {
  .vt-story .sec-h--story {
    font-size: calc(17px * var(--vt-ts, 1));
    letter-spacing: 0.42em;
    line-height: 1.2;
    margin-top: 16px;
  }

  .ed-eyebrow {
    font-size: calc(10px * var(--vt-ts, 1));
  }

  .ed-lede {
    font-size: calc(15.5px * var(--vt-ts, 1));
    line-height: 2.05;
    margin-top: 34px;
  }

  .body-p {
    font-size: calc(13.5px * var(--vt-ts, 1));
    line-height: 2.05;
    margin-bottom: 24px;
  }

  .close-line {
    font-size: calc(15px * var(--vt-ts, 1));
  }

  .matnav {
    gap: 28px;
  }

  .ed-split {
    display: grid;
    grid-template-columns: 620px 1fr;
    gap: 8px;
    padding: 0 56px;
    align-items: center;
    margin-top: 64px;
  }

  .ed-split--rev {
    grid-template-columns: 1fr 620px;
  }

  .ed-split--rev .ed-split__media {
    order: 2;
  }

  .ed-split--rev .ed-split__text {
    order: 1;
  }

  .ed-split__text {
    padding: 40px 40px 40px 72px;
  }

  .ed-split--rev .ed-split__text {
    padding: 40px 72px 40px 40px;
  }
}

/* ==========================================================================
   SC-2 · Ladder eyebrow reuses .sect-h (below); SC-3 · Trust strip
   ========================================================================== */
.trust {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9.5px * var(--vt-ts, 1));
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

/* ==========================================================================
   SC-4 · Solid-ink CTA family
   ========================================================================== */
.cta,
.dw-cta,
.dw-add {
  display: inline-block;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  text-transform: uppercase;
  background-color: var(--vt-ink);
  color: var(--vt-page);
  border: 0;
  border-radius: 0;
  text-align: center;
  cursor: pointer;
}

.cta {
  font-size: calc(11px * var(--vt-ts, 1));
  letter-spacing: 0.3em;
  padding: 16px 0;
}

.cta--inline {
  padding: var(--vt-cta-pad-inline);
}

.dw-cta {
  font-size: calc(11px * var(--vt-ts, 1));
  letter-spacing: 0.3em;
  padding: var(--vt-cta-pad-block);
  width: 100%;
}

.dw-add {
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  padding: 11px 25px;
}

@media (min-width: 990px) {
  /* :not(.cta--inline):not(.cta--responsive) — code-review H2 fix: the
     block-CTA desktop padding must not clobber .cta--inline's 17px 54px NOR
     .cta--responsive's desktop 17px 54px (var(--vt-cta-pad-inline), set below)
     — without the second :not, this rule's higher specificity (0,2,0 vs
     .cta--responsive's 0,1,0) wins regardless of source order. */
  .cta:not(.cta--inline):not(.cta--responsive) {
    padding: var(--vt-cta-pad-block);
  }
}

/* ==========================================================================
   SC-5 · Link species
   ========================================================================== */
.quietlink {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-ink);
  border-bottom: 1px solid var(--vt-underline-quietlink);
  padding-bottom: 3px;
}

.filterlink {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.filterlink--underline {
  border-bottom: 1px solid var(--vt-ink);
  padding-bottom: 3px;
}

.hairlink {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--vt-accent);
  border-bottom: 1px solid var(--vt-underline-hairlink);
  padding-bottom: 4px;
}

.attach-add {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--vt-accent);
  border-bottom: 1px solid var(--vt-underline-hairlink);
  padding-bottom: 3px;
  /* Horizon's .button-unstyled leaves buttons at cursor:default
     (owner 2026-09-04 "hover vao nut add khong co mouse pointer"). */
  cursor: pointer;
}

.txtlink {
  font: inherit;
  color: var(--vt-accent);
  border-bottom: 1px solid var(--vt-underline-txtlink);
  padding-bottom: 2px;
}

.tab {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  /* mobile-first: 0.24em per the approved artboard; 0.2em from 990px per
     spec-04 (code-review L1). */
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

@media (min-width: 990px) {
  .tab {
    letter-spacing: 0.2em;
  }
}

.tab.is-active {
  color: var(--vt-ink);
  border-bottom: 1px solid var(--vt-rule-strong);
  padding-bottom: 4px;
}

.tab b {
  font-weight: var(--vt-w-light, 400);
  color: var(--vt-muted);
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   SC-6 · Quiet page-end exit — reuses .quietlink/.filterlink + .count
   ========================================================================== */
.count {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9.5px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-muted);
}

/* ==========================================================================
   SC-8 · Swatch dot system (PDP)
   ========================================================================== */
.sw-dot {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background-size: cover;
  background-position: center;
  display: block;
}

.sw-dot.is-selected {
  outline: 1px solid var(--vt-rule-strong);
  outline-offset: 4px;
}

.sw-lbl {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.7;
  color: var(--vt-taupe);
  margin-top: 11px;
}

.sw-lbl.is-selected {
  color: var(--vt-ink);
}

.dotprice {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.12em;
  color: var(--vt-muted);
  font-variant-numeric: tabular-nums;
  margin-top: 3px;
}

@media (min-width: 990px) {
  .sw-dot {
    width: 30px;
    height: 30px;
  }

  .sw-lbl {
    margin-top: 13px;
  }
}

/* ==========================================================================
   Section / page headings, offers, editorial paragraphs
   ========================================================================== */
.sec-h {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.36em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--vt-ink);
}

.sect-h {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.eyebrow {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.lede {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(13px * var(--vt-ts, 1));
  letter-spacing: 0.03em;
  line-height: 1.95;
  color: var(--vt-body);
}

.desc {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(13px * var(--vt-ts, 1));
  letter-spacing: 0.02em;
  line-height: 1.85;
  color: var(--vt-body);
}

.fam-line {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  letter-spacing: 0.02em;
  line-height: 1.85;
  color: var(--vt-body);
  max-width: none;
}

.offer {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.big-offer {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(52px * var(--vt-ts, 1));
  letter-spacing: 0.1em;
  line-height: 1.05;
  color: var(--vt-ink);
  font-variant-numeric: tabular-nums;
}

/* Phase 6 (Debut LP / ads collections) — "Four leathers" strip register
   (spec-16 §8.4). Not needed anywhere before this phase (material-page
   stories use .body-p/.care-h instead), so added here rather than forked
   into a section-local stylesheet — same reasoning as the rest of this
   file: one edit repaints every future consumer. */
.mat-h {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.mat-b {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(11px * var(--vt-ts, 1));
  line-height: 1.75;
  letter-spacing: 0.02em;
  color: var(--vt-body);
  margin-top: 12px;
}

/* Phase 6 — responsive CTA (hero + close blocks on the Debut LP / 5 ads
   pages): full-width block at mobile (16px 0 padding, from the base .cta
   rule above), inline 17px/54px at desktop. `.cta--inline` alone can't do
   this — its padding is unconditional at every breakpoint (see cart-empty's
   single-size "Continue shopping" CTA, its only other consumer), so this is
   a distinct modifier rather than a reuse. */
.cta--responsive {
  display: block;
  width: 100%;
}

@media (min-width: 990px) {
  .mat-b {
    font-size: calc(12px * var(--vt-ts, 1));
    line-height: 1.8;
  }

  .cta--responsive {
    display: inline-block;
    width: auto;
    padding: var(--vt-cta-pad-inline);
  }
}

@media (min-width: 990px) {
  .sec-h {
    font-size: calc(13px * var(--vt-ts, 1));
    letter-spacing: 0.42em;
  }

  .sec-h--page-title {
    font-size: calc(14px * var(--vt-ts, 1));
  }

  .sect-h {
    font-size: calc(10px * var(--vt-ts, 1));
    letter-spacing: 0.3em;
  }

  .lede {
    font-size: calc(15px * var(--vt-ts, 1));
    line-height: 2;
  }

  .fam-line {
    font-size: calc(13px * var(--vt-ts, 1));
    line-height: 1.9;
    max-width: 640px;
  }

  .big-offer {
    font-size: calc(84px * var(--vt-ts, 1));
    line-height: 1.04;
  }
}

/* ==========================================================================
   Cart page + drawer ledger classes
   ========================================================================== */
.item-row {
  display: grid;
  grid-template-columns: 92px 1fr;
  gap: 20px;
  align-items: center;
}

.item-row--attach {
  grid-template-columns: 56px 1fr;
}

.item-obj {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* TESTER FIX: exact-px SLG sizing per the mock, replacing the old single
   68%-of-column .item-obj--slg blend (which under- or over-sized wallets and
   charms since one ratio stood in for both). Product class comes from the
   item's handle (cart-products.liquid) — display only, matches the drawer's
   .dw-item-obj.vt-slg-* rules below. */
.item-obj.vt-slg-bag img {
  width: 112px;
  margin: 0 auto;
}

.item-obj.vt-slg-wallet img {
  width: 82px;
  margin: 0 auto;
}

.item-obj.vt-slg-charm img {
  width: 74px;
  margin: 0 auto;
}

.iline {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.iname {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(11px * var(--vt-ts, 1));
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.iprice {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.08em;
  color: var(--vt-ink);
  font-variant-numeric: tabular-nums;
}

.imat {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  margin-top: 7px;
}

.iqty {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9.5px * var(--vt-ts, 1));
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--vt-body);
  margin-top: 15px;
}

.iqty a,
.iqty button {
  font: inherit;
  letter-spacing: inherit;
  color: var(--vt-taupe);
  text-decoration: none;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--vt-underline-taupe);
  padding: 0;
  cursor: pointer;
}

/* M3: the "With it +" meta-row trigger reuses .attach-add's accent register
   (same visual language as the in-block suggest summary it replaces) instead
   of the taupe .iqty button default above — needs the extra class to win on
   specificity, not !important. */
.iqty .dw-withit-trigger {
  color: var(--vt-accent);
  border-bottom-color: var(--vt-underline-hairlink);
}

.hair {
  border: 0;
  border-top: 1px solid var(--vt-hair-structural);
  margin: 22px 0;
}

.ledger {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.ledger .l {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--vt-body);
}

.ledger .v {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(13px * var(--vt-ts, 1));
  letter-spacing: 0.08em;
  color: var(--vt-ink);
  font-variant-numeric: tabular-nums;
}

.ledger .v--label {
  font-size: calc(10.5px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  font-variant-numeric: normal;
}

@media (min-width: 990px) {
  .item-row {
    grid-template-columns: 112px 1fr;
    gap: 28px;
  }

  .item-row--attach {
    grid-template-columns: 64px 1fr;
  }

  .hair {
    margin: 30px 0;
  }
}

/* ==========================================================================
   PDP accordion
   ========================================================================== */
.acc-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 2px;
  cursor: pointer;
}

.acc-label {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.acc-sign {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(13px * var(--vt-ts, 1));
  color: var(--vt-taupe);
}

.acc-body {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.04em;
  line-height: 2;
  color: var(--vt-body);
}

/* ==========================================================================
   Header / nav — .hd shared shell (spec-16 ch.18); header.liquid applies
   these classes rather than re-declaring the grid.
   ========================================================================== */
.hd {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 22px 20px 18px;
}

.hd a.nav,
.hd .nav {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9.5px * var(--vt-ts, 1));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vt-ink);
  line-height: 1;
}

@media (min-width: 990px) {
  .hd {
    grid-template-columns: 1fr auto 1fr;
    /* 2026-09-04 owner "header to quá cho nhỏ lại": Boards 38/30 (95px row)
       → 22/22 = 71px, the same row height as the homepage hero header. Same
       round, "nav không căn giữa vertical": the Boards' baseline alignment
       (flex-end + 2px nudge) read as bottom-heavy in the shorter row, so the
       cells now centre on the wordmark's vertical middle. */
    align-items: center;
    padding: 22px 56px 22px;
  }

  .hd a.nav,
  .hd .nav {
    font-size: calc(10.5px * var(--vt-ts, 1));
    letter-spacing: 0.16em;
  }
}

/* ==========================================================================
   Drawer dw-* grammar (spec-10 §2a)
   ========================================================================== */
.dw-drawer {
  background-color: var(--vt-page);
  color: var(--vt-ink);
  display: flex;
  flex-direction: column;
  overflow: clip;
}

.dw-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 26px 32px 10px;
  /* 2026-09-04 owner (empty state after Remove: "CART — 0 ×" shrink-wrapped
     in the middle): the injected #empty-cart-template head must span the
     drawer whatever its parent centres, so title left / × right hold. */
  width: 100%;
  box-sizing: border-box;
  align-self: stretch;
  justify-self: stretch;
  text-align: left;
}

.dw-title {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(11px * var(--vt-ts, 1));
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.dw-x {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(17px * var(--vt-ts, 1));
  line-height: 1;
  color: var(--vt-taupe);
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transition: color 160ms ease;
}

/* The dialog moves focus to × on open; Horizon's 3px currentcolor box read as
   a bug (owner 2026-09-04 "dấu X nhìn off brand … nhìn lỗi"). Focus and hover
   both answer with ink instead of a ring. */
.dw-x:hover,
.dw-x:focus-visible {
  outline: none;
  color: var(--vt-ink);
}

/* Line-level discount (the "Any two bags" Function): struck original next to
   the paid figure, and the rule named on its own row in the drawer register
   (owner 2026-09-04 "cần show rõ được phần discount"). */
.dw-itprice .cap-was {
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.08em;
  margin-left: 8px;
}

/* 2026-09-04 owner ("discount nghe confusing, không nhấn"): the paid figure
   goes to 400 next to the struck original, and the rule row becomes an ink
   "$50 off" pill (PDP save-pill vocabulary) + "Paired with the {partner}". */
.dw-itprice--now {
  font-weight: var(--vt-w-regular, 500);
}

.dw-pill {
  display: inline-block;
  padding: 3px 8px 2px;
  background: var(--vt-ink);
  color: var(--vt-page);
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  line-height: 1.3;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.dw-itdiscs {
  margin: 8px 0 0;
  padding: 0;
}

.dw-pairnote {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(11px * var(--vt-ts, 1));
  letter-spacing: 0.03em;
  color: var(--vt-body);
}

.dw-pairnote + .dw-pairnote {
  margin-top: 6px;
}

/* 2026-09-04 owner: the preorder note ("Preorder · Ships …") rendered in
   Horizon's sentence-case body register between the price and the pill;
   in the drawer it joins the secondary-line register (10px / 400 / taupe,
   same as .dw-itsub). Three-class selector — see the .dw-pairline trap. */
.dw-item-row .cart-items__details .cart-item-preorder {
  margin-top: 6px;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  line-height: 1.5;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  opacity: 1;
}

.dw-itname {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10.5px * var(--vt-ts, 1));
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.dw-itname--slg {
  font-size: calc(10px * var(--vt-ts, 1));
}

.dw-itsub {
  /* 2026-09-04 owner "text nhìn mờ tịt": Jost 300 at 9px on cream vanished;
     the drawer's secondary lines now sit at 400 / 10px, still taupe. */
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.dw-itprice {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.1em;
  color: var(--vt-ink);
  font-variant-numeric: tabular-nums;
}

.dw-itmeta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10.5px * var(--vt-ts, 1));
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.dw-itmeta a,
.dw-itmeta button {
  font: inherit;
  letter-spacing: inherit;
  color: var(--vt-ink);
  text-decoration: none;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--vt-hair-structural);
  padding: 0;
  cursor: pointer;
}

/* M3: see the matching .iqty .dw-withit-trigger comment above. */
.dw-itmeta .dw-withit-trigger {
  color: var(--vt-accent);
  border-bottom-color: var(--vt-underline-hairlink);
}

.dw-eyebrow {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.dw-offername {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.dw-offerwhy {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(11.5px * var(--vt-ts, 1));
  letter-spacing: 0.02em;
  line-height: 1.65;
  color: var(--vt-body);
}

.dw-whisper {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(8.5px * var(--vt-ts, 1));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vt-muted);
}

.dw-sumrow {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.dw-sumlbl {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.dw-sumfig {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(13px * var(--vt-ts, 1));
  letter-spacing: 0.08em;
  color: var(--vt-ink);
  font-variant-numeric: tabular-nums;
}

.dw-smlbl {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-muted);
}

.dw-smfig {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(11px * var(--vt-ts, 1));
  letter-spacing: 0.08em;
  color: var(--vt-muted);
}

.dw-reassure {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  text-align: center;
  margin-top: 13px;
}

/* ==========================================================================
   Drawer structural grammar (phase 5 — spec-03 §2 H1 order + scrim).
   dw-item-row/-obj/-text/-line1 build the F2 composed line on the uniform
   112px object column; dw-suggest builds the single-visible "With it"
   offer; dw-ledger builds the pinned foot. Text-group steps (7/16 single vs
   6/13 stacked, spec-03 §2.2) are driven by a Liquid-computed modifier on
   the items wrapper rather than nth-child math, since the rule is about
   TOTAL row count, not row position.
   ========================================================================== */
.dw-item-row {
  display: flex;
  align-items: center;
  gap: 26px;
  padding: 0 32px;
  flex-shrink: 0;
}

/* General-sibling (not adjacent-sibling): an error <tr> can sit between two
   item rows in the DOM, so "every item after the first" can't rely on `+`. */
.dw-item-row ~ .dw-item-row {
  padding-top: 8px;
}

.dw-item-obj {
  width: 112px;
  flex-shrink: 0;
  display: flex;
  justify-content: center;
}

.dw-item-obj img {
  display: block;
  width: 100%;
  height: auto;
}

/* TESTER FIX: exact-px SLG sizing per the mock (see the .item-obj.vt-slg-*
   comment above — same handle-keyed, display-only mechanism, drawer side). */
.dw-item-obj.vt-slg-bag img {
  width: 112px;
}

.dw-item-obj.vt-slg-wallet img {
  width: 82px;
}

.dw-item-obj.vt-slg-charm img {
  width: 74px;
}

.dw-item-text {
  flex: 1;
  min-width: 0;
}

.dw-item-line1 {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.dw-items--single .dw-itsub {
  margin-top: 7px;
}

.dw-items--single .dw-itmeta {
  margin-top: 16px;
}

.dw-items--stacked .dw-itsub {
  margin-top: 6px;
}

.dw-items--stacked .dw-itmeta {
  margin-top: 13px;
}

.dw-item-props {
  margin-top: 6px;
}

.dw-item-props dl {
  margin: 0;
}

.dw-item-props .cart-items__property {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.dw-item-error {
  margin-top: 6px;
}

/* -- Suggest engine ("With it") -- */
.dw-suggest {
  flex-shrink: 0;
}

.dw-suggest--after-single {
  padding: 26px 32px 0;
}

.dw-suggest--after-multi {
  padding: 22px 32px 0;
}

.dw-suggest details {
  margin: 0;
}

.dw-suggest details > summary {
  list-style: none;
  cursor: pointer;
}

.dw-suggest details > summary::-webkit-details-marker,
.dw-suggest details > summary::marker {
  display: none;
  content: '';
}

.dw-suggest details[open] > summary {
  display: none;
}

.dw-suggest-toggle {
  display: block;
  padding: 6px 0;
}

/* Per-line offer row (2026-09-04, owner: the offer sits under ITS product,
   never as a swapping block at the foot). Hidden summary: the meta-row
   "With it +" trigger is the affordance; that trigger hides while its own
   offer is open. Full drawer width, same 32px gutter as the item rows
   (owner 17:14 "cho full size"); offers never collapse each other. */
.dw-suggest-toggle--hidden {
  display: none;
}

.dw-suggest-row {
  display: block;
}

.dw-suggest-row > td {
  display: block;
  padding: 10px 32px 6px;
}

.dw-item-row:has(+ .cart-items__error + .dw-suggest-row .dw-suggest[open]) .dw-pairline {
  display: none;
}

/* Trigger: its own line well below Qty / Remove (owner 18:08: more air, so
   a thumb never lands on Remove), and a hairline pill, not an underlined word. */
.dw-item-row .cart-items__details .dw-pairline {
  /* specificity over Horizon's .cart-items__details child margins (base.css) */
  margin-top: 24px;
}

/* Quiet stepper: Horizon's quantity-selector-component (refs untouched)
   restyled as "- 1 +" in the meta register. */
.dw-qty .quantity-selector-wrapper {
  display: inline-flex;
  gap: 0;
}

.dw-qty .quantity-selector {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  height: auto;
  min-height: 0;
  padding: 0;
  border: 0;
  background: none;
}

.dw-qty .quantity-selector .button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  min-width: 0;
  min-height: 0;
  padding: 0;
  border: 1px solid var(--vt-hair-structural, rgba(20, 18, 16, 0.3));
  border-radius: 50%;
  background: none;
  color: var(--vt-ink);
  cursor: pointer;
  transition: border-color 160ms ease;
}

.dw-qty .quantity-selector .button:hover,
.dw-qty .quantity-selector .button:focus-visible {
  outline: none;
  border-color: var(--vt-ink);
}

.dw-qty .quantity-selector .button[disabled] {
  opacity: 0.35;
  cursor: default;
}

.dw-qty .quantity-selector .button .svg-wrapper,
.dw-qty .quantity-selector .button svg {
  display: block;
  width: 9px;
  height: 9px;
}

.dw-qty .quantity-selector input {
  width: 2.4em;
  height: auto;
  min-height: 0;
  padding: 0;
  margin: 0;
  border: 0;
  background: none;
  text-align: center;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10.5px * var(--vt-ts, 1));
  letter-spacing: 0.1em;
  color: var(--vt-ink);
  font-variant-numeric: tabular-nums;
  -moz-appearance: textfield;
  appearance: textfield;
}

.dw-qty .quantity-selector input::-webkit-outer-spin-button,
.dw-qty .quantity-selector input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

.dw-qty .quantity-selector input:focus-visible {
  outline: none;
  border-bottom: 1px solid var(--vt-ink);
}

.dw-pairpill {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px 7px;
  border: 1px solid var(--vt-hair-structural, rgba(20, 18, 16, 0.3));
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--vt-ink);
  transition: border-color 160ms ease, background-color 160ms ease;
}

.dw-pairpill span {
  font-weight: var(--vt-w-light, 400);
  font-size: calc(13px * var(--vt-ts, 1));
  line-height: 1;
  letter-spacing: 0;
}

.dw-pairpill:hover,
.dw-pairpill:focus-visible {
  outline: none;
  border-color: var(--vt-ink);
}

/* Framed note with legend (mock C): hairline box, legend on the border. */
.dw-pairbox {
  position: relative;
  margin: 18px 0 6px;
  padding: 18px 16px 14px;
  border: 1px solid var(--vt-hair-structural, rgba(20, 18, 16, 0.16));
}

.dw-pairbox__legend {
  position: absolute;
  top: -6px;
  left: 14px;
  padding: 0 8px;
  background: var(--vt-page);
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  white-space: nowrap;
}

.dw-pairbox__legend b {
  font-weight: var(--vt-w-regular, 500);
  color: var(--vt-ink);
}

.dw-pairbox__body {
  display: flex;
  align-items: center;
  gap: 16px;
}

.dw-pairbox__thumb {
  display: block;
  width: 48px;
  flex-shrink: 0;
}

.dw-pairbox__thumb img {
  display: block;
  width: 100%;
  height: auto;
}

.dw-pairbox__text {
  flex: 1;
  min-width: 0;
}

.dw-pairbox__name {
  display: block;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10.5px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.dw-pairbox__name a {
  color: inherit;
  text-decoration: none;
}

.dw-pairbox__name i {
  font-style: normal;
  font-weight: var(--vt-w-light, 400);
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
}

.dw-pairbox__why,
.dw-pairbox__whisper {
  display: block;
  margin-top: 5px;
}

.dw-pairbox__add {
  flex-shrink: 0;
}


.dw-offer {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 12px 0;
  border-top: 1px solid var(--vt-hair-soft);
}

.dw-offer__obj {
  display: block;
  height: auto;
  width: 68px;
  flex-shrink: 0;
}

/* TESTER FIX: exact-px SLG sizing per the mock for the suggest offer row
   only (vellatini-cart-suggest.liquid) — recall/empty rows share the base
   .dw-offer__obj rule above unmodified and keep their spec sizes. No bag
   override: an offer candidate suggesting another bag keeps the 68px
   default (not part of the mock's exact-width list). */
.dw-offer__obj.vt-slg-wallet {
  width: 72px;
}

.dw-offer__obj.vt-slg-charm {
  width: 64px;
}

.dw-offer__text {
  flex: 1;
  min-width: 0;
}

.dw-offer__nameline {
  display: block;
}

.dw-offer__why {
  margin-top: 6px;
}

.dw-offer__preorder {
  margin-top: 4px;
  color: var(--vt-accent);
}

/* -- Ledger foot -- */
/* 2026-09-04 owner ("ledger đơn điệu"): mock A — hairline-topped ledger,
   small taupe Items row, ink Any-two-bags row with the pill, hairline,
   Subtotal in a larger register, whisper, Checkout carrying the amount. */
.dw-ledger {
  padding: 20px 32px 32px;
  border-top: 1px solid var(--vt-hair-structural);
  flex-shrink: 0;
}

.dw-ledger .dw-sumrow--sm + .dw-sumrow--sm {
  margin-top: 9px;
}

.dw-sumrow--sm .dw-sumlbl {
  font-size: calc(9.5px * var(--vt-ts, 1));
  color: var(--vt-taupe);
}

.dw-sumrow--sm .dw-sumfig {
  font-size: calc(11.5px * var(--vt-ts, 1));
  color: var(--vt-taupe);
}

.dw-sumrow--discount .dw-sumlbl {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--vt-ink);
}

.dw-sumrow--discount .dw-sumfig {
  font-weight: var(--vt-w-regular, 500);
  color: var(--vt-ink);
}

.dw-ledger__hair {
  border: 0;
  border-top: 1px solid var(--vt-hair-structural);
  margin: 16px 0 14px;
}

.dw-sumrow--total .dw-sumlbl {
  font-size: calc(10.5px * var(--vt-ts, 1));
}

.dw-sumrow--total .dw-sumfig {
  font-size: calc(18px * var(--vt-ts, 1));
  font-weight: var(--vt-w-regular, 500);
  letter-spacing: 0.04em;
}

.dw-ledger__whisper {
  margin-top: 6px;
  text-align: right;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(8.5px * var(--vt-ts, 1));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vt-muted);
}

.dw-ledger .dw-cta {
  margin-top: 20px;
}

.dw-cta__amt {
  margin-left: 12px;
  font-weight: var(--vt-w-light, 400);
  letter-spacing: 0.12em;
  font-variant-numeric: tabular-nums;
}

/* -- Empty state (spec-03 §3 state 4) -- */
.dw-empty {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  text-align: center;
}

.dw-empty__identity {
  flex-shrink: 0;
  padding: 40px 32px 0;
}

.dw-empty__wordmark {
  display: inline-block;
  opacity: 0.9;
}

.dw-empty__line {
  margin-top: 22px;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.dw-empty__spacer {
  flex: 1;
}

.dw-recall {
  padding: 0 32px;
  flex-shrink: 0;
}

.dw-empty__foot {
  padding: 26px 32px 32px;
  text-align: center;
  flex-shrink: 0;
}

/* -- Owner-order scrim: the cart drawer always dims the rest of the page +
   click-outside closes, on every viewport (opt-out of Horizon's default
   ≥990px "squeeze" sidebar mode via [data-force-modal], assets/theme-
   drawer.js + snippets/theme-drawer.liquid). Literal --vt-scrim value
   (same veil as the search overlay, spec-09 §0) beats the shared
   --backdrop-color-rgb/--backdrop-opacity pair unconditionally. -- */
#cart-drawer .theme-drawer__dialog::backdrop {
  /* L5: literal fallback — ::backdrop doesn't inherit custom properties from
     the light DOM the way normal descendants do in every engine/version, so
     a lookup miss on --vt-scrim must still land on the intended veil color
     instead of `background: ;` (no dim at all). */
  background: var(--vt-scrim, rgba(20, 18, 16, 0.32));
}

/* ==========================================================================
   Search overlay
   ========================================================================== */
.searchline {
  display: flex;
  align-items: baseline;
  gap: 18px;
  border-bottom: 1px solid var(--vt-rule-strong);
  padding-bottom: 16px;
}

.searchline .q,
.searchline .ph {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(22px * var(--vt-ts, 1));
  letter-spacing: 0.06em;
}

.searchline .q {
  color: var(--vt-ink);
}

.searchline .ph {
  color: var(--vt-placeholder);
}

@media (min-width: 990px) {
  .searchline .q,
  .searchline .ph {
    font-size: calc(34px * var(--vt-ts, 1));
  }
}

/* ==========================================================================
   PDP — gallery + buy box (spec-02, spec-16 ch.5). `.pdp-bb` is the marker
   class on blocks/_product-details.liquid's wrapper (PDP-exclusive, per that
   file's own comment); every rule below is scoped to it or to standalone
   `.pdp-*` component classes used only inside the buy box.
   ========================================================================== */

/* -- 1.3 gallery: 9-frame editorial set, per-frame plate/ground treatment
   driven by vellatini.gallery_plan (snippets/product-media-gallery-content.liquid).
   Two real classes (vt-gallery-frame + vt-plate/vt-ground) give the specificity
   needed to beat Horizon's own single-class .product-media-container rule
   without !important (dev-rules cascade-trap ban) regardless of stylesheet
   bundling order.

   code-review M4: vt-plate/vt-ground (gallery-owned classes), NOT the bare
   .plate/.ground utilities defined earlier in this file — those utilities are
   shared by unrelated consumers (card-gallery.liquid, vellatini-story-editorial.
   liquid, vellatini-campaign-island.liquid, vellatini-lp-ladder.liquid), so this
   gallery previously leaked its background-color onto that shared class instead
   of owning it. Background color now lives here explicitly rather than being
   inherited from the bare utility. */
.product-information__media .vt-gallery-frame.vt-plate,
.product-information__media .vt-gallery-frame.vt-ground {
  aspect-ratio: 3 / 4;
}

.product-information__media .vt-plate {
  background-color: var(--vt-plate);
}

.product-information__media .vt-gallery-frame.vt-plate .product-media__image {
  object-fit: cover;
}

.product-information__media .vt-ground {
  background-color: var(--vt-ground);
}

.product-information__media .vt-gallery-frame.vt-ground {
  display: flex;
  align-items: center;
  justify-content: center;
}

.product-information__media .vt-gallery-frame.vt-ground .product-media__image {
  object-fit: contain;
}

@media (min-width: 750px) {
  .product-information__media .vt-gallery-frame--full {
    grid-column: 1 / -1;
  }
}

/* Mobile pager (spec-02 §2.2): Horizon's native slide dots, restyled — scoped
   to the PDP media column only so no other slideshow in the theme inherits
   this 4px-dot treatment. */
.product-information__media .slideshow-controls__dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  padding-top: 14px;
}

.product-information__media .slideshow-controls__dots .slideshow-control {
  font-size: 0;
  width: 4px;
  height: 4px;
  padding: 0;
  border-radius: 50%;
  background-color: var(--vt-dot-inactive);
}

.product-information__media .slideshow-controls__dots .slideshow-control[aria-selected='true'] {
  background-color: var(--vt-ink);
}

/* -- 1.4 buy box stack (top-to-bottom margins per spec-16 §5.3's "stack steps"
   table — each element owns the gap from the element above it, so the
   details block's own `gap` setting is set to 0 in templates/product.json). */
.pdp-bb__eyebrow {
  text-align: center;
  margin-bottom: 12px;
}

.sec-h--pdp {
  text-align: center;
  font-size: calc(13px * var(--vt-ts, 1));
  letter-spacing: 0.36em;
}

.pdp-bb__sub {
  margin-top: 10px;
  text-align: center;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

@media (min-width: 990px) {
  .pdp-bb__eyebrow {
    margin-bottom: 14px;
  }

  .sec-h--pdp {
    font-size: calc(14px * var(--vt-ts, 1));
    letter-spacing: 0.42em;
  }

  .pdp-bb__sub {
    margin-top: 12px;
    font-size: calc(10px * var(--vt-ts, 1));
    letter-spacing: 0.22em;
  }
}

/* -- rendition dots (P2) / P1 quiet line — spec-02 §3, THE LAW (§3.0): a dot
   is one real SKU. `.sw-dot`/`.sw-lbl`/`.dotprice` are the shared SC-8 type
   register defined above; this block only adds row/option layout. */
.pdp-dots {
  margin-top: 26px;
}

.pdp-dots__row {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 24px;
}

/* code-review 2026-09-03 (owner: "nhìn align nó bị lỗi"): the option was a
   fixed 66/74px block holding a block-level dot plus two INLINE spans. Three
   defects followed: the dot hugged the left edge while the text centred (a
   fixed-width block does not centre inside text-align), the price flowed
   inline after the material word whenever it fit ("SUEDE $119.00" on one
   line, "$159.00" alone on the next), and multi-word colours ("Dark
   chocolate") wrapped mid-name because 74px is narrower than the label at
   0.16em tracking. Now: flex column, everything centred, label and price on
   their own rows, each label line kept whole, column grows to fit the
   longest label so all three columns share one rhythm. */
.pdp-dots__opt {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 0 0 auto;
  min-width: 66px;
  text-align: center;
}

.pdp-dots__opt .sw-lbl,
.pdp-dots__opt .dotprice {
  display: block;
  white-space: nowrap;
}

.pdp-oneline {
  margin-top: 24px;
  text-align: center;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(8px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-muted);
}

@media (min-width: 990px) {
  .pdp-dots {
    margin-top: 30px;
  }

  .pdp-dots__row {
    gap: 30px;
  }

  .pdp-dots__opt {
    min-width: 74px;
  }

  .pdp-oneline {
    margin-top: 28px;
    font-size: calc(9px * var(--vt-ts, 1));
    letter-spacing: 0.22em;
  }
}

/* -- P3 size ladder — spec-02 §3.3: TRUE relative scale (width_cm * 1.45px/cm,
   set inline per rung via --rung-w), baseline-aligned, unselected rungs at
   0.55 opacity, a 20x1px ink bar under the selected rung only. */
.pdp-ladder {
  margin-top: 28px;
}

.pdp-ladder__row {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 20px;
}

.pdp-ladder__rung {
  display: block;
  text-align: center;
  color: inherit;
  /* 2026-09-04 owner: the 0.55 dim on unselected sizes read as sold out.
     Every rung is full strength; the selected one is told by its bar and
     ink label, hover previews that. */
}

.pdp-ladder__rung:hover .pdp-ladder__lbl {
  color: var(--vt-ink);
}

.pdp-ladder__imgwrap {
  display: block;
  width: var(--rung-w);
  margin: 0 auto;
}

.pdp-ladder__img {
  display: block;
  width: 100%;
  height: auto;
}

.pdp-ladder__bar {
  display: block;
  width: 20px;
  height: 1px;
  margin: 8px auto 0;
  background-color: var(--vt-ink);
}

.pdp-ladder__lbl {
  display: block;
  margin-top: 10px;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  transition: color 160ms ease;
}

.pdp-ladder__rung.is-selected .pdp-ladder__lbl {
  margin-top: 8px;
  color: var(--vt-ink);
}

.pdp-ladder__cm {
  display: block;
  margin-top: 2px;
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
}

@media (min-width: 990px) {
  .pdp-ladder {
    margin-top: 32px;
  }

  .pdp-ladder__row {
    gap: 26px;
  }
}

/* -- description — spec-16 §5.3: D 13/0.02em/1.85, M 12.5/0.02em/1.85. The
   shared `.desc` class above is 13px at both sizes (authored for a different,
   non-PDP context); this modifier corrects the mobile step for the buy box
   only, per the "no folklore percentages / verified deltas" discipline. */
.pdp-bb__desc {
  margin-top: 24px;
  text-align: center;
  font-size: calc(12.5px * var(--vt-ts, 1));
}

@media (min-width: 990px) {
  .pdp-bb__desc {
    margin-top: 30px;
    font-size: calc(13px * var(--vt-ts, 1));
  }
}

/* -- code-review M1: text-only ADD TO CART (spec-02 the buy-box CTA is a hairline
   text register, not an icon button). snippets/add-to-cart-button.liquid bakes an
   SVG icon and a checkmark-burst success flourish into its markup with no settings
   toggle; scoped display:none on the two PDP add-to-cart surfaces (buy box +
   Carried-inside mini-add) removes both without forking that snippet. No
   !important — these are the only two PDP consumers of this markup, so a plain
   class selector is enough. */
.pdp-bb .add-to-cart-icon,
.pdp-mini-add .add-to-cart-icon,
.pdp-mini-add .add-to-cart__added {
  display: none;
}

/* -- ADD TO CART — spec-16 §5.3: solid ink, full width, no radius/border.
   Colors come from the native add-to-cart block's own custom_button_* color
   settings (templates/product.json); this covers what those settings can't:
   exact Jost type + the 16px/17px padding step, ancestor-scoped onto
   Horizon's real add-to-cart-button markup so blocks/add-to-cart.liquid stays
   unforked. */
.pdp-bb .add-to-cart-button {
  display: block;
  width: 100%;
  margin-top: 28px;
  padding: 16px 0;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.28em;
  text-transform: uppercase;
  text-align: center;
  border-radius: 0;
}

/* -- In-flight state (owner 2026-09-04 "khi click Add thi nen co hieu ung
   loading"): Horizon's product-form.js and vellatini-pair-add.js already set
   `disabled` on the button for the /cart/add round trip; this makes that
   visible - label recedes, a 10px hairline ring turns beside it, cursor says
   progress. One rule set for the solid buy button, the quiet ADD links
   (.attach-add) and the drawer pill. */
@keyframes vt-spin {
  to {
    transform: rotate(360deg);
  }
}

.pdp-bb .add-to-cart-button,
.attach-add,
.dw-pairpill {
  position: relative;
}

.pdp-bb .add-to-cart-button[disabled],
.attach-add[disabled],
.dw-pairpill[disabled] {
  cursor: progress;
  opacity: 0.55;
  transition: opacity 160ms ease;
}

.pdp-bb .add-to-cart-button[disabled]::after,
.attach-add[disabled]::after,
.dw-pairpill[disabled]::after {
  content: '';
  display: inline-block;
  vertical-align: middle;
  width: 10px;
  height: 10px;
  margin-left: 10px;
  border: 1px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: vt-spin 700ms linear infinite;
}

.attach-add[disabled]::after,
.dw-pairpill[disabled]::after {
  width: 8px;
  height: 8px;
  margin-left: 8px;
  vertical-align: -1px;
}

.pdp-bb__returns {
  margin-top: 12px;
  text-align: center;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vt-muted);
}

@media (min-width: 990px) {
  .pdp-bb .add-to-cart-button {
    margin-top: 34px;
    padding: 17px 0;
    font-size: calc(11px * var(--vt-ts, 1));
    letter-spacing: 0.3em;
  }

  .pdp-bb__returns {
    margin-top: 14px;
    font-size: calc(10px * var(--vt-ts, 1));
  }
}

/* -- accordions — spec-16 §5.3: reuses the native <details>/<summary> a11y
   contract (blocks/_accordion-row.liquid); this restyles the header row,
   body copy, and the +/- glyph color/size, and lets the accordion block's own
   `divider_color` setting (set to the accordion hairline token in
   templates/product.json) carry the top/bottom rules. */
.pdp-bb .accordion {
  margin-top: 36px;
  text-align: left;
}

.pdp-bb .details__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 15px 2px;
  cursor: pointer;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.pdp-bb .details__icon {
  display: none;
}

.pdp-bb .icon-plus svg,
.pdp-bb .icon-caret svg {
  width: 13px;
  height: 13px;
  color: var(--vt-taupe);
}

.pdp-bb .details-content {
  padding: 0 2px 18px;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.04em;
  line-height: 2;
  color: var(--vt-body);
}

@media (min-width: 990px) {
  .pdp-bb .accordion {
    margin-top: 44px;
  }

  .pdp-bb .details__header {
    padding: 16px 2px;
    letter-spacing: 0.26em;
  }

  .pdp-bb .details-content {
    padding: 0 2px 20px;
  }
}

/* -- "Carried inside" attach rows — spec-02 §1.4-10. Thumb / name+price / real
   Add (vellatini-mini-add.liquid renders the actual add-to-cart-button, so
   .attach-add here IS the same element the shared SC-5 rule above styles). */
.pdp-carried {
  margin-top: 36px;
  text-align: left;
}

.pdp-carried__label {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  margin-bottom: 4px;
}

.pdp-carried__row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 0;
  border-top: 1px solid var(--vt-hair-soft);
}

.pdp-carried__thumb {
  display: block;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
}

.pdp-carried__thumb-img {
  display: block;
  width: 100%;
  height: auto;
}

.pdp-carried__text {
  flex: 1;
  min-width: 0;
}

.pdp-carried__name {
  display: block;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9.5px * var(--vt-ts, 1));
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--vt-ink);
}

.pdp-carried__price {
  margin-top: 3px;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(10px * var(--vt-ts, 1));
  color: var(--vt-taupe);
}

/* margin-left:auto targets the flex ITEM (the <product-form-component> wrapper
   vellatini-mini-add.liquid renders, class `pdp-mini-add`) — the .attach-add
   class itself lands on the nested <button>, which isn't the flex child. */
.pdp-carried .pdp-mini-add {
  margin-left: auto;
  flex-shrink: 0;
}

@media (min-width: 990px) {
  .pdp-carried {
    margin-top: 44px;
  }

  .pdp-carried__label {
    margin-bottom: 6px;
  }

  .pdp-carried__thumb {
    width: 48px;
    height: 48px;
  }

  .pdp-carried__name {
    font-size: calc(10px * var(--vt-ts, 1));
    letter-spacing: 0.2em;
  }

  .pdp-carried__price {
    margin-top: 4px;
  }
}

/* -- code-review H2: mini-add error affordance (snippets/vellatini-mini-add.liquid).
   Same `.product-form-text__error.hidden` contract as the native buy box
   (blocks/buy-buttons.liquid), which Horizon leaves visually unstyled beyond the
   `hidden` class — house-style it here for the rare case a Carried-inside/With-it
   "Add" genuinely fails, so the message reads as part of this register rather than
   unstyled browser text. */
.pdp-mini-add .product-form-text__error {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.pdp-mini-add .product-form-text__error.hidden {
  display: none;
}

.pdp-mini-add .product-form-text__error .svg-wrapper svg {
  width: 12px;
  height: 12px;
}

/* ==========================================================================
   "With it" / "You may also like" caption register — spec-16 §5.5/§5.6
   (code-review M3). Both cross-sell rows render Horizon's native `_product-card`
   chain, so the SC-1 caption grammar above (`.cap-name`/`.cap-price`/`.caption`)
   already applies; these two rows use a slightly different register than SC-1's
   generic default, so this overrides only the values that differ, scoped to
   `.vt-withit`/`.vt-ymal` (an extra ancestor class beats the unscoped SC-1 rule's
   specificity — no !important, same technique as `.cap-price--pdp` above).
   ========================================================================== */
/* spec-16 §5.5 TYPE: card name 400 D 10/0.24em · M 9.5/0.20em UC ink — the mobile
   step already matches SC-1's default (.cap-name) exactly, so only the desktop
   size needs an override below (SC-1's desktop default is 10.5px). */

.vt-withit .product-card__content product-price .price,
.vt-withit .product-card__content product-price .price-item__group.price,
.vt-ymal .product-card__content product-price .price,
.vt-ymal .product-card__content product-price .price-item__group.price {
  /* spec-16 §5.5/§5.6 TYPE: price 300 10 / D 0.12em (cap-price@10) · M 0.10em,
     #8A7968 (taupe) — SC-1's default price color is ink, not taupe. */
  color: var(--vt-taupe);
}

.vt-withit .product-card__content,
.vt-ymal .product-card__content {
  /* spec-16 §5.5/§5.6 SPACING: caption pt 12 M (SC-1 default is 11px). */
  padding-top: 12px;
}

@media (min-width: 990px) {
  .vt-withit .product-card__content a[ref='productTitleLink'] p,
  .vt-ymal .product-card__content a[ref='productTitleLink'] p {
    /* spec-16 §5.5 TYPE: card name D 10/0.24em (SC-1 default is 10.5px there;
       letter-spacing already matches at 0.24em). */
    font-size: calc(10px * var(--vt-ts, 1));
  }

  .vt-withit .product-card__content product-price .price,
  .vt-withit .product-card__content product-price .price-item__group.price,
  .vt-ymal .product-card__content product-price .price,
  .vt-ymal .product-card__content product-price .price-item__group.price {
    /* spec-16 §5.5/§5.6 TYPE+SPACING: price D 10/0.12em taupe, mt 7 (SC-1
       default at this breakpoint is 11px/0.1em ink, mt 6). */
    font-size: calc(10px * var(--vt-ts, 1));
    letter-spacing: 0.12em;
    margin-top: 7px;
  }

  .vt-withit .product-card__content,
  .vt-ymal .product-card__content {
    /* spec-16 §5.5/§5.6 SPACING: caption pt 16 D (SC-1 default is 14px). */
    padding-top: 16px;
  }
}

/* ==========================================================================
   Phase 7 — Secondary pages (spec-08, spec-16 ch.10-15): About · Contact ·
   Shipping · Returns · Privacy · Terms · Privacy Choices · Reviews.

   Reuse-first: `.ed-eyebrow`, `.body-p`, `.close-line`, `.plate`, `.count`,
   `.filterlink`/`.filterlink--underline` were already tuned to this exact
   register by phase-01/03 (Leather Stories reused the About split pattern
   ahead of time) — no redeclaration below. New classes/modifiers only cover
   what phase-01/03 didn't need: the secondary H1/pivot register, pillar
   headings, section heads, quiet lists, rules, rate cards, the Contact
   field/info grid, and the Reviews summary (avg + distribution + stars).
   ========================================================================== */
.sec-h--secondary {
  font-size: calc(13px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  line-height: 2;
}

.sec-h--secondary-sub {
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.24em;
}

.lede--secondary {
  font-size: calc(14px * var(--vt-ts, 1));
  line-height: 2;
  letter-spacing: 0.02em;
}

.body-p--reviews {
  margin-bottom: 20px;
}

.pillar-h {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  letter-spacing: 0.28em;
  line-height: 1.5;
  text-transform: uppercase;
  color: var(--vt-ink);
  margin: 14px 0 0;
}

.sect-h--secondary {
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.3em;
  color: var(--vt-ink);
  margin: 0 0 20px;
}

.sect-h--muted {
  color: var(--vt-taupe);
}

.note-h {
  display: block;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  margin-bottom: 6px;
}

.kicker {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.mail {
  border-bottom: 1px solid var(--vt-placeholder);
  padding-bottom: 1px;
}

.col {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 24px;
}

.rule {
  border: 0;
  border-top: 1px solid #e2d9cc;
  margin: 44px 24px;
}

.rule--trust,
.rule--policy {
  max-width: 720px;
  margin-left: auto;
  margin-right: auto;
}

.quiet {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
}

.quiet li {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  line-height: 2;
  letter-spacing: 0.02em;
  color: var(--vt-body);
  padding-left: 20px;
  position: relative;
}

.quiet li::before {
  content: '\2014';
  position: absolute;
  left: 0;
  color: var(--vt-muted);
}

/* Vellatini secondary-page head (spec-16 ch.10-14 shared head: eyebrow? +
   H1 + lede?) — identical padding across all 8 pages, per spec-08 §8.5. */
.vt-sec-head {
  text-align: center;
  padding: 26px 24px 0;
}

.vt-sec-head .sec-h--secondary {
  margin-top: 14px;
}

.vt-sec-head .lede--secondary {
  margin: 24px 0 0;
  text-align: left;
}

/* Reviews head body_1/body_2 only consumer here (spec-08 §6.1) — stays
   centered at both breakpoints (headwrap's text-align:center, unlike
   About/Contact's lede which the mock explicitly left-aligns on mobile). */
.vt-sec-head .body-p {
  margin: 20px 0 0;
}

.vt-sec-head .count {
  margin-top: 16px;
}

@media (min-width: 990px) {
  .sec-h--secondary {
    font-size: calc(15px * var(--vt-ts, 1));
    letter-spacing: 0.32em;
  }

  .sec-h--secondary-sub {
    font-size: calc(14px * var(--vt-ts, 1));
    letter-spacing: 0.36em;
  }

  .lede--secondary {
    font-size: calc(15.5px * var(--vt-ts, 1));
    line-height: 2.05;
  }

  .pillar-h {
    font-size: calc(14px * var(--vt-ts, 1));
    letter-spacing: 0.34em;
    margin-top: 16px;
  }

  .col {
    padding: 0 56px;
  }

  .rule {
    margin: 44px auto;
  }

  .rule--trust {
    margin: 56px auto;
  }

  .rule--policy {
    margin: 48px auto;
  }

  .quiet {
    margin-bottom: 22px;
  }

  .quiet li {
    font-size: calc(13.5px * var(--vt-ts, 1));
    line-height: 2.05;
    padding-left: 22px;
  }

  .vt-sec-head {
    padding: 46px 56px 0;
  }

  .vt-sec-head .sec-h--secondary {
    margin-top: 18px;
  }

  .vt-sec-head .lede--secondary {
    max-width: 640px;
    margin: 30px auto 0;
    text-align: center;
  }

  .vt-sec-head .body-p {
    max-width: 640px;
    margin: 22px auto 0;
    text-align: center;
  }

  .vt-sec-head .count {
    margin-top: 20px;
  }
}

/* About split rhythm (spec-08 §2.2/§10.2) — reuses `.ed-split`/`.ed-split--rev`
   (built in phase-03 for Leather Stories against this same About pattern);
   margin-top varies per instance (founder 78/48, pillar 1 78/48, pillars
   2-4 64/56 — desktop/mobile), so it's exposed as a CSS var with the
   Leather-Stories default (64px/48px) kept as the fallback so those pages
   render unchanged when the var is unset. */
.ed-split {
  margin-top: var(--vt-split-mt-m, 48px);
}

@media (min-width: 990px) {
  .ed-split {
    margin-top: var(--vt-split-mt-d, 64px);
  }
}

/* About / secondary-page blocks sit as flex items inside Horizon's generic
   `section` (section-content-wrapper = flex column, align-items:flex-start),
   so without a width they shrink-wrap to content and hug the left edge
   (2560: head w752 @x0, split w2018). Stretch them, then frame like the
   homepage / Leather Stories WIDE-SCREEN CAP (2026-09-02 ruling: only the
   hero is full-bleed; every other block lives in the 1440 column + 56px
   gutters). Auto inline margins centre a flex item on the cross axis even
   under align-items:flex-start. Mobile keeps its own padding, just stretched. */
.vt-sec-head,
.ed-split,
.vt-about-statement,
.vt-plate-image {
  width: 100%;
  box-sizing: border-box;
}

@media (min-width: 990px) {
  .vt-sec-head,
  .ed-split,
  .vt-about-statement,
  .vt-plate-image {
    max-width: calc(1440px + 2 * 56px);
    margin-inline: auto;
  }
}

/* 2026-09-05: same shrink-wrap trap on the five trust / contact / reviews /
   privacy-choices pages. `.col` is "max-width 720px; margin 0 auto" (spec-08
   §8.5) but as a flex item with no width it hugged the LEFT gutter at every
   desktop width (2560: text L=56 / R=1110; 1440: L=56 instead of centred).
   Stretch every auto-centred column so the auto margins actually centre it;
   max-widths (720 / 620) and paddings are unchanged. */
.col,
.rule--trust,
.rule--policy,
.rate-grid,
.sumwrap,
.vt-contact-info,
.vt-form-head,
.contact-form {
  width: 100%;
  box-sizing: border-box;
}

/* …and the flex item is NOT the column itself: Horizon's custom-liquid block
   renders an unclassed wrapper <div> around the markup, and THAT div is the
   shrink-wrapped flex item (probe 2560: div w=720 x=0 → .col w=720 x=0).
   Blocks with their own root (.vt-sec-head, .sumwrap) centred fine. */
.layout-panel-flex--column
  > div:has(> :is(.col, .rule--trust, .rule--policy, .rate-grid, .vt-contact-info, .vt-form-head)) {
  width: 100%;
}

/* ==========================================================================
   Privacy Policy / Terms of Service (page.json → Horizon `page-content` rte,
   only consumer of .page-content) — owner 2026-09-05: option A, the house
   policy column (spec-08 §8.5 shared skeleton: .col 720px centred, .sect-h
   sections split by hairline rules, body-p register). The page HTML is
   Word-pasted (p with inline margin styles, h4 section heads, h5 sub-heads,
   b, i, a) so paragraph margins need !important to beat the inline styles.
   ========================================================================== */
/* Horizon's main-page section is `page-width-content` = --normal-content-width
   (672px) laid out by grid, so the block can never reach 720 on its own —
   widen the section's content track to the house column instead. */
.section.page-width-content:has(.page-content) {
  --page-content-width: 720px;
  /* the column carries its own 24 / 56px side padding like every other
     house .col — drop Horizon's extra 16 / 40px page margin (mobile text
     sat at 40px instead of the spec 24px) */
  --page-margin: 0px;
}

.shopify-section .page-content {
  width: 100%;
  box-sizing: border-box;
  max-width: 720px;
  margin: 48px auto 0;
  padding: 0 24px;
}

.shopify-section .page-content p,
.shopify-section .page-content li {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  letter-spacing: 0.02em;
  line-height: 2;
  color: var(--vt-body);
  margin: 0 0 20px !important;
}

/* "Last Updated: …" opener → .count register (spec-08 policy head meta line) */
.shopify-section .page-content rte-formatter > p:first-child i {
  font-style: normal;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9.5px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--vt-muted);
}

/* Section heads → .sect-h (400 / 10px / 0.30em / upper / ink, mb 20px);
   every head after the first opens a new ruled section (hr.rule grammar:
   1px #E2D9CC, 44px mobile / 56px desktop of air each side). */
.shopify-section .page-content h2,
.shopify-section .page-content h3,
.shopify-section .page-content h4 {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.3em;
  line-height: 1.6;
  text-transform: uppercase;
  color: var(--vt-ink);
  margin: 0 0 20px;
}

.shopify-section .page-content :is(h2, h3, h4):not(:first-child) {
  border-top: 1px solid #e2d9cc;
  padding-top: 44px;
  margin-top: 44px;
}

/* Sub-heads → the quieter taupe .sect-h, no rule */
.shopify-section .page-content h5 {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--vt-taupe);
  margin: 28px 0 14px;
}

.shopify-section .page-content b,
.shopify-section .page-content strong {
  font-weight: var(--vt-w-regular, 500);
  color: var(--vt-ink);
}

.shopify-section .page-content a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid var(--vt-placeholder);
  padding-bottom: 1px;
  overflow-wrap: anywhere;
}

.shopify-section .page-content ul,
.shopify-section .page-content ol {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
}

.shopify-section .page-content li {
  position: relative;
  padding-left: 20px;
  margin: 0 !important;
}

.shopify-section .page-content li::before {
  content: '4';
  position: absolute;
  left: 0;
  color: var(--vt-muted);
}

@media (min-width: 990px) {
  .shopify-section .page-content {
    margin-top: 64px;
    padding: 0 56px;
  }

  .shopify-section .page-content :is(h2, h3, h4):not(:first-child) {
    padding-top: 56px;
    margin-top: 56px;
  }
}

/* ==========================================================================
   Contact (spec-08 §3 / spec-16 ch.11)
   ========================================================================== */
.vt-contact-info {
  display: flex;
  flex-direction: column;
  text-align: center;
  padding: 52px 24px 0;
}

.vt-contact-info__cell + .vt-contact-info__cell {
  margin-top: 34px;
}

.vt-contact-info__cell .body-p {
  margin: 0;
}

@media (min-width: 990px) {
  .vt-contact-info {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    max-width: 720px;
    margin: 72px auto 0;
    padding: 0 56px;
  }

  .vt-contact-info__cell + .vt-contact-info__cell {
    margin-top: 0;
  }
}

/* Contact form restyle (spec-14 §7) — hairline-underline `.fld` treatment
   overriding contact-form.liquid's own {% stylesheet %} rules. Equal-or-
   higher selector specificity (.contact-form .contact-form__input, 0,2,0)
   beats the block's own 0,1,0 `.contact-form__input` rule cleanly, no
   !important needed (input_style stays "default" per spec-14 §7 so no
   --style-border-width-inputs/--style-border-radius-inputs custom-var fight). */
.vt-form-head {
  text-align: center;
  max-width: 620px;
  margin: 60px auto 0;
  padding: 0 24px;
}

.vt-form-head__body {
  margin: 18px 0 28px;
}

@media (min-width: 990px) {
  .vt-form-head {
    margin-top: 88px;
    padding: 0 56px;
  }

  .vt-form-head__body {
    margin: 22px 0 34px;
  }
}

.contact-form {
  box-sizing: border-box;
  max-width: 620px;
  margin-left: auto;
  margin-right: auto;
  padding-left: 24px;
  padding-right: 24px;
}

@media (min-width: 990px) {
  .contact-form {
    padding-left: 56px;
    padding-right: 56px;
  }
}

.contact-form .contact-form__input {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--vt-placeholder);
  border-radius: 0;
  padding: 10px 0 8px;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--vt-taupe);
}

.contact-form .contact-form__input::placeholder {
  color: var(--vt-taupe);
  opacity: 1;
}

.contact-form .contact-form__input--textarea {
  min-height: 0;
  padding-bottom: 42px;
  resize: none;
}

.contact-form .contact-form__form {
  gap: 22px;
}

.contact-form .contact-form__form-row {
  gap: 22px;
}

.contact-form .submit-button {
  display: inline-block;
  background: transparent;
  color: var(--vt-ink);
  border: 0;
  border-bottom: 1px solid var(--vt-ink);
  border-radius: 0;
  padding: 0 0 3px;
  min-width: 0;
  font-family: var(--vt-font);
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.contact-form__form-foot {
  text-align: center;
  margin-top: 38px;
  padding-bottom: 72px;
}

@media (min-width: 990px) {
  .contact-form .contact-form__form {
    gap: 26px;
  }

  .contact-form .contact-form__form-row {
    gap: 26px;
  }

  .contact-form .contact-form__input--textarea {
    padding-bottom: 46px;
  }

  .contact-form__form-foot {
    margin-top: 44px;
    padding-bottom: 96px;
  }
}

/* ==========================================================================
   Shipping rate cards (spec-08 §4 / spec-16 ch.12)
   ========================================================================== */
.col--trust-head {
  margin-top: 48px;
}

.col--policy-head {
  margin-top: 64px;
}

.col--contact-intro {
  margin-top: 22px;
}

@media (min-width: 990px) {
  .col--trust-head {
    margin-top: 72px;
  }

  .col--policy-head {
    margin-top: 64px;
  }

  .col--contact-intro {
    margin-top: 64px;
  }
}

.rate-grid {
  display: flex;
  flex-direction: column;
  max-width: 720px;
  margin: 0 auto 20px;
  padding: 0 24px;
}

.rate-card {
  border: 1px solid #e2d9cc;
  padding: 22px 24px;
}

.rate-card + .rate-card {
  margin-top: 8px;
}

.rate-card .body-p {
  margin: 12px 0 0;
}

@media (min-width: 990px) {
  .rate-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-bottom: 22px;
    padding: 0 56px;
  }

  .rate-card {
    padding: 26px 30px;
  }

  .rate-card + .rate-card {
    margin-top: 0;
  }

  .rate-card .body-p {
    margin-top: 14px;
  }
}

/* Native `text`-block paragraph escape hatch — snippets/text.liquid ships an
   UNCONDITIONAL `.text-block p { margin-block: var(--font-paragraph--spacing) }`
   rule ((0,1,1) specificity) that outranks a bare `.body-p` class ((0,1,0)),
   so legal/trust copy authored as raw HTML inside a native `text` block
   (Shipping/Returns/Contact-intro/Terms/Privacy §) needs an ancestor-qualified
   tag selector to win the cascade regardless of stylesheet source order. */
.col.col--trust p {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  line-height: 2;
  letter-spacing: 0.02em;
  color: var(--vt-body);
  margin: 0 0 20px;
}

.col.col--trust p:last-child {
  margin-bottom: 0;
}

.col.col--policy p {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  line-height: 2;
  letter-spacing: 0.02em;
  color: var(--vt-body);
  margin: 0 0 20px;
}

.col.col--policy p:last-child {
  margin-bottom: 0;
}

@media (min-width: 990px) {
  .col.col--trust p {
    font-size: calc(13.5px * var(--vt-ts, 1));
    line-height: 2.05;
    margin-bottom: 22px;
  }

  .col.col--policy p {
    font-size: calc(13px * var(--vt-ts, 1));
  }

  .col--center-d p {
    text-align: center;
  }
}

/* ==========================================================================
   Privacy/Terms default template (`templates/page.json` → `page-content`,
   admin-authored body — spec-13 §6 ruling: Privacy + Terms render on the
   default page template with their legal body text entered in Admin, not
   carried as template settings; spec-08 §7.1 typographic deltas applied to
   the generic RTE tags this block renders). Unscoped is deliberate — per
   spec-13's file map, `page.json` is the leftover default template with no
   other consumer in this build (About/Contact/Shipping/Returns/Reviews/
   Privacy Choices/4 Stories all carry dedicated templates).
   ========================================================================== */
.page-content {
  max-width: 720px;
  margin: 64px auto 0;
  padding: 0 24px;
  font-family: var(--vt-font);
}

.page-content p {
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  line-height: 2;
  letter-spacing: 0.02em;
  color: var(--vt-body);
  margin: 0 0 20px;
}

.page-content h2,
.page-content h3 {
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--vt-ink);
  margin: 0 0 18px;
}

.page-content hr {
  border: 0;
  border-top: 1px solid #e2d9cc;
  margin: 44px 0;
}

@media (min-width: 990px) {
  .page-content {
    padding: 0 56px;
  }

  .page-content p {
    font-size: calc(13px * var(--vt-ts, 1));
  }

  .page-content hr {
    margin: 48px 0;
  }
}

/* ==========================================================================
   Reviews summary — avg + star row + distribution bars (spec-08 §6.2 /
   spec-16 ch.15.2)
   ========================================================================== */
.sumwrap {
  display: grid;
  grid-template-columns: 1fr;
  justify-items: center;
  gap: 40px;
  padding: 48px 24px 0;
}

.sum-avg {
  text-align: center;
}

.avg-num {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(44px * var(--vt-ts, 1));
  letter-spacing: 0.06em;
  line-height: 1;
  color: var(--vt-ink);
  margin-bottom: 14px;
}

.stars {
  letter-spacing: 0.18em;
  font-size: calc(12px * var(--vt-ts, 1));
  color: #d8cdbc;
}

.stars .st.on {
  color: var(--vt-taupe);
}

.sum-avg .count {
  margin-top: 12px;
}

.drow {
  display: grid;
  grid-template-columns: 26px 180px auto;
  align-items: center;
  gap: 14px;
  margin-bottom: 9px;
}

.dlab {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(10.5px * var(--vt-ts, 1));
  letter-spacing: 0.1em;
  color: var(--vt-body);
}

.dbar {
  display: block;
  height: 1px;
  background: #e2d9cc;
  position: relative;
}

.dfill {
  display: block;
  position: absolute;
  left: 0;
  top: -1px;
  height: 3px;
  background: var(--vt-taupe);
}

.dnum {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9.5px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  color: var(--vt-muted);
  font-variant-numeric: tabular-nums;
}

/* Reviews grid — the live Judge.me @app widget (Phase 10) renders inside
   `sections/reviews-app-slot` (an empty native `section`, no block entries
   pre-populated — the app-block uuid can only be added post-install via
   editor, spec-13 §6). Judge.me isn't in this pull (spec-12 verified: zero
   app blocks anywhere) so these are UNSCOPED, robust/tolerant selectors
   against Judge.me's documented default class names (jdgm-*) toward the
   boards card/star anatomy — "same register" tolerance, not byte-identical.
   Verify + tighten once the app is installed and its live DOM can be
   inspected; jdgm-* is Judge.me's own namespace so collision risk elsewhere
   in this theme is low. */
.jdgm-rev-widg__summary-external-link {
  display: none;
}

.jdgm-rev {
  border-top: 1px solid #e2d9cc;
  padding: 30px 0 26px;
  font-family: var(--vt-font);
}

.jdgm-rev__author {
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  color: var(--vt-ink);
}

.jdgm-rev__timestamp {
  font-weight: var(--vt-w-light, 400);
  font-size: calc(9px * var(--vt-ts, 1));
  letter-spacing: 0.16em;
  color: var(--vt-muted);
  font-variant-numeric: tabular-nums;
}

.jdgm-rev__body {
  font-weight: var(--vt-w-light, 400);
  font-size: calc(12.5px * var(--vt-ts, 1));
  line-height: 1.95;
  letter-spacing: 0.02em;
  color: var(--vt-body);
  margin: 12px 0 0;
}

.jdgm-star.jdgm--on {
  color: var(--vt-taupe);
}

.jdgm-star {
  color: #d8cdbc;
}

@media (min-width: 990px) {
  .sumwrap {
    grid-template-columns: auto auto;
    justify-content: center;
    justify-items: initial;
    gap: 88px;
    padding: 64px 56px 0;
  }

  .drow {
    grid-template-columns: 30px 220px auto;
  }

  .jdgm-rev__body {
    font-size: calc(13px * var(--vt-ts, 1));
    line-height: 1.95;
  }
}

/* ==========================================================================
   Phase 8 — Utility pages: search results wall, 404 (spec-09 ch.16–17;
   overlay's own .searchline/.vt-veil-*/.vt-search-*/.vt-popular-paths
   classes live with their component files, snippets/search-modal.liquid +
   snippets/vellatini-search-resting.liquid + snippets/vellatini-popular-
   paths.liquid + snippets/vellatini-search-load-more.liquid — this block
   only carries what's genuinely global register: the 404 display number and
   its supporting doors row).
   ========================================================================== */

/* -- 404 display "404" (spec-09 §10/§11: the About head display-weight
   precedent — 300/96px/0.14em/lh1/tabular-nums, 64px mobile) -- */
.vt-404-display {
  font-family: var(--vt-font);
  font-weight: var(--vt-w-light, 400);
  font-size: calc(64px * var(--vt-ts, 1));
  letter-spacing: 0.14em;
  line-height: 1;
  color: var(--vt-ink);
  font-variant-numeric: tabular-nums;
  margin-top: 20px;
}

/* -- 404 lede: two verbatim copy variants (spec-09 §10 desktop / §11 mobile
   — the mobile line drops the "moved/typo" clause), toggled by breakpoint
   rather than duplicated markup logic. -- */
.vt-404-lede {
  margin-top: 22px;
}

.vt-404-lede--desktop {
  display: none;
}

.vt-404-lede--mobile {
  display: block;
}

/* -- 404 doors: three quietlinks (spec-09 §10/§11) -- */
.vt-404-doors {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  margin-top: 26px;
}

@media (min-width: 990px) {
  .vt-404-display {
    font-size: calc(96px * var(--vt-ts, 1));
    margin-top: 26px;
  }

  .vt-404-lede {
    max-width: 440px;
    margin: 32px auto 0;
  }

  .vt-404-lede--desktop {
    display: block;
  }

  .vt-404-lede--mobile {
    display: none;
  }

  .vt-404-doors {
    flex-direction: row;
    justify-content: center;
    gap: 30px;
    margin-top: 34px;
  }
}

/* -- 404 main section padding (spec-09 §10/§11, tokens ch.17): the "main"
   section (templates/404.json) authors padding-block-start/end as 90/40 —
   the correct DESKTOP values (spec-09 §10) — but Horizon's generic
   `.spacing-style` fluid scale (assets/base.css ~1350-1380, --spacing-scale:
   0.7 below 990px) auto-shrinks that to ~63px/~28px on mobile rather than
   the spec-09 §11 mobile values of 60/30. Scoped override, mobile only;
   desktop is untouched (the settings-driven 90/40 already matches spec).
   Same `[id$='__main']` suffix-match technique as the ladder-spacing rule
   below, further scoped with `:has(+ [id$='__ladder'])` since this rule has
   no sibling of its own to chain onto — only 404.json's "main" section is
   immediately followed by a "ladder" section, so this can't match any other
   template's "main" section (search.json's "main" has no ladder sibling). -- */
@media screen and (max-width: 989px) {
  [id$='__main']:has(+ [id$='__ladder']) .section-content-wrapper.spacing-style {
    padding-block-start: 60px;
    padding-block-end: 30px;
  }
}

/* -- 404 ladder spacing (spec-09 §10/§11): the ladder is a separate JSON
   template section (sections/vellatini-lp-ladder.liquid can't read the
   "main" section's own content, and vice versa). The IDs are NOT literally
   "shopify-section-main"/"shopify-section-ladder" — Online Store 2.0 JSON
   templates render section wrappers as
   "shopify-section-template--<template-id>__<section-key>", so a bare
   #shopify-section-main can never match. Match on the section-key SUFFIX
   instead (the literal keys authored in templates/404.json: "main" +
   "ladder"), chained via the adjacent-sibling combinator for specificity
   that only ever matches this exact template's two sections. -- */
[id$='__main'] + [id$='__ladder'] .vt-ladder {
  padding-top: 30px;
  padding-bottom: 56px;
}

@media (min-width: 990px) {
  [id$='__main'] + [id$='__ladder'] .vt-ladder {
    margin-top: 40px;
    padding-top: 0;
    padding-bottom: 100px;
  }
}

/* cache-bump 260824-1150 */

/* ==========================================================================
   PDP accordion register (owner 2026-09-03 "headline sai font"): Horizon's
   native summary renders 14px sentence-case; the boards buy-box runs
   .acc-head/.acc-label — Jost 400 10px caps, 0.24em mobile / 0.26em desktop,
   with the sign in taupe. Scoped to the buy-box details column.
   ========================================================================== */
.product-details summary.details__header {
  font-family: 'Jost', sans-serif;
  font-weight: var(--vt-w-regular, 500);
  font-size: calc(10px * var(--vt-ts, 1));
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: #141210;
}

.product-details summary.details__header .svg-wrapper {
  color: #8a7968;
}

@media (min-width: 990px) {
  .product-details summary.details__header {
    letter-spacing: 0.26em;
  }
}

/* ==========================================================================
   PDP mobile gutter + vertical rhythm (owner 2026-09-04: "margin chỗ xa chỗ
   gần" on the mobile PDP). Laws: spec-16 §0 page margin M 20px, "PDP mobile
   20 throughout"; spec-02 §2.2 pager dots sit BELOW the hero on the page
   ground (padding 14px 0 0); spec-02 §2.3 buy area padding-top 36px.
   Before: Horizon's .page-width-* set --page-margin 16px on the product
   section (buy box at 16 while header / YMAL / footer sit at 20), the mobile
   gallery stack added its own 20px inside that column (36px), Horizon's
   native pager was absolutely positioned over the image, and the buy box
   started flush against the hero (0px). Mobile-only; desktop untouched.
   ========================================================================== */
@media screen and (max-width: 989px) {
  .product-information.section {
    --page-margin: 20px;
  }

  .product-details.pdp-bb {
    padding-top: 36px;
  }

  /* Pager below the hero: drop Horizon's controls-on-media overlay
     (absolute + 44px touch-target band + difference blend) so the dots flow
     after the slides on the page ground in ink, per spec-02 §2.2. */
  .product-information__media slideshow-controls.media-gallery__mobile-controls[controls-on-media] {
    position: static;
    min-height: 0;
    mix-blend-mode: normal;
  }

  /* Horizon draws each dot as a 5.6px button::after with a 1.5px inset ring
     inside a pill (border-radius 3rem + overflow hidden) — on the cream
     ground that reads as hollow squares and clips the last dot at the pill
     corner. The 4px ink dot is the button itself (rule above), so drop the
     pseudo, the pill clip and the button's negative margins. */
  .product-information__media .slideshow-controls__dots {
    padding: 14px 0 0;
    border-radius: 0;
    overflow: visible;
  }

  .product-information__media .slideshow-controls__dots .slideshow-control {
    margin: 0;
  }

  .product-information__media .slideshow-controls__dots .slideshow-control::after {
    display: none;
  }

  /* spec-16 §5.6: YMAL price mt 6 on mobile (SC-1 default is 5). */
  .vt-ymal .product-card__content product-price .price,
  .vt-ymal .product-card__content product-price .price-item__group.price {
    margin-top: 6px;
  }
}

/* 2026-09-06: ADS LANDING PAGES wide-screen cap (owner "fix lại width hết đi").
   The six paid-traffic templates (collection.debut + collection.ads-*) were
   built to the 1440 artboard and every section root stretched to the full
   viewport at 2560 (hero split 620px/1fr → text column 1800px wide, walls
   4-up at 600px a cell). Same ruling as the homepage / About / Leather
   Stories: only the homepage hero is full-bleed; every other block lives in
   the 1440 column + 56px gutters. Each root already carries its own 56px
   side padding, so border-box + 1552 outer = 1440 content. The LP ladder
   shell sets `margin:0` at (0,2,0) in its own stylesheet — the repeated
   class bumps this to (0,3,0) so the auto centring wins regardless of
   load order. */
@media (min-width: 990px) {
  .vt-ah,
  .vt-ladder.vt-ladder--lp-shell.vt-ladder,
  .vt-founder,
  .vt-fl,
  .vt-famwall,
  .vt-tcb,
  .vt-wg,
  .vt-pw,
  .vt-fs,
  .vt-close,
  .vt-trust {
    max-width: calc(1440px + 2 * 56px);
    margin-inline: auto;
    box-sizing: border-box;
  }
}

/* 2026-09-06 owner: LP CTAs scroll to the bags ("gắn vào scroll") — hero and
   close CTAs now point at #vt-shop (first wall/ladder). The ≥990 scroller is
   .page-wrapper, which base.css never gave smooth scrolling (only html). */
@media (prefers-reduced-motion: no-preference) {
  .page-wrapper {
    scroll-behavior: smooth;
  }
}

/* 2026-09-06 owner: "header của mấy phần này khó nhìn quá" — the 9px taupe
   .sect-h / 9.5px muted .count rows on the LP walls were unreadable at
   1440+. Scoped to the ads/LP section roots only; the hero eyebrow and the
   rest of the site keep the small register. */
.vt-famwall .sect-h,
.vt-wg .sect-h,
.vt-pw .sect-h,
.vt-fs .sect-h,
.vt-fl .sect-h,
.vt-tcb .sect-h,
.vt-founder .sect-h {
  font-size: calc(12px * var(--vt-ts, 1));
  letter-spacing: 0.24em;
  color: var(--vt-ink);
}

.vt-famwall .count,
.vt-wg .count,
.vt-pw .count,
.vt-fs .count {
  font-size: calc(10.5px * var(--vt-ts, 1));
  color: var(--vt-taupe);
}
