#preview-container {
    background: #111;
    border-radius: 8px;
    padding: 15px;
    width: 100%;
    display: flex;
    justify-content: center;
}
 
#cigar-svg {
    width: 100%;
    height: auto;
    max-height: 400px;
}
 
.preview-panel {
    background-color: #f8f9fa;
    border-radius: 0 0.375rem 0.375rem 0;
}

/* Hero banner images. Replaces a hardcoded inline `height: 250px` that applied
   at every width - fine on desktop, far too tall on a phone where the three
   columns are only ~110px wide each.

   Height stays FIXED per breakpoint rather than proportional: the source
   photos are a mix of landscape and portrait at assorted ratios, and a fixed
   box + object-fit: cover crops them all to identical dimensions. Letting the
   height float (aspect-ratio) made them look uneven and far too small.
   768px and up is unchanged from the original 250px. */
.hero-banner-img {
    width: 100%;
    height: 150px;
    object-fit: cover;
}

@media (min-width: 576px) {
    .hero-banner-img { height: 200px; }
}

@media (min-width: 768px) {
    .hero-banner-img { height: 250px; }
}

/* The opening illustration on /instructions is a tall 793x1200 line drawing.
   It needs a cap so it doesn't dominate the column on a wide screen, but the
   cap must never beat the container. This used to be an inline
   style="max-width:420px", and an inline style overrides .img-fluid's
   max-width:100% outright - so on a phone (column ~330-360px) the image drew
   out to 420px and pushed the whole page into horizontal scroll, which made
   every other image on the page look like it overflowed too. width:100% is
   what makes the container win on narrow screens; keep both declarations. */
.instructions-illustration {
    width: 100%;
    max-width: 420px;
}

/* Jump-link / deep-link targets on /molds and /instructions. Without this,
   following #parejo (or a per-mold #figurado-<id> link from elsewhere) scrolls
   the target flush to the top of the viewport - which is exactly where the
   sticky #cartAlert bar sits when the cart has items, hiding the heading behind
   it. Bootstrap has no scroll-margin utility. Harmless when the bar isn't
   showing. #opening-illustration matters most on mobile, where the right-hand
   column stacks below the entire text column. */
#parejo,
#torpedo,
#figurado,
#opening-illustration,
[id^="figurado-"] {
    scroll-margin-top: 5rem;
}

/* Navbar brand layout. .navbar-brand is white-space: nowrap, so the full
   "Custom Cigar Molds - Adam Ziegler" can neither wrap nor shrink - on a 360px
   phone it runs ~30-50px past the container, which scrolls the whole page
   sideways and pushes the hamburger onto its own row.

   Below 460px the byline moves to its own line and the logo grows to fill the
   now two-line block. Above it, the original single line at 36px.

   The break is a flex column, not a wrap: nowrap would defeat a wrap, and a
   display:block child of an inline element splits the inline box awkwardly.
   Making .brand-text a flex container turns the title and the byline into two
   flex items that stack cleanly - and collapses the byline's leading space,
   which is why the second line reads "- Adam Ziegler" and not " - Adam
   Ziegler". At 460px it goes back to inline so that space returns and the two
   halves rejoin as one sentence. Bootstrap's smallest breakpoint is sm
   (576px), which is later than this needs. */
.brand-text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.brand-byline {
    font-size: 0.85rem;
}

.brand-logo {
    height: 48px;
}

@media (min-width: 460px) {
    .brand-text   { display: inline; line-height: inherit; }
    .brand-byline { font-size: inherit; }
    .brand-logo   { height: 36px; }
}

/* Master mold list rows on /molds-list. script.js makes the whole row open the
   mold's page (the real <a> stays in the first cell for crawlers, keyboard and
   middle-click), so the row needs to look clickable. Bootstrap has no cursor
   utility - same reason .mold-gallery-track below carries one. */
#moldsListTable tbody tr {
    cursor: pointer;
}

/* Mold card images on /molds - the parejo and torpedo estimator previews and
   every figurado listing. Fixed height (not a ratio) so all the cards in a row
   line up whatever their column width, with .object-fit-cover on the markup
   doing the cropping. Bootstrap has no height utility at this value, which is
   the only reason this rule exists; the backdrop and the fit are .bg-dark and
   .object-fit-cover utilities on the elements themselves.

   Also used by the two placeholder divs so an image-less card is exactly as
   tall as one with an image. */
.mold-card-img {
    height: 220px;
}

/* Mold gallery on /mold/<slug>-<id>. Almost all of this is Bootstrap utilities
   on the markup - .ratio-16x9 for the box, .object-fit-contain / -cover for the
   fit, .bg-dark for the backdrop. Only the two things 5.3.8 has no utility for
   live here: cursor (there are no cursor utilities at all, checked against the
   real CDN file) and the thumb's fixed 72px square. */
/* The gallery track on /mold/... - every image side by side, moved with a
   transform so a drag can follow the finger. Bootstrap has no utility for any
   of this: no flex-basis:100%, no touch-action, no transition helpers.

   touch-action: pan-y is the whole reason vertical scrolling still works. It
   tells the browser to keep handling up/down itself and hand us left/right,
   so the drag listeners never call preventDefault and can stay passive. */
/* The gesture surface - a fixed window over the strip. touch-action and every
   touch listener live HERE and not on the track, and that distinction is the
   whole reason iOS works.

   WebKit derives an element's touch-event region from that element's own box.
   The track is translated, so from the second image onward its box sits outside
   the window, iOS stopped routing touches to it, and the gesture was handed to
   the page as a scroll - you could swipe exactly once, off the first image, on
   every iOS browser (Safari, Chrome and Brave on iPad are all WebKit). Blink
   recomputes those regions, which is why Android never showed it.

   The window never moves, so its region is always right. */
.mold-gallery-viewport {
    touch-action: pan-y;
    cursor: zoom-in;
}

.mold-gallery-track {
    display: flex;
    transition: transform .35s ease;
}

/* Suppresses the slide animation. Two uses, both needing an instant move:
   while a finger is down (the track must follow it exactly, and a transition
   would lag behind then coast past on release), and for the silent
   repositioning after a wrap-around, where the strip jumps back to the real
   index once the animation onto the parked slide has finished. */
.mold-gallery-track.no-anim {
    transition: none;
}

.mold-gallery-slide {
    flex: 0 0 100%;
    width: 100%;
    height: 100%;
}

/* The same strip inside the lightbox. On the page the track is a child of
   .ratio, which sizes it; here it has to fill its own window. Declared after
   .mold-gallery-track so the cursor wins on equal specificity - zoom-in is
   right on the page but wrong once you are already zoomed in. */
.mold-lightbox-track {
    width: 100%;
    height: 100%;
}

/* Declared after .mold-gallery-viewport so the cursor wins on equal
   specificity - zoom-in is right on the page but wrong once already zoomed in. */
.mold-lightbox-viewport {
    cursor: default;
}

/* Added by script.js only when there is more than one image, so a single-image
   gallery never advertises a drag it does not have. The page window keeps
   zoom-in either way - tapping it still opens the lightbox. */
.mold-lightbox-viewport.is-draggable {
    cursor: grab;
}

.mold-gallery-thumb {
    width: 72px;
    height: 72px;
    cursor: pointer;
}

/* The #cartAlert strip uses .sticky-top (z-index 1020), but Bootstrap's
   dropdown-menu is only z-index 1000 - so an open "Free STL Files" dropdown
   would render *behind* the strip whenever the cart is non-empty. Lifting the
   whole navbar above the strip fixes it for the dropdown and any future
   navbar overlay. */
.navbar {
    position: relative;
    z-index: 1021;
}