/* ═══════════════════════════════════════════════════════════════════════════
   lajoya.css — La Joya Dominicana brand showcase
   ───────────────────────────────────────────────────────────────────────────
   Loaded ONLY by /collection/la-joya-dominicana. Everything is scoped under
   .ljd-page (which sits on the .brand-page wrapper alongside the shared brand
   chrome), so nothing here can leak into the other fourteen brand pages.

   WHY THE .theme-* BLOCKS LIVE HERE AND NOT IN components.css
   ───────────────────────────────────────────────────────────
   Every other .theme-* block is in components.css. These two are not, and that
   is deliberate: components.css is loaded by ~250 pages behind a ?v= query
   string, so adding two rules there means either rewriting that query string in
   every one of those files or shipping a rule that cached clients never fetch.
   The blast radius is not worth the consistency. The cost is real though — the
   next person grepping components.css for .theme- will not find these two.

   LOAD ORDER: this sheet must come AFTER brand.css. It overrides .brand-name,
   .brand-tagline and .vitola-separator, all of which brand.css/components.css
   define first.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ══════════════════════════════════════════════════════════
   SECTION 1: FULL-BLEED ESCAPE
   .brand-main is max-width:64rem with 1.5rem side padding. The hero, the
   tasting band and the suspension band all need the whole viewport, so they
   break out with the standard 100vw / calc(50% - 50vw) idiom. This is safe
   from horizontal-scrollbar overflow only because .brand-page is overflow-x:
   clip — do not remove that.
   ══════════════════════════════════════════════════════════ */
.ljd-page .ljd-bleed {
  width: 100vw;
  margin-left: calc(50% - 50vw);
}


/* ══════════════════════════════════════════════════════════
   SECTION 2: BACKGROUND PLATE STACK
   Four fixed plates that cross-fade by section. js/lajoya.js owns
   .style.opacity on these; CSS owns only the transform (Ken Burns) and the
   transition. Never set opacity in a body.page-loaded rule here — an inline
   style always wins, so a CSS opacity would be dead weight that reads as if
   it were doing something.
   ══════════════════════════════════════════════════════════ */
.ljd-page .ljd-bg-stack {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.ljd-page .ljd-plate {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0;
  transform: scale(1.05);
  transition: opacity 1.6s cubic-bezier(0.22, 1, 0.36, 1),
              transform 3s cubic-bezier(0.22, 1, 0.36, 1);
}

body.page-loaded .ljd-page .ljd-plate {
  transform: scale(1);
}

/* transform-origin varies per plate so the drift direction differs by section
   and the four do not read as one repeated move. */
.ljd-page .ljd-plate--hero {
  background-image: url("../../assets/images/ljd-hero-1920.webp");
  transform-origin: 50% 20%;
}
.ljd-page .ljd-plate--heritage {
  background-image: url("../../assets/images/ljd-plate-heritage-1920.webp");
  transform-origin: 20% 50%;
}
.ljd-page .ljd-plate--humidor {
  background-image: url("../../assets/images/ljd-plate-humidor-1920.webp");
  transform-origin: 80% 50%;
}
.ljd-page .ljd-plate--lounge {
  background-image: url("../../assets/images/ljd-plate-lounge-1920.webp");
  transform-origin: 50% 80%;
}

/* Phones pull the 800w set instead. These plates never exceed 0.16 opacity
   behind a scrim, so the resolution drop is invisible, and it saves ~1.2MB on
   the connection least able to afford it. */
@media (max-width: 767px) {
  .ljd-page .ljd-plate--hero {
    background-image: url("../../assets/images/ljd-hero-800.webp");
  }
  .ljd-page .ljd-plate--heritage {
    background-image: url("../../assets/images/ljd-plate-heritage-800.webp");
  }
  .ljd-page .ljd-plate--humidor {
    background-image: url("../../assets/images/ljd-plate-humidor-800.webp");
  }
  .ljd-page .ljd-plate--lounge {
    background-image: url("../../assets/images/ljd-plate-lounge-800.webp");
  }
}


/* ══════════════════════════════════════════════════════════
   SECTION 3: HERO
   Three sibling layers in a positioned parent, each with an explicit z-index.
   The image is NOT a background shorthand on the element holding the text —
   the layers have to stay separable for the motion work.
   ══════════════════════════════════════════════════════════ */
.ljd-page .ljd-hero {
  position: relative;
  isolation: isolate;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: -8rem;            /* cancels .brand-main's padding-top */
  margin-bottom: 7rem;
  min-height: 100vh;            /* fallback for browsers without svh */
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* ── z-0: the photograph ── */
.ljd-page .ljd-hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
}
/* The plate is portrait (1920x2399) and the hero is a landscape 100vw x 100svh,
   so cover always scales to WIDTH and spends the difference in height. Nothing
   is lost sideways — the humidor shelves, the lounge chair and the lit wall
   either side of the box survive at every width — so the whole framing decision
   is which horizontal band of the photograph the crop keeps.

   Y only bites above a 0.8 viewport aspect. Below that the crop flips to
   horizontal, the full height is already on screen, and this value stops doing
   anything — so phones and portrait tablets need no override and get the
   ceiling lights and the counter for free.

   55% is chosen against the WORDMARK, not against the photograph alone. The
   crest carries its own "LA JOYA DOMINICANA" line, so any band that centres the
   crest also parks it under the h1 saying the same words:
     42%  crest dead centre — the h1 lands on top of it and the two readings of
          the name collide. This is what the old plate's 40% became once the
          box grew in frame.
     55%  what ships. The LJD monogram clears the h1 with room to spare, and the
          band reaches far enough down to land the whole cigar row, the box base
          and the counter reflection — the context the crop is spending height
          to buy.
     60%  too far. The box's top edge starts to leave the frame and the crest
          crowds the upper border.
   Stable across desktop aspects: the band is 30–75% of the source at 16:9 and
   27–78% at 16:10, so the crest does not drift between laptop and monitor. */
.ljd-page .ljd-hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 55%;
  display: block;
}

