# Öne çıkan ürün: ücretsiz Shopify bölümü

> Galerisi, fiyatı, varyant düğmeleri, adet seçimi ve sepete ekle düğmesiyle tek ürün, her sayfada. JavaScript olmadan da çalışır; tüm metinler düzenlenebilir.

Öne çıkan ürün, seçtiğiniz tek bir ürünü görsel galerisi, fiyatı ve indirim etiketi, varyant düğmeleri, adet seçimi ve sepete ekle düğmesiyle her sayfaya yerleştiren ücretsiz bir Shopify bölümüdür. Form doğrudan Shopify sepetine gönderilir; bu yüzden JavaScript olmadan da çalışır, fiyat, stok durumu ve görsel de seçilen varyanta göre değişir. Online Store 2.0 temalarında uygulama olmadan çalışır.

- **Kategori:** Ürün ve koleksiyon keşfi
- **Kullanıldığı yerler:** Ana sayfa, Açılış sayfaları, Koleksiyon, Her sayfa
- **Okuduğu veri:** Tek ürün
- **Boyut:** 2 dosyada 41 KB, küçük bir betikle
- **Lisans:** MIT, © 2026 Lintel
- **Sayfa:** https://lintelagency.com/tr/kaynaklar/shopify-bolumleri/one-cikan-urun
- **Canlı demo:** https://lintelagency.com/resources/shopify-sections/demo/lib-featured-product.html
- **Eklenme tarihi:** 2026-11-02

## Ne işe yarar

- Ana sayfada, sayfadan ayrılmadan satın alınabilen öne çıkan ürün ya da en çok satan
- Tek bir ürün etrafında kurulan lansman ya da kampanya sayfası
- Anlattığı ürünü satan hediye rehberi, blog yazısı ya da Hakkımızda sayfası

## Tema düzenleyici ayarları

Bölüm tema düzenleyicide “Lib · Featured product” adıyla görünür. Kimlikler, türler, etiketler ve varsayılan değerler bölümün şemasından gelir. Etiketler tema düzenleyicide göründüğü gibi İngilizcedir.

### Product

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `product` | `product` | Product | – |  |
| `show_vendor` | `checkbox` | Show vendor | `true` |  |
| `heading_tag` | `select` | Product title tag | h2 | `h1`, `h2`, `h3`, `p` |
| `heading_size` | `select` | Product title size | medium | `small`, `medium`, `large` |
| `show_description` | `checkbox` | Show product description | `true` |  |
| `show_quantity` | `checkbox` | Show quantity selector | `true` |  |

### Gallery

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `show_thumbnails` | `checkbox` | Show thumbnails | `true` |  |
| `media_ratio` | `select` | Image shape | square | `adapt`, `square`, `portrait`, `landscape` |
| `corner_radius` | `range` | Corner radius | `12` | 0–32 px, step 2 |
| `details_label` | `text` | Details link label | View full details |  |
| `details_style` | `select` | Details link style | text | `primary`, `outline`, `text` |
| `details_new_tab` | `checkbox` | Open details link in a new tab | `false` |  |

### Shopper-facing words

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `button_label` | `text` | Add to cart button | Add to cart |  |
| `sold_out_label` | `text` | Sold out | Sold out |  |
| `unavailable_label` | `text` | Unavailable combination | Unavailable |  |
| `sale_badge_label` | `text` | Sale badge | Sale |  |
| `sale_price_label` | `text` | Sale price (screen readers) | Sale price |  |
| `regular_price_label` | `text` | Regular price (screen readers) | Regular price |  |
| `quantity_label` | `text` | Quantity (screen readers) | Quantity |  |
| `decrease_label` | `text` | Decrease quantity (screen readers) | Decrease quantity |  |
| `increase_label` | `text` | Increase quantity (screen readers) | Increase quantity |  |
| `thumbnail_label` | `text` | Thumbnail button (screen readers) | Show image |  |

### Layout

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `media_position` | `select` | Gallery position on desktop | left | `left`, `right` |
| `media_width` | `select` | Gallery width on desktop | half | `half`, `wide` |
| `mobile_order` | `select` | Order on mobile | media_first | `media_first`, `info_first` |
| `section_width` | `select` | Width | page | `page`, `full` |
| `text_alignment` | `select` | Text alignment on desktop | left | `left`, `center` |
| `text_alignment_mobile` | `select` | Text alignment on mobile | left | `left`, `center` |

### Colors

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `color_bg` | `color` | Background | #FBF8F4 |  |
| `color_text` | `color` | Text | #231F1B |  |
| `color_accent` | `color` | Add to cart button, sale price and badge | #7C2D12 |  |
| `color_accent_text` | `color` | Text on button and sale badge | #FFFFFF |  |
| `color_border` | `color` | Borders | #D9D2C8 |  |

### Spacing, visibility and motion

| Kimlik | Tür | Etiket | Varsayılan | Seçenekler ya da aralık |
| --- | --- | --- | --- | --- |
| `padding_top` | `range` | Top padding on desktop | `80` | 0–200 px, step 4 |
| `padding_bottom` | `range` | Bottom padding on desktop | `80` | 0–200 px, step 4 |
| `padding_top_mobile` | `range` | Top padding on mobile | `40` | 0–160 px, step 4 |
| `padding_bottom_mobile` | `range` | Bottom padding on mobile | `48` | 0–160 px, step 4 |
| `show_on` | `select` | Show on | all | `all`, `desktop`, `mobile` |
| `anchor_id` | `text` | Anchor ID | – |  |
| `animate` | `checkbox` | Fade in on scroll | `false` |  |

## Kurulum

### Shopify yönetim panelinde