/* ── z-1: scrim (+ .brand-vignette, which is already z-index:1) ── */
/* The last two stops are the seam. The original ramp only reached full
   --color-surface on the hero's final pixel, so the photograph was still
   partly visible where the page below it was already flat — a soft edge, but
   an edge. Reaching the surface colour at 92% and holding it gives the hero a
   dissolve to land in instead: the image is gone before the section is. */
.ljd-page .ljd-hero-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to bottom,
              rgba(24, 18, 16, 0.58) 0%,
              rgba(24, 18, 16, 0.35) 42%,
              rgba(24, 18, 16, 0.62) 74%,
              rgba(24, 18, 16, 0.93) 87%,
              #181210 96%,
              #181210 100%);
}

/* ── z-2: type ── */
.ljd-page .ljd-hero-inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 60rem;
  margin: 0 auto;
  padding: 7rem 1.5rem 9rem;
  text-align: center;
}

/* HOUSE EXCLUSIVE — gold on this page only; brand.css ships it stone-400. */
.ljd-page .ljd-hero-eyebrow {
  color: rgba(202, 152, 69, 0.92);
  margin-bottom: 1.25rem;
}

/* "LA JOYA DOMINICANA" is 18 characters — twice PLASENCIA. brand.css's flat
   3.75rem overflows a 375px viewport, so this clamps and is allowed to wrap;
   two balanced lines read better than one shrunken one. */
.ljd-page .ljd-hero .brand-name {
  font-size: clamp(2.5rem, 9vw, 6rem);
  line-height: 1.04;
  margin-bottom: 2rem;
  text-wrap: balance;
}

.ljd-page .ljd-hero .brand-story {
  margin-top: 2rem;
}

/* Scroll cue. .animate-bounce's keyframe carries translateX(-50%), so the
   element must be absolutely positioned at left:50% or it jumps half its own
   width to the left. */
.ljd-page .ljd-hero-cue {
  position: absolute;
  left: 50%;
  bottom: 2.25rem;
  z-index: 2;
  width: 1px;
  height: 3rem;
  background: linear-gradient(to bottom, transparent, rgba(202, 152, 69, 0.55));
}


/* ══════════════════════════════════════════════════════════
   SECTION 4: ORNAMENT
   ══════════════════════════════════════════════════════════ */

/* ── 4a. Gold hairline rules ──────────────────────────────
   Three on the page, no more: under the hero eyebrow block, above the tasting
   section, above the CTA. Reuses components.css's gt-bc-rule keyframe rather
   than defining a second scaleX wipe. */
.ljd-page .ljd-rule {
  width: 12rem;
  max-width: 60%;
  height: 1px;
  margin: 0 auto 2.25rem;
  background: linear-gradient(to right,
              rgba(202, 152, 69, 0.30),
              rgba(202, 152, 69, 0.10),
              transparent);
  transform: scaleX(0);
  transform-origin: left center;
  opacity: 0;
}
body.page-loaded .ljd-page .ljd-hero .ljd-rule,
.ljd-page .reveal-on-scroll.visible .ljd-rule {
  animation: gt-bc-rule 900ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* ── 4b. Medallion separators ─────────────────────────────
   The crest flanks its monogram with two stacks of three gold discs. Three
   discs, built in CSS — no image, no Material Symbol.

   .vitola-separator ships at opacity:0.3, which was tuned for an opaque
   --color-primary glyph. Left in place it would multiply against the discs'
   own 0.55 alpha and land near 0.16 — much fainter than the mark it replaces.
   The container is reset to 1 here so the specified 0.55 is what actually
   renders. */
.ljd-page .vitola-separator {
  opacity: 1;
  align-items: center;
  padding: 0.75rem 0;
}
.ljd-page .ljd-medallion {
  position: relative;
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(202, 152, 69, 0.55);
}
.ljd-page .ljd-medallion::before,
.ljd-page .ljd-medallion::after {
  content: "";
  position: absolute;
  top: 0;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(202, 152, 69, 0.55);
}
.ljd-page .ljd-medallion::before { left: -11px; }
.ljd-page .ljd-medallion::after  { left:  11px; }

/* ── 4c. The diamond ──────────────────────────────────────
   The joya itself — the only cool note in an entirely warm palette. Used
   exactly ONCE on the page, beside the hero eyebrow. A second instance turns
   it into a motif and it stops reading as a detail. */
.ljd-page .ljd-gem {
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-left: 0.7rem;
  vertical-align: middle;
  transform: rotate(45deg);
  background: linear-gradient(135deg, #dceaf7 0%, #a9c6e4 45%, #6f93bb 100%);
  box-shadow: 0 0 6px rgba(190, 219, 245, 0.55);
}

/* ── 4d. Smoke ────────────────────────────────────────────
   Reuses .smoke-element and its smoke-drift keyframe; retinted from the stock
   cool blue to the page's gold. No new keyframe.

   The two overrides below are a compositing fix, not a look change — see
   SECTION 11. components.css ships this element at `inset: -100%` (three times
   its parent on both axes) with `filter: blur(48px)`, animated forever. On a
   phone that is a 1125×1510 CSS-pixel filtered layer — 61MB of GPU raster at
   DPR 3, the largest single surface on the page — and the blur is applied to a
   radial gradient, which a blur cannot meaningfully change. Both the size and
   the filter exist to keep a blurred edge out of frame; with no blur, neither
   is needed. The gradient's own `transparent` stop does that work instead. */
.ljd-page .smoke-element {
  /* Enough margin for smoke-drift's 100px translate, and no more. */
  inset: -18%;
  background: radial-gradient(ellipse at center, rgba(197, 160, 89, 0.07), transparent 100%);
  filter: none;
}


/* ══════════════════════════════════════════════════════════
   SECTION 5: TASTING PROFILE
   ══════════════════════════════════════════════════════════ */
.ljd-page .ljd-tasting {
  position: relative;
  isolation: isolate;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  padding: 7rem 1.5rem;
  margin-bottom: 6rem;
}

/* Its own positioned sibling, not a background on the content box. */
.ljd-page .ljd-tasting-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: url("../../assets/images/ljd-tasting-1920.webp");
  background-size: cover;
  background-position: center;
  opacity: 0.10;
  pointer-events: none;
}

.ljd-page .ljd-tasting-inner {
  position: relative;
  z-index: 1;
  max-width: 46rem;
  margin: 0 auto;
  text-align: center;
}

.ljd-page .ljd-tasting-notes {
  margin: 3.5rem 0 0;
  display: flex;
  flex-direction: column;
  gap: 2rem;
  text-align: left;
}

.ljd-page .ljd-tasting-note {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.4rem;
}

.ljd-page .ljd-tasting-name {
  font-family: var(--font-headline);
  font-size: 1.15rem;
  color: #e8dcc4;
  letter-spacing: 0.01em;
}

.ljd-page .ljd-tasting-descriptor {
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--color-on-surface-variant);
}

/* Flat meter. Same two-token fill .gt-card-strength-fill uses — that rule
   lives in fuse-search.css, which only collection.html loads, so the
   declaration is repeated here rather than inherited. Its border-radius and
   box-shadow glow are deliberately NOT carried over: this page is square and
   unlit. */
.ljd-page .ljd-tasting-meter {
  display: block;
  height: 4px;
  margin-top: 0.55rem;
  background: var(--color-surface-variant);
  overflow: hidden;
}
.ljd-page .ljd-tasting-fill {
  display: block;
  height: 100%;
  background: linear-gradient(to right, var(--color-primary), var(--color-primary-container));
}

.ljd-page .ljd-tasting-axes {
  margin-top: 4rem;
  display: flex;
  flex-direction: column;
  gap: 1.6rem;
  text-align: left;
}

.ljd-page .ljd-tasting-axis-label {
  display: block;
  font-size: 0.7rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  font-weight: 700;
  color: rgba(202, 152, 69, 0.92);
}

.ljd-page .ljd-tasting-axis-value {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.8rem;
  color: var(--color-on-surface-variant);
}

@media (min-width: 768px) {
  .ljd-page .ljd-tasting-notes {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2.5rem 3rem;
  }
}


/* ══════════════════════════════════════════════════════════
   SECTION 6: SUSPENSION BAND

   A single lit object floating in a dark room. Three layers, still STATIC —
   the scroll coupling described in the brief has not been approved, and
   scroll-linked parallax exists nowhere else on this site. The layer
   structure and z-indexes are kept intact so the coupling can be added later
   without re-cutting the markup.

   WHY THE PLATE IS NO LONGER THE PHOTOGRAPH
   ─────────────────────────────────────────
   The first cut painted ljd-suspension-1920.webp TWICE in the same band:
   once `contain` (the object, 562px — only 39% of a 1440px band) and once
   `cover` behind it (the same frame at 1440×1799, a 2.56× enlargement of the
   same crop). Both were sharp, so the crest, the lid and the cigar row all
   read twice at two different scales, and the `contain` layer's rectangle cut
   two hard vertical lines through the enlargement it sat on. That is the
   blurred-album-art backdrop trick without the blur, and no amount of tuning
   opacity fixes it — the subject cannot be its own set dressing.

   What replaces it is light, not more photograph. The plate is now a warm
   pool with a grounding shadow under the object; the object is the only
   photographic element in the band. The atmosphere that used to come from
   the duplicate now comes from the page's own fixed plate stack, which
   already cross-fades .ljd-plate--lounge up to 0.16 behind this exact
   section (the markup carries data-ljd-plate="lounge"). The duplicate was
   competing with a background that was already there.

   WHY THE BAND IS MASKED RATHER THAN CAPPED
   ─────────────────────────────────────────
   The band's top and bottom used to be razor cuts against flat surface. The
   obvious fix — fading the band's own edges to an opaque var(--color-surface)
   — produces a REVERSE seam here, because the fixed lounge plate sits behind
   the band AND behind the sections either side of it: an opaque cap would
   render the band's edge measurably darker than the page beside it. Masking
   the whole section instead dissolves every layer inside it at once and lets
   whatever is behind carry straight through. The section is decorative and
   aria-hidden, so it has no text to lose to a mask.
   ══════════════════════════════════════════════════════════ */