1. Canlı temanızda değil, bir kopyasında çalışın: Shopify yönetim panelinde **Online Mağaza > Temalar** sayfasına gidin, mevcut temanızın **…** menüsünü açın ve **Kopya oluştur**’u seçin.
2. Kopyada **…** menüsünü açın ve **Kodu düzenle**’yi seçin.
3. `sections` klasörüne `lib-featured-product.liquid` adında yeni bir dosya ekleyin, aşağıdaki kaynak koddan `sections/lib-featured-product.liquid` içeriğini yapıştırıp kaydedin.
4. `lib-button.liquid` dosyalarını da aynı şekilde `snippets` klasörüne ekleyin. Başka bir Lib bölümünden gelen aynı adlı bir snippet zaten varsa aynı dosyadır; tek kopya yeterli.
5. Kopyada **Özelleştir**’i açın, **Bölüm ekle**’yi seçin ve **Lib · Featured product** bölümünü ekleyin. Örnek içeriği kendi içeriğinizle değiştirin, renkleri ayarlayın.
6. Kopyayı önizleyin, her şey doğru göründüğünde yayınlayın.

### Shopify CLI ile

Yerel tema klasörünüzde dosyaları indirin ve yalnızca bunları yayında olmayan bir temaya gönderin (temanın kimliğini `shopify theme list` gösterir):

```sh
curl -fsSL -o sections/lib-featured-product.liquid https://lintelagency.com/resources/shopify-sections/files/lib-featured-product.liquid
curl -fsSL -o snippets/lib-button.liquid https://lintelagency.com/resources/shopify-sections/files/lib-button.liquid
shopify theme push --theme <unpublished-theme-id> --only sections/lib-featured-product.liquid --only snippets/lib-button.liquid
```

Canlı temaya asla göndermeyin: her zaman yayında olmayan bir temanın kimliğini verin, `--live` ya da `--allow-live` kullanmayın. Ardından bölümü yukarıdaki gibi tema düzenleyicide ekleyin.

## Dosyalar