.ljd-page .ljd-suspension {
  position: relative;
  isolation: isolate;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  /* 84svh, not the original 78: the art is 4:5 and its subject fills only the
     middle ~65% of the frame, so a short band forces the object to compete
     with its own edge fades. The extra height buys the negative space that
     makes it read as displayed rather than cropped. */
  min-height: 84svh;
  margin-bottom: 6rem;
  overflow: hidden;

  /* The seam treatment. Both edges dissolve over a tenth of the band height,
     so the band has no boundary — it is a brightening of the page, not a
     panel laid on top of it. */
  -webkit-mask-image: linear-gradient(to bottom,
              transparent 0%, #000 10%, #000 90%, transparent 100%);
          mask-image: linear-gradient(to bottom,
              transparent 0%, #000 10%, #000 90%, transparent 100%);
}

.ljd-page .ljd-suspension-plate,
.ljd-page .ljd-suspension-box,
.ljd-page .ljd-suspension-debris {
  position: absolute;
  inset: 0;
  background-repeat: no-repeat;
  pointer-events: none;
}

/* ── z-0: the light ──────────────────────────────────────────
   Three gradients, no bitmap: the pool the object stands in, an elliptical
   contact shadow beneath it so it has a floor to float above, and an outer
   falloff so the pool has a rim instead of an edge. Alphas stay inside the
   ceiling the rest of this page observes — nothing here is meant to be looked
   at directly. */
.ljd-page .ljd-suspension-plate {
  z-index: 0;
  background-image:
    radial-gradient(ellipse 34% 42% at 50% 44%,
      rgba(216, 176, 104, 0.17) 0%,
      rgba(150, 112, 60, 0.08) 48%,
      rgba(24, 18, 16, 0) 76%),
    radial-gradient(ellipse 17% 5% at 50% 82%,
      rgba(0, 0, 0, 0.60) 0%,
      rgba(0, 0, 0, 0.26) 48%,
      rgba(0, 0, 0, 0) 100%),
    radial-gradient(ellipse 50% 66% at 50% 45%,
      rgba(10, 8, 6, 0) 44%,
      rgba(10, 8, 6, 0.56) 82%,
      rgba(10, 8, 6, 0.78) 100%);
}

/* ── z-1: the object ─────────────────────────────────────────
   Sized by WIDTH, not by height. `contain` fitted the art to whichever axis
   bound first, which on a wide band meant 562px — 39% of a 1440px frame, and
   the number changed with viewport height. Driving it from the width keeps
   the object a fixed share of the band at every size, and lets the mask stops
   below be derived from that one number instead of being hand-tuned to one
   viewport. Vertical overflow is intended: it crops the dead space the frame
   carries above and below the box.

   --ljd-obj-w is the single source of truth. The image's left and right edges
   fall at (100% - w)/2, so the mask is transparent exactly there and ramps in
   over 5%: the art's rectangle can never show an edge, whatever w becomes,
   and the smoke and floating debris drift off into the dark instead of being
   clipped by a straight line.

   Nothing masks the TOP and BOTTOM edges, so the art has to be guaranteed
   taller than the band or those two edges draw hard lines across it — which
   is exactly what a tall viewport did on the first pass, and what a phone did
   badly (a 375-wide band is 682 tall, and 4:5 art can only reach 469). Hence
   the svh floor inside max(): the band is 84svh and the art is 4:5, so any
   width at or above 84 × 0.8 = 67.2svh overflows it at every viewport height.
   The percentage governs when the viewport is wide relative to its height,
   the svh floor when it is tall. Change the band's height and this floor has
   to move with it. */
.ljd-page .ljd-suspension-box {
  /* clamp: no smaller than a stamp on a narrow desktop, no wider than the
     band's height allows on an ultrawide. max(): never shorter than the band.
     If the result exceeds 100%, --ljd-obj-edge goes negative and the mask
     correctly becomes a no-op — the art already bleeds past both sides. */
  --ljd-obj-w: max(clamp(300px, 48%, 700px), 68svh);
  --ljd-obj-edge: calc((100% - var(--ljd-obj-w)) / 2);

  z-index: 1;
  background-image: url("../../assets/images/ljd-suspension-1920.webp");
  background-size: var(--ljd-obj-w) auto;
  /* 44%, not 50%: the subject sits at 47% of its own frame, and the band is
     sometimes shorter than the art and sometimes taller. This reads correctly
     in both regimes — it crops from below when the art overflows, and holds
     the object just above centre when the band has room to spare. */
  background-position: center 44%;
  opacity: 0.96;

  -webkit-mask-image: linear-gradient(to right,
              transparent var(--ljd-obj-edge),
              #000 calc(var(--ljd-obj-edge) + 5%),
              #000 calc(100% - var(--ljd-obj-edge) - 5%),
              transparent calc(100% - var(--ljd-obj-edge)));
          mask-image: linear-gradient(to right,
              transparent var(--ljd-obj-edge),
              #000 calc(var(--ljd-obj-edge) + 5%),
              #000 calc(100% - var(--ljd-obj-edge) - 5%),
              transparent calc(100% - var(--ljd-obj-edge)));
}

/* ── z-2: the room ───────────────────────────────────────────
   Sits above the object so the vignette closes over it. It no longer has a
   seam to hide, so it is lighter than the 0.55 it carried before. */
.ljd-page .ljd-suspension-debris {
  z-index: 2;
  background-image: radial-gradient(ellipse 60% 68% at 50% 44%,
              rgba(9, 7, 6, 0) 44%,
              rgba(9, 7, 6, 0.24) 100%);
}

/* Phones. Two things change. The band comes down to 62svh — 84 was most of a
   phone screen spent on one decorative frame — and the object goes past full
   width, so 4:5 art in a 0.55-aspect band bleeds off both sides instead of
   sitting in it with four visible edges. The svh floor moves with the band
   (62 × 0.8 = 49.6, so 51svh). The mask stops re-derive themselves from
   --ljd-obj-w and go inert at over 100%, so only that one value changes. */
@media (max-width: 767px) {
  .ljd-page .ljd-suspension {
    min-height: 62svh;
  }
  .ljd-page .ljd-suspension-box {
    --ljd-obj-w: max(112%, 51svh);
    background-image: url("../../assets/images/ljd-suspension-800.webp");
    background-position: center 46%;
  }
  .ljd-page .ljd-suspension-plate {
    background-image:
      radial-gradient(ellipse 60% 34% at 50% 44%,
        rgba(216, 176, 104, 0.17) 0%,
        rgba(150, 112, 60, 0.08) 48%,
        rgba(24, 18, 16, 0) 76%),
      radial-gradient(ellipse 30% 4% at 50% 80%,
        rgba(0, 0, 0, 0.60) 0%,
        rgba(0, 0, 0, 0.26) 48%,
        rgba(0, 0, 0, 0) 100%),
      radial-gradient(ellipse 82% 62% at 50% 45%,
        rgba(10, 8, 6, 0) 44%,
        rgba(10, 8, 6, 0.56) 82%,
        rgba(10, 8, 6, 0.78) 100%);
  }
}


/* ══════════════════════════════════════════════════════════
   SECTION 7: CTA
   ══════════════════════════════════════════════════════════ */
.ljd-page .brand-cta {
  position: relative;
  z-index: 1;
}


/* ══════════════════════════════════════════════════════════
   SECTION 7b: THE CLOSING RAMP

   The page used to end on two stacked edges: the CTA sat on the fixed lounge
   plate at full strength, and then the shared footer opened with a flat
   1px rule and a tonal step from #181210 to its own #130d0b. Two hard lines
   inside 200px, at the one place the eye is already looking for an ending.

   This replaces both with a single ~30rem descent. The ramp is anchored to
   the bottom of .brand-main, runs the full viewport width, and resolves to
   the footer's exact colour — so by the time the footer starts there is no
   step left to see. It also quiets the fixed plate behind the CTA, which is
   what let that fold read as busy.

   z-index:-1 keeps it behind main's own content: .brand-main carries
   z-index:20, so it opens a stacking context and a negative child stays
   inside it. The suspension band overlaps the top of the ramp by ~100px and
   is unaffected for the same reason — the band paints above it.
   ══════════════════════════════════════════════════════════ */
.ljd-page .brand-main::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: 100vw;
  bottom: 0;
  height: 30rem;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(to bottom,
              rgba(19, 13, 11, 0) 0%,
              rgba(19, 13, 11, 0.32) 46%,
              rgba(19, 13, 11, 0.76) 78%,
              #130d0b 100%);
}

/* The shared footer's own rule is a flat full-width hairline at 0.15 stone.
   With the ramp above it there is no longer a colour step for it to conceal,
   so it becomes the page's fourth gold rule instead — same language as
   .ljd-rule, fading out at both ends rather than running to the edges.
   Scoped to .ljd-page: .site-footer is shared by ~248 files. */
.ljd-page .site-footer {
  border-top: 0;
}
.ljd-page .site-footer::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(to right,
              transparent 0%,
              rgba(202, 152, 69, 0.22) 28%,
              rgba(202, 152, 69, 0.22) 72%,
              transparent 100%);
}


/* ══════════════════════════════════════════════════════════
   SECTION 8: CARD THEMES
   Fitted to the envelope the existing .theme-* blocks occupy — gradient
   alphas 0.38–0.65, four separately-coloured borders, one inset highlight,
   one drop shadow, one hover glow.

   On the green: the extracted crest green is #313e23, and .theme-plasencia's
   gradient origin is rgba(44,54,36,0.38) — nearly the same colour, on the
   site's most developed brand page. The two are held apart by keeping this
   one a step darker and lower-alpha, and by giving it gold borders and a gold
   hover glow where Plasencia has none. Do not raise the green's alpha or
   lighten it; that separation is load-bearing.

   Both variants share every border, shadow and text colour. Only the field
   differs. Radius stays at .showcase-card's 2px — nothing on this page rounds.
   ══════════════════════════════════════════════════════════ */

/* -- Line heads ------------------------------------------------
   The lineup is two lines of three, not one stack of six: the black box is
   the Maduro, the red is the Natural. Each group gets a rule and a label so
   the split is legible without reading every card.

   .brand-tagline supplies the type. This only supplies the gold and the
   spacing, because brand.css sets the tagline stone-grey for a hero eyebrow
   sitting on photography, and here it sits on the page surface between two
   card groups. Same override the hero eyebrow makes, same two properties --
   and, like the eyebrow, it does not compensate the 0.4em tracking on the
   trailing character. That is the page convention, not an oversight.
   -- */
.ljd-page .ljd-line-head {
  margin: 0 auto 2.5rem;
  text-align: center;
}
/* Only between groups -- the first head takes its top spacing from the
   statement band above it, which already carries its own. */
.ljd-page .showcase-stack + .ljd-line-head {
  margin-top: 5.5rem;
}
.ljd-page .ljd-line-head .ljd-rule {
  margin-bottom: 1.5rem;
}
.ljd-page .ljd-line-head-title {
  color: rgba(202, 152, 69, 0.92);
  margin-bottom: 0;
}

/* ── La Joya Dominicana — red lacquer ────────────────────────── */
.ljd-page .theme-lajoya-red {
  background: linear-gradient(140deg,
              rgba(92, 14, 14, 0.42) 0%,
              rgba(48, 10, 9, 0.50) 50%,
              rgba(18, 7, 6, 0.62) 100%);
  backdrop-filter: blur(24px);
  border-top:    1px solid rgba(202, 152, 69, 0.30);
  border-left:   1px solid rgba(202, 152, 69, 0.13);
  border-right:  1px solid rgba(0, 0, 0, 0.35);
  border-bottom: 1px solid rgba(0, 0, 0, 0.42);
  box-shadow: inset 0 1px 0 rgba(225, 211, 167, 0.14),
              0 12px 36px rgba(0, 0, 0, 0.55);
}
/* Gated, like all 23 theme-hover blocks in components.css. This page's two
   were the only ones that were not, which meant the glow latched on after a
   tap on a touch device and never cleared. */
@media (hover: hover) {
  .ljd-page .theme-lajoya-red:hover {
    box-shadow: 0 0 48px rgba(202, 152, 69, 0.20),
                0 18px 46px rgba(0, 0, 0, 0.58),
                inset 0 1px 0 rgba(225, 211, 167, 0.18);
  }
}

/* ── La Joya Dominicana — black lacquer ──────────────────────── */
.ljd-page .theme-lajoya-black {
  background: linear-gradient(140deg,
              rgba(38, 48, 34, 0.40) 0%,
              rgba(20, 26, 19, 0.48) 50%,
              rgba(9, 11, 8, 0.62) 100%);
  backdrop-filter: blur(24px);
  border-top:    1px solid rgba(202, 152, 69, 0.30);
  border-left:   1px solid rgba(202, 152, 69, 0.13);
  border-right:  1px solid rgba(0, 0, 0, 0.35);
  border-bottom: 1px solid rgba(0, 0, 0, 0.42);
  box-shadow: inset 0 1px 0 rgba(225, 211, 167, 0.14),
              0 12px 36px rgba(0, 0, 0, 0.55);
}
@media (hover: hover) {
  .ljd-page .theme-lajoya-black:hover {
    box-shadow: 0 0 48px rgba(202, 152, 69, 0.20),
                0 18px 46px rgba(0, 0, 0, 0.58),
                inset 0 1px 0 rgba(225, 211, 167, 0.18);
  }
}

/* ── Shared card text ────────────────────────────────────────── */
.ljd-page .theme-lajoya-red   .showcase-card-title,
.ljd-page .theme-lajoya-black .showcase-card-title    { color: #e8dcc4; }
.ljd-page .theme-lajoya-red   .showcase-card-subtitle,
.ljd-page .theme-lajoya-black .showcase-card-subtitle { color: rgba(202, 152, 69, 0.92); }
.ljd-page .theme-lajoya-red   .showcase-card-desc,
.ljd-page .theme-lajoya-black .showcase-card-desc     { color: var(--color-on-surface-variant); }


/* ══════════════════════════════════════════════════════════
   SECTION 8b: VITOLA CARD IMAGERY
   The shared card styling sizes photography conservatively, and on this page
   it left the box floating small inside a mostly empty card. Three things in
   components.css cause that, and all three are overridden below:

     • mobile pins the image to `height: 16rem; width: auto` with
       `object-fit: contain`, so a 4:5 portrait renders ~205px wide inside a
       ~340px card;
     • desktop caps it at `max-height: 24rem`, again `contain`, so it never
       fills its half of the row;
     • a `radial-gradient(circle, black 60%, transparent 100%)` mask feathers
       the edges away, which shrinks the apparent size further.

   The replacement gives the image its own aspect-ratio box and lets it fill
   that box with `object-fit: cover`. The ratio is 4:5 because the source
   frames are exactly 4:5 (3278×4096, converted to 800×1000) — matching them
   means `cover` crops NOTHING while still filling the box edge to edge. Do
   not change this ratio without re-cropping the art: any other value silently
   starts cutting the box out of frame.
   ══════════════════════════════════════════════════════════ */

/* The anchor and <picture> are intermediate elements between the flex
   container and the image; both have to stretch or the img has nothing to
   fill. */
.ljd-page .showcase-card-image .showcase-image-link,
.ljd-page .showcase-card-image picture {
  display: block;
  width: 100%;
  height: 100%;
}

.ljd-page .showcase-card-image img {
  width: 100%;
  height: 100%;
  max-height: none;
  object-fit: cover;
  object-position: center;
  /* The circular mask is what made the art read as a small floating vignette.
     A full-bleed plate wants a clean edge; the card's own gold hairline and
     2px radius do the framing. */
  -webkit-mask-image: none;
  mask-image: none;
}

/* ── Mobile: the image becomes the top of the card, edge to edge ──────────
   .showcase-card carries `padding: 0 2rem`, so the container is pulled back
   out by that amount on each side to reach the card's real edges. */
.ljd-page .showcase-card-image {
  position: relative;
  width: calc(100% + 4rem);
  margin: 0 -2rem;
  padding-top: 0;
  aspect-ratio: 4 / 5;
}

/* ── 8c. HOVER: WHY THIS PAGE DOES NOT SCALE THE IMAGE ───────────────────
   Reported 2026-08-28: the card image visibly stretches while two-finger
   scrolling. It does, and it is not a compositor bug — it is a hover state
   firing when nobody meant to hover. A trackpad scroll leaves the pointer
   parked while the page travels under it, so every card in turn takes
   :hover, runs components.css's `transform: scale(1.05)` over its 0.7s
   transition, and gets interrupted by the next card doing the same. Verified
   by instrumenting the cards: one stationary pointer over the stack fires
   mouseenter, starts the image transform and switches the 48px glow on.

   That rule is sized for the stock card, where the image is a 16rem-tall
   `object-fit: contain` thumbnail. Section 8b above made it a full-bleed 4:5
   plate instead — 509×636 on a 1440 viewport, from a 512×639 source. So the
   scale was already upsampling past the asset's native resolution before any
   of this, and removing it costs no fidelity that existed.

   The affordance is replaced, not deleted: a warm light wash crossing the
   plate. It animates `opacity` on a pseudo-element, which the compositor can
   do without re-rasterising the photograph — the whole point. Do not
   reintroduce a transform or a filter on this image.
   ──────────────────────────────────────────────────────────────────────── */
@media (hover: hover) {
  .ljd-page .showcase-card:hover .showcase-card-image img {
    transform: none;
  }
}

.ljd-page .showcase-card-image img {
  transition: none;
}

.ljd-page .showcase-card-image::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s ease;
  background: linear-gradient(135deg,
              rgba(214, 175, 103, 0.18) 0%,
              rgba(202, 152, 69, 0.06) 42%,
              rgba(0, 0, 0, 0) 74%);
}

@media (hover: hover) {
  .ljd-page .showcase-card:hover .showcase-card-image::before {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ljd-page .showcase-card-image::before {
    transition: none;
  }
}


/* Softens the hand-off from photograph to title block. Sits above the image
   but below nothing else, and never intercepts the link underneath. */
.ljd-page .showcase-card-image::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 30%;
  background: linear-gradient(to bottom, transparent, rgba(9, 7, 6, 0.60));
  pointer-events: none;
}

@media (min-width: 768px) {
  /* Row layout: drop the card's own side padding so the photograph runs to
     the card edge, and give the text column its padding back instead. With
     `gap: 0` the two halves meet cleanly whichever way .reverse flips them. */
  .ljd-page .showcase-card {
    padding: 0;
    gap: 0;
  }

  .ljd-page .showcase-card-image {
    width: 54%;
    margin: 0;
    aspect-ratio: 4 / 5;
  }

  .ljd-page .showcase-card-body {
    width: 46%;
    padding: 3rem;
  }

  /* Vertical scrim is a stacked-layout device; side by side there is nothing
     below the image to blend into. */
  .ljd-page .showcase-card-image::after {
    content: none;
  }
}


/* ══════════════════════════════════════════════════════════
   SECTION 9: CONTENT PLACEHOLDERS — LIVE AGAIN

   Re-enabled 2026-08-28 at the operator's request. History: the brief asked
   for loud on-page markers so no slot could ship blank by accident; they were
   stripped to HTML comments on 2026-08-27, and a comment is invisible in a
   browser, so an empty page looked finished. They are back, and they are
   deliberately loud.

   Two shapes. .ljd-slot is the original inline marker, for a word or a phrase
   inside a line that otherwise exists. .ljd-slot-block is the new one, for a
   whole paragraph that does not exist yet: it names itself from data-slot, so
   a placeholder says what belongs in it rather than just that something does.

   EVERY ONE OF THESE MUST BE GONE BEFORE LAUNCH. They are not a copy style —
   replacing a slot means deleting the element and putting the real element in
   its place (the data-slot label says which element that is).
   ══════════════════════════════════════════════════════════ */
.ljd-page .ljd-slot {
  display: inline-block;
  padding: 0.15em 0.5em;
  border: 1px dashed rgba(202, 152, 69, 0.45);
  background: rgba(202, 152, 69, 0.07);
  color: rgba(214, 175, 103, 0.95);
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  line-height: 1.5;
}

.ljd-page .ljd-slot-block {
  display: block;
  max-width: 42rem;
  margin: 0 auto;
  padding: 1rem 1.25rem 1.15rem;
  border: 1px dashed rgba(202, 152, 69, 0.40);
  border-radius: 2px;
  background: rgba(202, 152, 69, 0.045);
  color: rgba(214, 175, 103, 0.72);
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.88rem;
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: 0.01em;
  text-align: left;
  text-wrap: pretty;
}

/* The label. content: attr() is safe here — it is authored markup, not user
   input, and it is decorative, so it is also announced to nobody. */
.ljd-page .ljd-slot-block::before {
  content: attr(data-slot);
  display: block;
  margin-bottom: 0.45rem;
  font-family: var(--font-label, var(--font-body));
  font-size: 0.58rem;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(202, 152, 69, 0.92);
}

/* Inside a vitola card the slot has to live in a 46%-wide text column, so it
   drops the centring and the max-width the page-level slots use. */
.ljd-page .showcase-card-body .ljd-slot-block {
  max-width: none;
  margin-top: 1.25rem;
  font-size: 0.82rem;
}


/* ── PARKED 2026-08-28 ────────────────────────────────────────────────────
   Hidden at the operator's request, same day they went back in. The markup
   and the labels stay in place, so bringing them back is deleting this one
   block rather than re-authoring seven slots. The 2026-08-27 round stripped
   them to HTML comments instead, which is why they had to be rebuilt from
   scratch this time — do not do that again.

   .ljd-statement is parked with them: it holds nothing but its slot, so
   hiding only the slot would leave an orphaned gold rule above 6rem of dead
   space. When the statement line is written, delete BOTH rules below.
   ──────────────────────────────────────────────────────────────────────── */
.ljd-page .ljd-slot,
.ljd-page .ljd-slot-block {
  display: none;
}

.ljd-page .ljd-statement {
  display: none;
}


/* ══════════════════════════════════════════════════════════
   SECTION 9b: STATEMENT BAND
   One line of positioning copy, set large, between the overview and the
   vitola stack. Every premium brand page this one is modelled on has a beat
   like this — the page currently goes from a title straight to a product
   list. Added 2026-08-28 as an empty slot, not as copy.
   ══════════════════════════════════════════════════════════ */
.ljd-page .ljd-statement {
  max-width: 46rem;
  margin: 0 auto 6rem;
  padding: 0 1.5rem;
  text-align: center;
}

.ljd-page .ljd-statement-quote {
  margin: 0;
  font-family: var(--font-headline);
  font-size: clamp(1.3rem, 3.1vw, 2rem);
  line-height: 1.36;
  letter-spacing: 0.005em;
  color: #e8dcc4;
  text-wrap: balance;
}

.ljd-page .ljd-statement-attrib {
  display: block;
  margin-top: 1.4rem;
  font-family: var(--font-label, var(--font-body));
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: rgba(202, 152, 69, 0.85);
}

@media (max-width: 767px) {
  .ljd-page .ljd-statement {
    margin-bottom: 4rem;
  }
}


/* ══════════════════════════════════════════════════════════
   SECTION 10: REDUCED MOTION
   brand.css has no prefers-reduced-motion block at all — its Ken Burns and
   reveals run regardless of the preference. That gap is not replicated here:
   every animation this page introduces is switched off below.
   ══════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {

  /* Plate cross-fades collapse to the hero plate, shown statically.
     js/lajoya.js checks the same query and never attaches its observer, so
     nothing writes an inline opacity that would outrank these rules. */
  .ljd-page .ljd-plate {
    transition: none;
    transform: none;
  }
  body.page-loaded .ljd-page .ljd-plate {
    transform: none;
  }
  .ljd-page .ljd-plate--hero {
    opacity: 0.14;
  }
  .ljd-page .ljd-plate--heritage,
  .ljd-page .ljd-plate--humidor,
  .ljd-page .ljd-plate--lounge {
    opacity: 0;
  }

  /* Gold rules render at rest, no wipe. */
  .ljd-page .ljd-rule,
  body.page-loaded .ljd-page .ljd-hero .ljd-rule,
  .ljd-page .reveal-on-scroll.visible .ljd-rule {
    animation: none;
    transform: scaleX(1);
    opacity: 1;
  }

  /* Smoke, scroll cue, suspension layers: still. */
  .ljd-page .smoke-element,
  .ljd-page .ljd-hero-cue {
    animation: none;
  }
  .ljd-page .ljd-suspension-plate,
  .ljd-page .ljd-suspension-box,
  .ljd-page .ljd-suspension-debris {
    transform: none;
    transition: none;
  }
}