- [sections/lib-featured-product.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-featured-product.liquid): `sections/` klasörüne
- [snippets/lib-button.liquid](https://lintelagency.com/resources/shopify-sections/files/lib-button.liquid): `snippets/` klasörüne

## Sık sorulan sorular

### Müşteriler ürün sayfasını açmadan sepete ekleyebilir mi?

Evet. Bölümde, seçilen varyantı ve adedi /cart/add adresine gönderen gerçek bir ürün formu vardır; ürün sepete eklenir ve Shopify müşteriyi her zamanki gibi sepete götürür. Ürün sayfasına giden "View full details" bağlantısı isteğe bağlıdır.

### Tükenen varyantlar nasıl gösterilir?

Tükenen seçenekler görünür kalır ve yine seçilebilir: üstleri çizilir ve ekran okuyucular değerden sonra "sold out" duyurur. Seçilen varyant tükenmişse düğme "Sold out" yazar ve devre dışı kalır, fiyatın yanında da bir tükendi etiketi görünür. Var olmayan kombinasyonlarda "Unavailable" yazar. Bu metinlerin hepsini Türkçeye çevirebilirsiniz.

### JavaScript olmadan çalışır mı?

Evet. JavaScript yoksa seçenekler, her varyantın fiyatıyla birlikte listelendiği tek bir menüdür; tükenen varyantlar seçilemez. JavaScript varsa menü seçenek düğmelerine dönüşür; fiyat, karşılaştırma fiyatı, indirim etiketi, stok durumu ve ana görsel seçilen varyanta göre güncellenir. Sayfa adresi değişmez.

### Yorumları ya da stok sayısını gösterir mi?

Hayır. Yalnızca ürünün kendisinde olanı gösterir: görseller, başlık, satıcı, fiyat, karşılaştırma fiyatı, varyantlar, stok durumu ve açıklama. Puan, "son 3 ürün" gibi stok sayıları ya da ziyaretçi rakamları gibi uydurma veriler yoktur.

### Düğmeyi ve etiketleri çevirebilir miyim?

Müşterinin gördüğü ya da duyduğu her kelime bir ayardır: Add to cart, Sold out, Unavailable, Sale, indirimli ve normal fiyat etiketleri, adet düğmeleri ve küçük görsel düğmeleri. Bunları tema düzenleyicide değiştirebilir ya da Translate & Adapt ile çevirebilirsiniz.

## Kaynak kod

### sections/lib-featured-product.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{%- comment -%}
  Featured product: one product you pick, with its image gallery, title, price, variant picker,
  quantity and add to cart, for a home page or landing page. The form posts to /cart/add, so it
  works without JavaScript (a plain variant menu); with JavaScript the options become buttons and
  the price, sale label, availability and image follow the chosen variant. Every word a shopper
  sees is a setting. Reads the product only; no ratings, stock counts or other made-up data.
  Depends on: snippets/lib-button.liquid
{%- endcomment -%}

{%- liquid
  assign s = section.settings
  assign p = s.product
  assign heading_tag = s.heading_tag | default: 'h2'
  assign uid = 'lib-fp-' | append: section.id
  assign eager = false
  if section.index <= 2
    assign eager = true
  endif

  assign render_section = true
  if p == blank and request.design_mode == false
    assign render_section = false
  endif

  if p != blank
    assign current = p.selected_or_first_available_variant
    assign price = current.price | default: p.price
    assign compare = current.compare_at_price | default: 0
    assign on_sale = false
    if compare > price
      assign on_sale = true
    endif
    assign has_options = true
    if p.has_only_default_variant or p.variants.size < 2
      assign has_options = false
    endif
    assign first_media = p.media | where: 'media_type', 'image' | first
    assign option_names = p.options_with_values | map: 'name' | join: ' / '
  endif

  assign media_sizes = '(min-width: 990px) 50vw, 100vw'
  if s.media_width == 'wide'
    assign media_sizes = '(min-width: 990px) 58vw, 100vw'
  endif
-%}

{%- if render_section -%}
<lib-featured-product
  class="lib-featured-product lib-featured-product--{{ s.section_width }}"
  {% if s.anchor_id != blank %}
    id="{{ s.anchor_id | handleize }}"
  {% endif %}
  data-show="{{ s.show_on }}"
  data-media-position="{{ s.media_position }}"
  data-media-width="{{ s.media_width }}"
  data-mobile-order="{{ s.mobile_order }}"
  data-ratio="{{ s.media_ratio }}"
  {% if s.animate %}
    data-animate
  {% endif %}
  style="
    --lib-bg: {{ s.color_bg }};
    --lib-text: {{ s.color_text }};
    --lib-accent: {{ s.color_accent }};
    --lib-accent-text: {{ s.color_accent_text }};
    --lib-border: {{ s.color_border }};
    --lib-radius: {{ s.corner_radius }}px;
    {% if first_media != blank %}--lib-ratio: {{ first_media.preview_image.width }} / {{ first_media.preview_image.height }};{% endif %}
    --lib-pt: {{ s.padding_top }}px;
    --lib-pb: {{ s.padding_bottom }}px;
    --lib-pt-m: {{ s.padding_top_mobile }}px;
    --lib-pb-m: {{ s.padding_bottom_mobile }}px;
  "
>
  <div class="lib-featured-product__inner">
    <div class="lib-featured-product__media">
      {%- if p != blank and p.media.size > 0 -%}
        <div class="lib-featured-product__stage">
          {%- assign shown = 0 -%}
          {%- for media in p.media -%}
            {%- if media.media_type != 'image' -%}{%- continue -%}{%- endif -%}
            {%- liquid
              assign loading = 'lazy'
              assign priority = 'auto'
              if shown == 0 and eager
                assign loading = 'eager'
                assign priority = 'high'
              endif
            -%}
            <div
              class="lib-featured-product__slide"
              data-media-id="{{ media.id }}"
              data-index="{{ shown }}"
              {% if shown > 0 %}
                hidden
              {% endif %}
            >
              {{
                media.preview_image
                | image_url: width: 1600
                | image_tag:
                  class: 'lib-featured-product__img',
                  loading: loading,
                  fetchpriority: priority,
                  sizes: media_sizes,
                  widths: '400, 600, 800, 1000, 1200, 1600',
                  alt: media.alt
              }}
            </div>
            {%- assign shown = shown | plus: 1 -%}
          {%- endfor -%}
        </div>

        {%- if s.show_thumbnails and shown > 1 -%}
          <ul class="lib-featured-product__thumbs" role="list" data-thumbs hidden>
            {%- assign thumb = 0 -%}
            {%- for media in p.media -%}
              {%- if media.media_type != 'image' -%}{%- continue -%}{%- endif -%}
              <li>
                <button
                  type="button"
                  class="lib-featured-product__thumb"
                  data-show-index="{{ thumb }}"
                  aria-label="{{ s.thumbnail_label | escape }} {{ thumb | plus: 1 }}"
                  {% if thumb == 0 %}
                    aria-current="true"
                  {% endif %}
                >
                  {{
                    media.preview_image
                    | image_url: width: 160
                    | image_tag: class: 'lib-featured-product__thumb-img', loading: 'lazy', sizes: '80px', alt: ''
                  }}
                </button>
              </li>
              {%- assign thumb = thumb | plus: 1 -%}
            {%- endfor -%}
          </ul>
        {%- endif -%}
      {%- else -%}
        <div class="lib-featured-product__stage">
          <div class="lib-featured-product__slide">
            {{ 'product-1' | placeholder_svg_tag: 'lib-featured-product__img lib-featured-product__placeholder' }}
          </div>
        </div>
      {%- endif -%}
    </div>

    <div class="lib-featured-product__info" data-align="{{ s.text_alignment }}" data-align-m="{{ s.text_alignment_mobile }}">
      {%- if p == blank -%}
        {%- comment -%} Only reachable in the theme editor (no product chosen yet). {%- endcomment -%}
        <p class="lib-featured-product__vendor">Choose a product in the section settings</p>
        <{{ heading_tag }} class="lib-featured-product__title lib-featured-product__title--{{ s.heading_size }}">
          Your product's name
        </{{ heading_tag }}>
      {%- else -%}
        {%- if s.show_vendor and p.vendor != blank -%}
          <p class="lib-featured-product__vendor">{{ p.vendor | escape }}</p>
        {%- endif -%}

        <{{ heading_tag }} class="lib-featured-product__title lib-featured-product__title--{{ s.heading_size }}">
          {{- p.title | escape -}}
        </{{ heading_tag }}>

        <div class="lib-featured-product__price" aria-live="polite" aria-atomic="true">
          <span class="lib-featured-product__sr" data-sale-label{% unless on_sale %} hidden{% endunless %}>{{ s.sale_price_label | escape }}</span>
          <span class="lib-featured-product__now{% if on_sale %} is-sale{% endif %}" data-price>{{ price | money }}</span>
          <span class="lib-featured-product__sr" data-was-label{% unless on_sale %} hidden{% endunless %}>{{ s.regular_price_label | escape }}</span>
          <s class="lib-featured-product__was" data-compare{% unless on_sale %} hidden{% endunless %}>
            {%- if on_sale -%}{{ compare | money }}{%- endif -%}
          </s>
          <span class="lib-featured-product__badge" data-badge-sale{% unless on_sale %} hidden{% endunless %}>{{ s.sale_badge_label | escape }}</span>
          <span class="lib-featured-product__badge lib-featured-product__badge--muted" data-badge-sold{% if current.available %} hidden{% endif %}>{{ s.sold_out_label | escape }}</span>
        </div>

        {%- form 'product', p, id: uid, class: 'lib-featured-product__form', novalidate: 'novalidate' -%}
          <input type="hidden" name="id" value="{{ current.id }}" data-variant-id{% if has_options %} disabled{% endif %}>

          {%- if has_options -%}
            {%- comment -%} Without JavaScript: one menu of every variant. {%- endcomment -%}
            <div class="lib-featured-product__fallback" data-fallback>
              <label class="lib-featured-product__label" for="{{ uid }}-variant">{{ option_names | escape }}</label>
              <select id="{{ uid }}-variant" class="lib-featured-product__select" name="id">
                {%- for variant in p.variants -%}
                  <option
                    value="{{ variant.id }}"
                    {% if variant.id == current.id %}
                      selected
                    {% endif %}
                    {% unless variant.available %}
                      disabled
                    {% endunless %}
                  >
                    {{- variant.title | escape }} · {{ variant.price | money -}}
                    {%- unless variant.available %} · {{ s.sold_out_label | escape }}{% endunless -%}
                  </option>
                {%- endfor -%}
              </select>
            </div>

            {%- comment -%}
              With JavaScript: a group of buttons per option. Their form attribute names no form, so
              they are never posted; only the variant id is.
            {%- endcomment -%}
            {%- for option in p.options_with_values -%}
              {%- assign option_index = forloop.index0 -%}
              <fieldset class="lib-featured-product__option" data-option hidden>
                <legend class="lib-featured-product__label">
                  {{- option.name | escape -}}
                </legend>
                <div class="lib-featured-product__values">
                  {%- for value in option.values -%}
                    {%- liquid
                      assign value_available = false
                      for variant in p.variants
                        if variant.options[option_index] == value and variant.available
                          assign value_available = true
                          break
                        endif
                      endfor
                    -%}
                    <span class="lib-featured-product__choice"{% unless value_available %} data-sold-out{% endunless %}>
                      <input
                        type="radio"
                        class="lib-featured-product__radio"
                        id="{{ uid }}-{{ option.position }}-{{ forloop.index }}"
                        name="{{ uid }}-option-{{ option.position }}"
                        value="{{ value | escape }}"
                        form="{{ uid }}-options"
                        {% if option.selected_value == value %}
                          checked
                        {% endif %}
                      >
                      <label class="lib-featured-product__value" for="{{ uid }}-{{ option.position }}-{{ forloop.index }}">
                        {{- value | escape -}}
                        <span class="lib-featured-product__sr" data-sold-out-text{% if value_available %} hidden{% endif %}>, {{ s.sold_out_label | escape }}</span>
                      </label>
                    </span>
                  {%- endfor -%}
                </div>
              </fieldset>
            {%- endfor -%}
          {%- endif -%}

          <div class="lib-featured-product__buy">
            {%- if s.show_quantity -%}
              <div class="lib-featured-product__qty-wrap">
                <label class="lib-featured-product__sr" for="{{ uid }}-qty">{{ s.quantity_label | escape }}</label>
                <div class="lib-featured-product__qty">
                  <button type="button" class="lib-featured-product__step" data-step="-1" aria-label="{{ s.decrease_label | escape }}" hidden>
                    <svg viewBox="0 0 12 12" width="12" height="12" aria-hidden="true" focusable="false"><path d="M2.5 6h7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
                  </button>
                  <input
                    id="{{ uid }}-qty"
                    class="lib-featured-product__qty-input"
                    type="number"
                    name="quantity"
                    value="1"
                    min="1"
                    step="1"
                    inputmode="numeric"
                  >
                  <button type="button" class="lib-featured-product__step" data-step="1" aria-label="{{ s.increase_label | escape }}" hidden>
                    <svg viewBox="0 0 12 12" width="12" height="12" aria-hidden="true" focusable="false"><path d="M2.5 6h7M6 2.5v7" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
                  </button>
                </div>
              </div>
            {%- endif -%}
            <button
              type="submit"
              name="add"
              class="lib-featured-product__add"
              data-add
              data-label="{{ s.button_label | escape }}"
              data-sold-out="{{ s.sold_out_label | escape }}"
              data-unavailable="{{ s.unavailable_label | escape }}"
              {% unless current.available %}
                disabled
              {% endunless %}
            >
              {%- if current.available -%}{{ s.button_label | escape }}{%- else -%}{{ s.sold_out_label | escape }}{%- endif -%}
            </button>
          </div>
        {%- endform -%}

        {%- if s.show_description and p.description != blank -%}
          <div class="lib-featured-product__description">{{ p.description }}</div>
        {%- endif -%}

        {%- if s.details_label != blank -%}
          <div class="lib-featured-product__details">
            {%- render 'lib-button',
              label: s.details_label,
              url: p.url,
              style: s.details_style,
              new_tab: s.details_new_tab
            -%}
          </div>
        {%- endif -%}

        <script type="application/json" data-variants>
          [
            {%- for variant in p.variants -%}
              {
                "id": {{ variant.id | json }},
                "options": {{ variant.options | json }},
                "available": {{ variant.available | json }},
                "price": {{ variant.price | money | json }},
                "compare": {% if variant.compare_at_price > variant.price %}{{ variant.compare_at_price | money | json }}{% else %}null{% endif %},
                "media": {% if variant.featured_media != blank %}{{ variant.featured_media.id | json }}{% else %}null{% endif %}
              }{% unless forloop.last %},{% endunless %}
            {%- endfor -%}
          ]
        </script>
      {%- endif -%}
    </div>
  </div>
</lib-featured-product>
{%- endif -%}

{% stylesheet %}
  .lib-featured-product {
    display: block;
    background-color: var(--lib-bg);
    color: var(--lib-text);
    padding: var(--lib-pt) 1rem var(--lib-pb);
  }
  .lib-featured-product__inner {
    display: grid;
    gap: clamp(1.75rem, 4vw, 4rem);
    max-width: 1200px;
    margin: 0 auto;
  }
  .lib-featured-product--full .lib-featured-product__inner { max-width: none; }
  .lib-featured-product__inner > * { min-width: 0; }
  @media (max-width: 749px) {
    .lib-featured-product { padding-top: var(--lib-pt-m); padding-bottom: var(--lib-pb-m); }
    .lib-featured-product[data-show='desktop'] { display: none; }
  }
  @media (min-width: 750px) {
    .lib-featured-product[data-show='mobile'] { display: none; }
  }
  @media (max-width: 989px) {
    .lib-featured-product[data-mobile-order='info_first'] .lib-featured-product__info { order: -1; }
  }
  @media (min-width: 990px) {
    .lib-featured-product__inner { grid-template-columns: 1fr 1fr; align-items: start; }
    .lib-featured-product[data-media-width='wide'] .lib-featured-product__inner { grid-template-columns: 7fr 5fr; }
    .lib-featured-product[data-media-position='right'] .lib-featured-product__media { order: 2; }
    .lib-featured-product[data-media-position='right'][data-media-width='wide'] .lib-featured-product__inner { grid-template-columns: 5fr 7fr; }
    .lib-featured-product__info { position: sticky; top: 2rem; }
  }

  /* Gallery: one image at a time, thumbnails underneath. */
  .lib-featured-product__stage {
    position: relative;
    overflow: hidden;
    border-radius: var(--lib-radius);
    background: color-mix(in srgb, var(--lib-text) 6%, var(--lib-bg));
    aspect-ratio: 1;
  }
  .lib-featured-product[data-ratio='portrait'] .lib-featured-product__stage { aspect-ratio: 4 / 5; }
  .lib-featured-product[data-ratio='landscape'] .lib-featured-product__stage { aspect-ratio: 4 / 3; }
  .lib-featured-product[data-ratio='adapt'] .lib-featured-product__stage { aspect-ratio: var(--lib-ratio, 1); }
  .lib-featured-product__slide { position: absolute; inset: 0; }
  .lib-featured-product__slide[hidden] { display: none; }
  .lib-featured-product__img { display: block; width: 100%; height: 100%; object-fit: cover; }
  .lib-featured-product__placeholder { fill: color-mix(in srgb, var(--lib-text) 25%, transparent); }
  .lib-featured-product__thumbs {
    display: flex;
    gap: 0.625rem;
    margin: 0.875rem 0 0;
    padding: 0.25rem;
    list-style: none;
    overflow-x: auto;
    scrollbar-width: thin;
  }
  .lib-featured-product__thumbs[hidden] { display: none; }
  .lib-featured-product__thumb {
    display: block;
    width: 4.5rem;
    height: 4.5rem;
    padding: 0;
    border: 1px solid var(--lib-border);
    border-radius: calc(var(--lib-radius) / 2);
    overflow: hidden;
    background: color-mix(in srgb, var(--lib-text) 6%, var(--lib-bg));
    cursor: pointer;
    opacity: 0.7;
    transition: opacity 0.2s ease, border-color 0.2s ease;
  }
  .lib-featured-product__thumb:hover { opacity: 1; }
  .lib-featured-product__thumb[aria-current='true'] { opacity: 1; border-color: var(--lib-text); box-shadow: inset 0 0 0 1px var(--lib-text); }
  .lib-featured-product__thumb:focus-visible { outline: 2px solid var(--lib-text); outline-offset: 2px; }
  .lib-featured-product__thumb-img { display: block; width: 100%; height: 100%; object-fit: cover; }

  /* Info column and alignment: desktop, then mobile override. */
  .lib-featured-product__info { display: flex; flex-direction: column; align-items: flex-start; text-align: left; }
  .lib-featured-product__info[data-align='center'] { align-items: center; text-align: center; }
  @media (max-width: 749px) {
    .lib-featured-product__info[data-align-m='left'] { align-items: flex-start; text-align: left; }
    .lib-featured-product__info[data-align-m='center'] { align-items: center; text-align: center; }
  }
  .lib-featured-product__info > * { margin: 0; }
  .lib-featured-product__vendor {
    margin-bottom: 0.75rem;
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    opacity: 0.75;
  }
  .lib-featured-product__title {
    font-size: clamp(1.75rem, 3vw, 2.5rem);
    line-height: 1.1;
    letter-spacing: -0.02em;
    text-wrap: balance;
  }
  .lib-featured-product__title--small { font-size: clamp(1.375rem, 2vw, 1.75rem); }
  .lib-featured-product__title--large { font-size: clamp(2rem, 4vw, 3.25rem); }
  .lib-featured-product__price {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.25rem 0.625rem;
    margin-top: 1rem;
    font-size: 1.25rem;
  }
  .lib-featured-product__info[data-align='center'] .lib-featured-product__price { justify-content: center; }
  @media (max-width: 749px) {
    .lib-featured-product__info[data-align-m='left'] .lib-featured-product__price { justify-content: flex-start; }
    .lib-featured-product__info[data-align-m='center'] .lib-featured-product__price { justify-content: center; }
  }
  .lib-featured-product__now { font-weight: 600; }
  .lib-featured-product__now.is-sale { color: var(--lib-accent); }
  .lib-featured-product__was { font-size: 1rem; opacity: 0.65; }
  .lib-featured-product__badge {
    align-self: center;
    padding: 0.3em 0.7em;
    border-radius: 999px;
    background: var(--lib-accent);
    color: var(--lib-accent-text);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
  }
  .lib-featured-product__badge--muted { background: color-mix(in srgb, var(--lib-text) 12%, transparent); color: var(--lib-text); }
  .lib-featured-product__badge[hidden],
  .lib-featured-product__was[hidden] { display: none; }

  .lib-featured-product__form { display: flex; flex-direction: column; gap: 1.25rem; width: 100%; max-width: 30rem; margin-top: 1.75rem; text-align: left; }
  .lib-featured-product__label { display: block; margin: 0 0 0.5rem; padding: 0; font-size: 0.875rem; font-weight: 600; }
  .lib-featured-product__select {
    width: 100%;
    min-height: 2.75rem;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--lib-border);
    border-radius: calc(var(--lib-radius) / 2);
    background: transparent;
    color: inherit;
    font: inherit;
  }
  .lib-featured-product__option { min-width: 0; margin: 0; padding: 0; border: 0; }
  .lib-featured-product__option[hidden],
  .lib-featured-product__fallback[hidden] { display: none; }
  .lib-featured-product__values { display: flex; flex-wrap: wrap; gap: 0.5rem; }
  .lib-featured-product__choice { position: relative; display: inline-flex; }
  .lib-featured-product__radio { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
  .lib-featured-product__value {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    padding: 0.5rem 1.125rem;
    border: 1px solid var(--lib-border);
    border-radius: 999px;
    font-size: 0.9375rem;
    cursor: pointer;
    transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
  }
  .lib-featured-product__radio:hover + .lib-featured-product__value { border-color: var(--lib-text); }
  .lib-featured-product__radio:checked + .lib-featured-product__value { background: var(--lib-text); border-color: var(--lib-text); color: var(--lib-bg); }
  .lib-featured-product__radio:focus-visible + .lib-featured-product__value { outline: 2px solid var(--lib-text); outline-offset: 2px; }
  .lib-featured-product__choice[data-sold-out] .lib-featured-product__value { text-decoration: line-through; text-decoration-thickness: 1px; opacity: 0.6; }
  .lib-featured-product__choice[data-sold-out] .lib-featured-product__radio:checked + .lib-featured-product__value { opacity: 0.75; }

  .lib-featured-product__buy { display: flex; flex-wrap: wrap; gap: 0.75rem; }
  .lib-featured-product__qty {
    display: inline-flex;
    align-items: center;
    height: 3rem;
    border: 1px solid var(--lib-border);
    border-radius: 999px;
  }
  .lib-featured-product__step {
    display: grid;
    place-items: center;
    width: 2.75rem;
    height: 100%;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    cursor: pointer;
  }
  .lib-featured-product__step[hidden] { display: none; }
  .lib-featured-product__step:focus-visible { outline: 2px solid var(--lib-text); outline-offset: -4px; border-radius: 999px; }
  .lib-featured-product__qty-input {
    width: 3.5rem;
    height: 100%;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: center;
    appearance: textfield;
    -moz-appearance: textfield;
  }
  .lib-featured-product__qty-input::-webkit-inner-spin-button,
  .lib-featured-product__qty-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
  .lib-featured-product__qty-input:focus-visible { outline: 2px solid var(--lib-text); outline-offset: -2px; border-radius: 4px; }
  .lib-featured-product__add {
    flex: 1 1 12rem;
    min-height: 3rem;
    padding: 0.85rem 1.5rem;
    border: 0;
    border-radius: 999px;
    background: var(--lib-accent);
    color: var(--lib-accent-text);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease;
  }
  .lib-featured-product__add:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 8px 20px -10px rgb(0 0 0 / 0.45); }
  .lib-featured-product__add:focus-visible { outline: 2px solid var(--lib-accent); outline-offset: 3px; }
  .lib-featured-product__add:disabled { cursor: not-allowed; opacity: 0.55; }

  .lib-featured-product__description { margin-top: 1.75rem; max-width: 34rem; font-size: 1rem; line-height: 1.65; opacity: 0.85; }
  .lib-featured-product__description > :first-child { margin-top: 0; }
  .lib-featured-product__description > :last-child { margin-bottom: 0; }
  .lib-featured-product__description a { color: inherit; }
  .lib-featured-product__details { margin-top: 1.5rem; }

  .lib-featured-product__sr {
    position: absolute !important;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }
  .lib-featured-product__sr[hidden] { display: none; }

  /* Motion: gallery and info fade up as they scroll into view (scroll-driven animations only). */
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {
      .lib-featured-product[data-animate] .lib-featured-product__media,
      .lib-featured-product[data-animate] .lib-featured-product__info > * {
        animation: lib-featured-product-rise linear both;
        animation-timeline: view();
        animation-range: entry 0% entry 50%;
      }
    }
  }
  @keyframes lib-featured-product-rise {
    from { opacity: 0; transform: translateY(20px); }
  }
  @media (prefers-reduced-motion: reduce) {
    .lib-featured-product__add, .lib-featured-product__value, .lib-featured-product__thumb { transition: none; }
    .lib-featured-product__add:hover:not(:disabled) { transform: none; }
  }
{% endstylesheet %}

{% javascript %}
  if (!customElements.get('lib-featured-product')) {
    customElements.define(
      'lib-featured-product',
      class extends HTMLElement {
        connectedCallback() {
          const data = this.querySelector('script[data-variants]');
          this.form = this.querySelector('form');
          if (!data || !this.form) return;
          try {
            this.variants = JSON.parse(data.textContent);
          } catch (error) {
            console.error('lib-featured-product: variant data could not be read', error);
            return;
          }
          this.cleanup = [];
          const listen = (target, type, fn) => {
            target.addEventListener(type, fn);
            this.cleanup.push(() => target.removeEventListener(type, fn));
          };

          this.idInput = this.querySelector('[data-variant-id]');
          this.groups = [...this.querySelectorAll('[data-option]')];
          this.slides = [...this.querySelectorAll('.lib-featured-product__slide[data-media-id]')];
          this.thumbs = [...this.querySelectorAll('[data-show-index]')];
          this.addButton = this.querySelector('[data-add]');

          // Swap the plain variant menu for option buttons.
          const fallback = this.querySelector('[data-fallback]');
          if (fallback && this.groups.length) {
            fallback.hidden = true;
            fallback.querySelector('select').disabled = true;
            this.idInput.disabled = false;
            this.groups.forEach((group) => {
              group.hidden = false;
              listen(group, 'change', () => this.update());
            });
          }

          const thumbList = this.querySelector('[data-thumbs]');
          if (thumbList) thumbList.hidden = false;
          this.thumbs.forEach((thumb) => listen(thumb, 'click', () => this.showSlide(Number(thumb.dataset.showIndex))));

          const qty = this.querySelector('.lib-featured-product__qty-input');
          this.querySelectorAll('[data-step]').forEach((button) => {
            button.hidden = false;
            listen(button, 'click', () => {
              const next = Math.max(1, (parseInt(qty.value, 10) || 1) + Number(button.dataset.step));
              qty.value = String(next);
            });
          });

          if (this.groups.length) this.update();
        }

        disconnectedCallback() {
          (this.cleanup || []).forEach((fn) => fn());
          this.cleanup = [];
        }

        selectedValues() {
          return this.groups.map((group) => group.querySelector('input:checked')?.value);
        }

        update() {
          const selected = this.selectedValues();
          const matches = (variant, index, value) =>
            variant.options.every((option, i) => (i === index ? option === value : option === selected[i]));

          // Mark every value that would lead to a sold-out or missing combination.
          this.groups.forEach((group, index) => {
            group.querySelectorAll('input').forEach((input) => {
              const variant = this.variants.find((v) => matches(v, index, input.value));
              const soldOut = !variant || !variant.available;
              const choice = input.closest('.lib-featured-product__choice');
              choice.toggleAttribute('data-sold-out', soldOut);
              choice.querySelector('[data-sold-out-text]').hidden = !soldOut;
            });
          });

          const variant = this.variants.find((v) => v.options.every((option, i) => option === selected[i]));
          const button = this.addButton;
          if (!variant) {
            button.disabled = true;
            button.textContent = button.dataset.unavailable;
            return;
          }
          this.idInput.value = variant.id;
          button.disabled = !variant.available;
          button.textContent = variant.available ? button.dataset.label : button.dataset.soldOut;

          const onSale = Boolean(variant.compare);
          const price = this.querySelector('[data-price]');
          price.textContent = variant.price;
          price.classList.toggle('is-sale', onSale);
          const compare = this.querySelector('[data-compare]');
          compare.textContent = variant.compare || '';
          compare.hidden = !onSale;
          this.querySelector('[data-sale-label]').hidden = !onSale;
          this.querySelector('[data-was-label]').hidden = !onSale;
          this.querySelector('[data-badge-sale]').hidden = !onSale;
          this.querySelector('[data-badge-sold]').hidden = variant.available;

          if (variant.media !== null) {
            const index = this.slides.findIndex((slide) => slide.dataset.mediaId === String(variant.media));
            if (index > -1) this.showSlide(index);
          }
        }

        showSlide(index) {
          this.slides.forEach((slide, i) => {
            slide.hidden = i !== index;
          });
          this.thumbs.forEach((thumb, i) => {
            if (i === index) thumb.setAttribute('aria-current', 'true');
            else thumb.removeAttribute('aria-current');
          });
        }
      },
    );
  }
{% endjavascript %}