/* ══════════════════════════════════════════════════════════
   SECTION 11: COMPOSITING BUDGET

   Reported 2026-08-28: an intermittent flat olive rectangle over part of a
   vitola card while scrolling on a phone. That shape is a card whose image
   tiles were evicted before they could be re-rastered, leaving the card's own
   backdrop-filtered background showing through — the olive is the aging-room
   photograph blurred flat. The same session reproduced a sibling symptom in
   the preview pane: the whole viewport painted twice, tiled 2×2, immediately
   after a render timeout. Both are raster starvation, not layout bugs.

   Measured at 375×812, DPR 2, this page promoted ~95MB of composited layers
   — about 215MB on a DPR-3 phone, well past what a mobile browser will hold,
   so tiles get dropped and repainted continuously while scrolling. Three of
   those layers were paying for nothing:

     .smoke-element   25.9MB  animated 48px blur over a radial gradient (§4d)
     .brand-main      19.8MB  will-change:transform, for a transform that is
                              applied to #overscroll-canvas, not to it
     .ljd-suspension-box 2.9MB  will-change:transform, for a parallax that was
                              never approved and does not exist

   None of the three changes a pixel. .smoke-element is still overridden here
   rather than at source, because components.css is loaded by ~250 files behind
   a ?v= string and the blast radius is not worth it. .brand-main WAS fixed at
   source on 2026-08-28 — brand.css no longer sets will-change at all, and the
   local override that used to sit in this section is gone with it, so there is
   nothing left here to keep in sync.

   What is deliberately KEPT, and why the obvious fourth candidate is not on
   the list: the showcase cards' backdrop-filter: blur(24px) is the layer the
   reported artifact actually appeared ON, and it is 2.3MB per card, so it
   looks like the first thing to cut. It is not. A/B'd on 2026-08-28 with the
   cards over the lounge plate: with the blur off, the plate's "LA JOYA
   DOMINICANA" lettering and the box edges read straight through the card body
   as legible text. The blur is what turns a 16%-opacity photograph behind a
   40-62% alpha panel into a clean field. It is load-bearing — do not remove it
   on the theory that blurring a faint image is a no-op. The four cross-fading
   plates in .ljd-bg-stack (~4.6MB each while transitioning) stay too; they are
   this page's signature.
   ══════════════════════════════════════════════════════════ */