{% schema %}
{
  "name": "Lib · Featured product",
  "tag": "section",
  "class": "lib-section",
  "settings": [
    { "type": "header", "content": "Product" },
    { "type": "product", "id": "product", "label": "Product" },
    { "type": "checkbox", "id": "show_vendor", "label": "Show vendor", "default": true },
    {
      "type": "select",
      "id": "heading_tag",
      "label": "Product title tag",
      "info": "Use H1 only when this is the page's main heading.",
      "options": [
        { "value": "h1", "label": "H1" },
        { "value": "h2", "label": "H2" },
        { "value": "h3", "label": "H3" },
        { "value": "p", "label": "Paragraph" }
      ],
      "default": "h2"
    },
    {
      "type": "select",
      "id": "heading_size",
      "label": "Product title size",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" }
      ],
      "default": "medium"
    },
    { "type": "checkbox", "id": "show_description", "label": "Show product description", "default": true },
    { "type": "checkbox", "id": "show_quantity", "label": "Show quantity selector", "default": true },

    { "type": "header", "content": "Gallery" },
    { "type": "checkbox", "id": "show_thumbnails", "label": "Show thumbnails", "default": true },
    {
      "type": "select",
      "id": "media_ratio",
      "label": "Image shape",
      "options": [
        { "value": "adapt", "label": "Adapt to first image" },
        { "value": "square", "label": "Square" },
        { "value": "portrait", "label": "Portrait" },
        { "value": "landscape", "label": "Landscape" }
      ],
      "default": "square"
    },
    { "type": "range", "id": "corner_radius", "label": "Corner radius", "min": 0, "max": 32, "step": 2, "unit": "px", "default": 12 },

    { "type": "text", "id": "details_label", "label": "Details link label", "info": "Links to the product page. Leave empty to hide.", "default": "View full details" },
    {
      "type": "select",
      "id": "details_style",
      "label": "Details link style",
      "options": [
        { "value": "primary", "label": "Solid" },
        { "value": "outline", "label": "Outline" },
        { "value": "text", "label": "Text link" }
      ],
      "default": "text"
    },
    { "type": "checkbox", "id": "details_new_tab", "label": "Open details link in a new tab", "default": false },

    { "type": "header", "content": "Shopper-facing words" },
    { "type": "text", "id": "button_label", "label": "Add to cart button", "default": "Add to cart" },
    { "type": "text", "id": "sold_out_label", "label": "Sold out", "default": "Sold out" },
    { "type": "text", "id": "unavailable_label", "label": "Unavailable combination", "default": "Unavailable" },
    { "type": "text", "id": "sale_badge_label", "label": "Sale badge", "default": "Sale" },
    { "type": "text", "id": "sale_price_label", "label": "Sale price (screen readers)", "default": "Sale price" },
    { "type": "text", "id": "regular_price_label", "label": "Regular price (screen readers)", "default": "Regular price" },
    { "type": "text", "id": "quantity_label", "label": "Quantity (screen readers)", "default": "Quantity" },
    { "type": "text", "id": "decrease_label", "label": "Decrease quantity (screen readers)", "default": "Decrease quantity" },
    { "type": "text", "id": "increase_label", "label": "Increase quantity (screen readers)", "default": "Increase quantity" },
    { "type": "text", "id": "thumbnail_label", "label": "Thumbnail button (screen readers)", "info": "The image number is added, e.g. \"Show image 2\".", "default": "Show image" },

    { "type": "header", "content": "Layout" },
    {
      "type": "select",
      "id": "media_position",
      "label": "Gallery position on desktop",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "right", "label": "Right" }
      ],
      "default": "left"
    },
    {
      "type": "select",
      "id": "media_width",
      "label": "Gallery width on desktop",
      "options": [
        { "value": "half", "label": "Half" },
        { "value": "wide", "label": "Wide" }
      ],
      "default": "half"
    },
    {
      "type": "select",
      "id": "mobile_order",
      "label": "Order on mobile",
      "options": [
        { "value": "media_first", "label": "Gallery first" },
        { "value": "info_first", "label": "Product info first" }
      ],
      "default": "media_first"
    },
    {
      "type": "select",
      "id": "section_width",
      "label": "Width",
      "options": [
        { "value": "page", "label": "Page width" },
        { "value": "full", "label": "Full width" }
      ],
      "default": "page"
    },
    {
      "type": "select",
      "id": "text_alignment",
      "label": "Text alignment on desktop",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" }
      ],
      "default": "left"
    },
    {
      "type": "select",
      "id": "text_alignment_mobile",
      "label": "Text alignment on mobile",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" }
      ],
      "default": "left"
    },

    { "type": "header", "content": "Colors" },
    { "type": "color", "id": "color_bg", "label": "Background", "default": "#FBF8F4" },
    { "type": "color", "id": "color_text", "label": "Text", "default": "#231F1B" },
    { "type": "color", "id": "color_accent", "label": "Add to cart button, sale price and badge", "default": "#7C2D12" },
    { "type": "color", "id": "color_accent_text", "label": "Text on button and sale badge", "default": "#FFFFFF" },
    { "type": "color", "id": "color_border", "label": "Borders", "default": "#D9D2C8" },

    { "type": "header", "content": "Spacing, visibility and motion" },
    { "type": "range", "id": "padding_top", "label": "Top padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 80 },
    { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 80 },
    { "type": "range", "id": "padding_top_mobile", "label": "Top padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 40 },
    { "type": "range", "id": "padding_bottom_mobile", "label": "Bottom padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 48 },
    {
      "type": "select",
      "id": "show_on",
      "label": "Show on",
      "options": [
        { "value": "all", "label": "All devices" },
        { "value": "desktop", "label": "Desktop only" },
        { "value": "mobile", "label": "Mobile only" }
      ],
      "default": "all"
    },
    { "type": "text", "id": "anchor_id", "label": "Anchor ID", "info": "Optional. Link to this section with #your-id." },
    { "type": "checkbox", "id": "animate", "label": "Fade in on scroll", "info": "Only in browsers that support scroll-driven animations; never when reduced motion is on.", "default": false }
  ],
  "presets": [
    { "name": "Lib · Featured product" }
  ]
}
{% endschema %}
```

### snippets/lib-button.liquid

```liquid
{%- comment -%}
  MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections
{%- endcomment -%}
{% doc %}
  Animated call-to-action link. Light sweep on hover, arrow slides right.
  Colors come from the parent section's --lib-accent / --lib-accent-text / --lib-text vars.
  Inspired by Uiverse.io button patterns; rewritten for themes, no dependencies.

  @param {string} label - Button text
  @param {string} [url] - Link target; renders a disabled-looking span when blank
  @param {string} [style] - 'primary' (default), 'outline' or 'text'
  @param {boolean} [new_tab] - Open the link in a new tab
  @param {boolean} [arrow] - Show the trailing arrow (default true)

  @example
  {% render 'lib-button', label: section.settings.button_label, url: section.settings.button_url, style: 'outline' %}
{% enddoc %}

{%- liquid
  assign btn_style = style | default: 'primary'
  assign show_arrow = true
  if arrow == false
    assign show_arrow = false
  endif
-%}

{%- unless label == blank -%}
{%- capture inner -%}
  <span class="lib-btn__label">{{ label | escape }}</span>
  {%- if show_arrow -%}
    <svg class="lib-btn__arrow" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true" focusable="false">
      <path d="M3 8h9M8.5 4.5 12 8l-3.5 3.5" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>
  {%- endif -%}
{%- endcapture -%}

{%- if url != blank -%}
  <a
    class="lib-btn lib-btn--{{ btn_style }}"
    href="{{ url }}"
    {% if new_tab %}
      target="_blank" rel="noopener"
    {% endif %}
  >
    {{- inner -}}
  </a>
{%- else -%}
  <span class="lib-btn lib-btn--{{ btn_style }}" aria-disabled="true">{{ inner }}</span>
{%- endif -%}
{%- endunless -%}

{% stylesheet %}
  .lib-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    padding: 0.85em 1.5em;
    border-radius: var(--lib-radius, 999px);
    font: inherit;
    font-weight: 600;
    line-height: 1;
    text-decoration: none;
    overflow: hidden;
    isolation: isolate;
    transition: transform 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
  }
  .lib-btn--primary {
    background: var(--lib-accent, #111);
    color: var(--lib-accent-text, #fff);
    box-shadow: 0 1px 2px rgb(0 0 0 / 0.12);
  }
  .lib-btn--outline {
    background: transparent;
    color: var(--lib-text, #111);
    box-shadow: inset 0 0 0 1.5px currentColor;
  }
  .lib-btn--text {
    padding-inline: 0;
    background: none;
    color: var(--lib-text, #111);
    text-decoration: underline;
    text-underline-offset: 0.3em;
    overflow: visible;
  }
  .lib-btn--text::before { display: none; }
  .lib-btn--text:hover { transform: none; box-shadow: none; }
  .lib-btn::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(110deg, transparent 30%, rgb(255 255 255 / 0.35) 50%, transparent 70%);
    transform: translateX(-120%);
    transition: transform 0.6s ease;
  }
  .lib-btn--outline::before {
    background: linear-gradient(110deg, transparent 30%, rgb(127 127 127 / 0.18) 50%, transparent 70%);
  }
  .lib-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 20px -8px rgb(0 0 0 / 0.35);
  }
  .lib-btn:hover::before { transform: translateX(120%); }
  .lib-btn__arrow { transition: transform 0.2s ease; }
  .lib-btn:hover .lib-btn__arrow { transform: translateX(3px); }
  .lib-btn:focus-visible {
    outline: 2px solid var(--lib-accent, #111);
    outline-offset: 3px;
  }
  .lib-btn[aria-disabled='true'] { pointer-events: none; }
  @media (prefers-reduced-motion: reduce) {
    .lib-btn, .lib-btn::before, .lib-btn__arrow { transition: none; }
    .lib-btn:hover { transform: none; }
  }
{% endstylesheet %}
```

## Lisans

MIT Lisansı, © 2026 Lintel. Kendi mağazanızda ya da müşteri işlerinde ücretsiz kullanabilir, değiştirebilir ve yayınlayabilirsiniz; her dosyanın başındaki lisans satırını koruyun.
