/* =========================================================
   IRSHAD — Design System  (RTL-first, mobile-first)
   =========================================================
   01 tokens        02 reset/base      03 typography
   04 buttons       05 badges          06 header/nav
   07 hero          08 sections        09 book covers
   10 product card  11 category card   12 collections
   13 editorial     14 trust/whatsapp  15 footer
   16 bottom nav    17 category page   18 product page
   19 cart          20 search/modal    21 motion/util
   ========================================================= */

/* ---------- 01 · TOKENS ---------- */
:root {
  /* color */
  --paper:      #F6F1E7;
  --paper-2:    #EFE7D7;
  --paper-3:    #E7DDC8;
  --ink:        #211E19;
  --ink-soft:   #57503F;
  --ink-faint:  #8B8270;
  --emerald:    #123B31;
  --emerald-2:  #1B5244;
  --emerald-ink:#0C2B24;
  --brass:      #A8853B;
  --brass-2:    #C2A566;
  --line:       rgba(33, 30, 25, .14);
  --line-soft:  rgba(33, 30, 25, .08);
  --danger:     #8C3B2E;
  /* Named --white for historical reasons, but deliberately never white:
     a warm ivory that sits a shade above --paper without going stark. */
  --white:      #FCF9F1;

  /* Deckle edge — the untrimmed edge of a hand-bound page. Used as a mask
     so the colour still comes from CSS and follows the palette. */
  --deckle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1200' height='36' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M0,13 C60,5 120,20 200,12 C280,4 345,19 430,11 C520,4 585,18 660,12 C745,6 805,20 880,13 C965,7 1025,18 1105,11 C1150,7 1175,11 1200,13 L1200,36 L0,36 Z'/%3E%3C/svg%3E");

  /* type */
  --f-display: "Amiri", "Noto Naskh Arabic", serif;
  --f-body: "IBM Plex Sans Arabic", "Segoe UI", system-ui, sans-serif;

  /* scale (mobile base) */
  --fs-hero:   clamp(2.1rem, 7.2vw, 4.4rem);
  --fs-h2:     clamp(1.5rem, 4.5vw, 2.4rem);
  --fs-h3:     clamp(1.15rem, 3vw, 1.5rem);
  --fs-body:   1rem;
  --fs-small:  .85rem;
  --fs-tiny:   .74rem;

  /* space */
  --sp-1: .25rem; --sp-2: .5rem; --sp-3: .75rem; --sp-4: 1rem;
  --sp-5: 1.5rem; --sp-6: 2rem;  --sp-7: 3rem;   --sp-8: 4.5rem;

  /* misc */
  --r-sm: 4px; --r-md: 8px; --r-lg: 14px;
  --shadow-1: 0 1px 2px rgba(33,30,25,.06), 0 4px 14px rgba(33,30,25,.06);
  --shadow-2: 0 2px 6px rgba(33,30,25,.08), 0 14px 34px rgba(33,30,25,.12);
  --header-h: 60px;
  --bottomnav-h: 62px;
  --container: 1240px;
  --ease: cubic-bezier(.22,.8,.3,1);
}

/* ---------- 02 · RESET / BASE ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
/* Direction is NOT set here: <html dir> is stamped by i18n.js before first
   paint and inherits down. Hardcoding `direction: rtl` on body would win
   over that attribute and pin the whole site to RTL. Everything below uses
   logical properties (inset-inline-*, margin-inline-*) so the layout
   mirrors from that one attribute. */
body {
  margin: 0;
  font-family: var(--f-body);
  font-size: var(--fs-body);
  line-height: 1.7;
  color: var(--ink);
  background: var(--paper);
  padding-bottom: var(--bottomnav-h); /* mobile bottom nav */
}
img, svg, video { max-width: 100%; display: block; }
button { font: inherit; cursor: pointer; background: none; border: 0; color: inherit; padding: 0; }
input, select { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
ul { margin: 0; padding: 0; list-style: none; }
h1,h2,h3,h4,p { margin: 0; }
:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; border-radius: 2px; }
::selection { background: var(--emerald); color: var(--white); }

.container { max-width: var(--container); margin-inline: auto; padding-inline: var(--sp-4); }
@media (min-width: 900px) { .container { padding-inline: var(--sp-6); } }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* ---------- 03 · TYPOGRAPHY ---------- */
.t-display { font-family: var(--f-display); font-weight: 700; line-height: 1.35; }
.t-kicker {
  font-size: var(--fs-tiny); font-weight: 600; letter-spacing: .06em;
  color: var(--brass); text-transform: uppercase;
  display: inline-flex; align-items: center; gap: .6em;
}
.t-kicker::before { content: ""; width: 26px; height: 1px; background: var(--brass); }
.t-muted { color: var(--ink-soft); }
.t-price { font-weight: 700; font-variant-numeric: tabular-nums; }

/* ---------- 04 · BUTTONS ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  min-height: 48px; padding: .65em 1.6em;
  border-radius: var(--r-sm);
  font-weight: 600; font-size: .95rem; line-height: 1.2;
  transition: background .25s var(--ease), color .25s var(--ease),
              border-color .25s var(--ease), transform .25s var(--ease);
  -webkit-tap-highlight-color: transparent;
  white-space: nowrap;
}
.btn:active { transform: scale(.98); }
.btn-primary { background: var(--emerald); color: var(--white); }
.btn-primary:hover { background: var(--emerald-2); }
.btn-outline { border: 1px solid var(--line); color: var(--ink); background: transparent; }
.btn-outline:hover { border-color: var(--ink); }
.btn-light { background: var(--white); color: var(--emerald); }
.btn-light:hover { background: var(--paper-2); }
.btn-ghost-light { border: 1px solid rgba(253,251,246,.35); color: var(--white); }
.btn-ghost-light:hover { border-color: var(--white); background: rgba(253,251,246,.08); }
.btn-brass { background: var(--brass); color: var(--white); }
.btn-brass:hover { background: #96762F; }
.btn-block { width: 100%; }
.btn-sm { min-height: 40px; padding: .4em 1.1em; font-size: .88rem; }
.btn[disabled] { opacity: .5; cursor: not-allowed; }

.iconbtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  color: var(--ink); transition: background .2s var(--ease);
  position: relative;
}
.iconbtn:hover { background: var(--paper-2); }
.iconbtn svg { width: 22px; height: 22px; }

/* ---------- 05 · BADGES ---------- */
.badge {
  display: inline-flex; align-items: center; gap: .35em;
  font-size: var(--fs-tiny); font-weight: 600;
  padding: .28em .7em; border-radius: 3px; line-height: 1.4;
}
.badge-discount { background: var(--danger); color: var(--white); }
/* The points that belong to this dealer's account, never to the title.
   House green rather than another red: two reds side by side would read
   as one discount split across two lines, which is the confusion this
   badge exists to end. */
.badge-dealer { background: var(--emerald-ink); color: var(--white); }
.badge-new { background: var(--emerald); color: var(--white); }
.badge-set { background: var(--paper-2); color: var(--ink-soft); border: 1px solid var(--line); }
.badge-stock-low { color: var(--danger); background: transparent; padding-inline: 0; }
.badge-stock-ok { color: var(--emerald-2); background: transparent; padding-inline: 0; }

/* ---------- 06 · HEADER / NAV ---------- */
/* The shipping line wraps to two rows on narrow phones and eats scarce
   vertical space, so below 640px only the language switcher survives. */
.topbar {
  background: var(--emerald-ink); color: rgba(253,251,246,.85);
  font-size: var(--fs-tiny); text-align: center;
  padding: .45em var(--sp-4);
  display: flex; align-items: center; justify-content: center; gap: 1.5em;
}
.topbar > span:first-child { display: none; }
@media (min-width: 640px) { .topbar > span:first-child { display: inline; } }

/* ---------- 06b · LANGUAGE / CURRENCY PICKERS ----------
   Rendered three times, one shown per context. On desktop they belong in
   the sticky header, because a price the reader is looking at halfway down
   a listing is exactly when they reach for the currency — a picker parked
   in the non-sticky topbar would have scrolled away. On phones the header
   row has no room, so the topbar carries them and the drawer repeats them.
   All instances share one delegated handler and one state. */
.pickers { display: flex; align-items: center; gap: var(--sp-1); }
.header-actions .pickers { display: none; }
@media (min-width: 1000px) {
  .header-actions .pickers { display: flex; margin-inline-end: var(--sp-2); }
  .topbar .pickers { display: none; }
}
/* Header sits on paper, the topbar on ink — same control, two grounds. */
.header-actions .picker-btn { color: var(--ink-soft); }
.header-actions .picker-btn:hover,
.header-actions .picker-btn[aria-expanded="true"] {
  color: var(--emerald); background: var(--paper-2); border-color: var(--line);
}
.picker { position: relative; }
.picker-btn {
  display: flex; align-items: center; gap: .3em;
  padding: .15em .5em; border-radius: 3px;
  color: var(--brass-2); font-weight: 600; font-size: var(--fs-tiny);
  letter-spacing: .04em; line-height: 1.9;
  border: 1px solid transparent;
  transition: color .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease);
}
.picker-btn:hover, .picker-btn[aria-expanded="true"] {
  color: var(--white); background: rgba(253,251,246,.1); border-color: rgba(253,251,246,.18);
}
.picker-face { font-variant-numeric: tabular-nums; }
.picker-chev { display: flex; width: 12px; height: 12px; opacity: .8; }
.picker-chev svg { width: 12px; height: 12px; }
.picker-menu {
  position: absolute; top: calc(100% + 6px); inset-inline-end: 0; z-index: 120;
  min-width: 168px; padding: 5px;
  background: var(--white); color: var(--ink);
  border: 1px solid var(--line); border-radius: 4px;
  box-shadow: var(--shadow-2);
  text-align: start;
}
.picker-menu[hidden] { display: none; }
.picker-menu button {
  display: flex; align-items: baseline; gap: .6em; width: 100%;
  padding: .5em .7em; border-radius: 3px;
  font-size: var(--fs-small); line-height: 1.5;
  transition: background .15s var(--ease);
}
.picker-menu button:hover { background: var(--paper-2); }
.picker-menu button.on { background: var(--paper-2); font-weight: 700; }
/* The tick marks the active row without shifting the label — it lives in
   the gutter that the padding already reserves. */
.picker-menu button.on::after { content: "✓"; margin-inline-start: auto; color: var(--brass); }
.pk-a { font-weight: 600; }
.pk-b { font-size: var(--fs-tiny); color: var(--ink-faint); }

.drawer-foot .pickers { justify-content: flex-start; gap: var(--sp-2); }
.drawer-foot .picker-btn { color: var(--emerald); border-color: var(--line); }
.drawer-foot .picker-btn:hover, .drawer-foot .picker-btn[aria-expanded="true"] {
  color: var(--emerald); background: var(--paper-2); border-color: var(--line);
}
/* In the drawer the menu would fall off the bottom of the panel — drop it
   upward instead. */
.drawer-foot .picker-menu { top: auto; bottom: calc(100% + 6px); inset-inline-start: 0; inset-inline-end: auto; }

.site-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(246,241,231,.92);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--line-soft);
  transition: box-shadow .3s var(--ease);
}
.site-header.is-scrolled { box-shadow: var(--shadow-1); }
.header-row {
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: var(--header-h);
}
.brand { display: flex; align-items: center; gap: var(--sp-3); margin-inline-end: auto; }
.brand-text { display: flex; flex-direction: column; line-height: 1.1; }
.brand-logo { width: 44px; height: 44px; flex: none; }
/* Below the tablet break the wordmark goes and the mark carries the brand
   alone: on a 360px header, a logo AND two lines of type leave no room
   for the nav button and the cart. */
@media (max-width: 480px) {
  .brand-text { display: none; }
  .brand-logo { width: 40px; height: 40px; }
}
.brand-name { font-family: var(--f-display); font-weight: 700; font-size: 1.55rem; color: var(--emerald); }
.brand-name em { font-style: normal; color: var(--brass); }
.brand-tag { font-size: .62rem; letter-spacing: .28em; color: var(--ink-faint); margin-top: 2px; }

.main-nav { display: none; }
@media (min-width: 1000px) {
  .main-nav { display: flex; gap: var(--sp-5); margin-inline: var(--sp-6); }
  .main-nav a {
    font-size: .93rem; font-weight: 500; color: var(--ink-soft);
    padding-block: .4em; position: relative;
  }
  .main-nav a::after {
    content: ""; position: absolute; inset-inline: 0; bottom: 0; height: 2px;
    background: var(--brass); transform: scaleX(0);
    /* transform-origin has no logical keyword — the underline has to be
       told which way to grow per direction. */
    transform-origin: right;
    transition: transform .3s var(--ease);
  }
  [dir="ltr"] .main-nav a::after { transform-origin: left; }
  .main-nav a:hover, .main-nav a[aria-current="page"] { color: var(--ink); }
  .main-nav a:hover::after, .main-nav a[aria-current="page"]::after { transform: scaleX(1); }
}
.header-actions { display: flex; align-items: center; gap: var(--sp-1); }
.cart-count {
  position: absolute; top: 4px; inset-inline-start: 2px;
  min-width: 18px; height: 18px; padding-inline: 4px;
  background: var(--brass); color: var(--white);
  border-radius: 999px; font-size: .68rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.cart-count:empty { display: none; }
#menuBtn { display: inline-flex; }
@media (min-width: 1000px) { #menuBtn { display: none; } }

/* ---------- dealer sign-in ----------
   It left the shelf navigation (which is now three entries) and became
   an action, beside the search and the basket. Two renderings of ONE
   element, switched on width rather than duplicated in the markup:

     below 1000px  the padlock alone, at the same 44px touch target as
                   the other two actions — a 360px header already holds a
                   menu button, the mark, search and the basket, and a
                   fourth word does not fit beside them
     from 1000px   padlock and words, outlined, so it reads as the one
                   thing in the bar that is an account and not a shelf

   The drawer renders the same component with .is-full forced on (see
   .drawer-nav .dealer-link below), so a phone has the words too — one
   tap away rather than hidden behind an icon nobody has to guess at. */
.dealer-link {
  display: inline-flex; align-items: center; justify-content: center;
  gap: .5em; flex: none;
  width: 44px; height: 44px; border-radius: 50%;
  color: var(--ink); transition: background .2s var(--ease), border-color .2s var(--ease);
}
.dealer-link:hover { background: var(--paper-2); }
.dealer-link .dl-lock { font-size: 1.05rem; line-height: 1; }
.dealer-link .dl-txt { display: none; }
@media (min-width: 1000px) {
  .header-actions .dealer-link {
    width: auto; height: 40px; border-radius: var(--r-sm);
    padding-inline: var(--sp-4); margin-inline-start: var(--sp-2);
    border: 1px solid var(--line);
    font-size: .88rem; font-weight: 600; color: var(--emerald);
  }
  .header-actions .dealer-link .dl-txt { display: inline; }
  .header-actions .dealer-link:hover { background: var(--paper-2); border-color: var(--brass); }
}

/* ---------- catalogue download ----------
   Three skins, one component (catalogLinkHTML in ui.js): a hero button,
   a footer row and a drawer row. The size label is quiet on purpose —
   it answers "how big is this?" without competing with the verb. */
.dl-size { font-style: normal; font-size: var(--fs-tiny); opacity: .7; font-variant-numeric: tabular-nums; }
.btn-dl svg { width: 19px; height: 19px; }
.foot-dl { display: inline-flex; align-items: center; gap: .5em; }
.foot-dl svg { width: 15px; height: 15px; flex-shrink: 0; color: var(--brass-2); }
.drawer-nav .drawer-dl { gap: .6em; justify-content: flex-start; }
.drawer-nav .drawer-dl svg { width: 18px; height: 18px; color: var(--brass); flex-shrink: 0; }
/* In the drawer both of these are full-width rows like every other
   entry, not the circular icon buttons the header reduces them to. */
.drawer-nav .dealer-link {
  width: auto; height: auto; border-radius: 0;
  padding: .8em var(--sp-5); justify-content: flex-start;
  font-weight: 500;
}
.drawer-nav .dealer-link .dl-txt { display: inline; }

/* mobile drawer */
.drawer {
  position: fixed; inset: 0; z-index: 90; visibility: hidden;
}
.drawer.open { visibility: visible; }
.drawer-scrim {
  position: absolute; inset: 0; background: rgba(20,18,14,.5);
  opacity: 0; transition: opacity .3s var(--ease);
}
.drawer.open .drawer-scrim { opacity: 1; }
.drawer-panel {
  position: absolute; top: 0; bottom: 0; inset-inline-start: 0;
  width: min(320px, 86vw); background: var(--paper);
  transform: translateX(100%);
  transition: transform .35s var(--ease);
  display: flex; flex-direction: column;
  overflow-y: auto; overscroll-behavior: contain;
}
[dir="ltr"] .drawer-panel { transform: translateX(-100%); }
.drawer.open .drawer-panel { transform: translateX(0); }
.drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-4); border-bottom: 1px solid var(--line-soft);
}
.drawer-nav { padding: var(--sp-2) 0; }
.drawer-nav a {
  display: flex; align-items: center; justify-content: space-between;
  padding: .8em var(--sp-5); font-weight: 500;
}
.drawer-nav a:hover { background: var(--paper-2); }
.drawer-nav .sub { font-size: .9rem; color: var(--ink-soft); padding-inline-start: var(--sp-6); }
.drawer-sep { height: 1px; background: var(--line-soft); margin: var(--sp-2) var(--sp-4); }
.drawer-foot { margin-top: auto; padding: var(--sp-4) var(--sp-5) var(--sp-6); font-size: var(--fs-small); color: var(--ink-soft); }

/* ---------- 07 · HERO ---------- */
.hero {
  position: relative; overflow: hidden;
  background:
    radial-gradient(120% 90% at 85% 10%, #1B5244 0%, transparent 55%),
    linear-gradient(160deg, #0E322A 0%, #0C2B24 45%, #081F1A 100%);
  color: var(--white);
}
/* Deepens the last stretch of the hero so the ivory sheet below reads as
   paper lying over something dark, rather than two blocks butted together. */
.hero::before {
  content: ""; position: absolute; inset-inline: 0; bottom: 0;
  height: clamp(120px, 22vw, 190px); z-index: 0; pointer-events: none;
  background: linear-gradient(to bottom, transparent, rgba(5,19,15,.92));
}
.hero::after { /* film grain */
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .04 0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
.hero-inner {
  position: relative; z-index: 1;
  display: grid; gap: var(--sp-6);
  padding-block: var(--sp-7) var(--sp-6);
}
@media (min-width: 900px) {
  .hero-inner {
    grid-template-columns: 1.15fr .85fr; align-items: center;
    min-height: min(78vh, 720px); padding-block: var(--sp-7);
  }
}
.hero-kicker {
  color: var(--brass-2); font-size: var(--fs-small); font-weight: 600;
  letter-spacing: .12em; display: flex; align-items: center; gap: .8em;
}
.hero-kicker::after { content: ""; width: 48px; height: 1px; background: var(--brass); }
.hero h1 {
  font-family: var(--f-display); font-size: var(--fs-hero);
  line-height: 1.45; font-weight: 700; margin-block: var(--sp-4);
}
.hero h1 .accent { color: var(--brass-2); }
.hero-sub {
  color: rgba(253,251,246,.72); max-width: 34em;
  font-size: clamp(.95rem, 2.5vw, 1.08rem); font-weight: 300;
}
.hero-ctas { display: flex; flex-wrap: wrap; gap: var(--sp-3); margin-top: var(--sp-5); }
.hero-stats {
  display: flex; gap: var(--sp-6); margin-top: var(--sp-6);
  padding-top: var(--sp-5); border-top: 1px solid rgba(253,251,246,.14);
}
.hero-stat b { display: block; font-family: var(--f-display); font-size: 1.5rem; color: var(--brass-2); }
/* "more than" — the word comes from the markup (and so from the dictionary)
   rather than being hardcoded here, or it stays Arabic on the Turkish page.
   The last stat carries no attribute, so it renders nothing. */
.hero-stat b::before { content: attr(data-prefix); font-size: .55em; color: rgba(253,251,246,.5); font-family: var(--f-body); margin-inline-end: .4em; }
.hero-stat span { font-size: var(--fs-tiny); color: rgba(253,251,246,.6); }

/* hero visual: a typeset multi-volume set, lit by a moving sheen */
.hero-visual { position: relative; display: flex; justify-content: center; min-width: 0; }
.hero-visual > div { max-width: 100%; min-width: 0; }
.hero-shelf {
  display: flex; align-items: flex-end; gap: 6px;
  padding: 0 22px 16px;
  border-bottom: 3px solid rgba(194,165,102,.5);
  position: relative;
  /* The old drop-shadow() filter is gone: ::before now casts a directed
     shelf shadow and the per-spine shadows ground each volume, so the
     blanket silhouette only muddied both. Dropping it also spares the
     shelf a filtered render surface that re-rasterises with the sheen. */
  /* Darkness behind the row, so the gaps between volumes read as shadowed
     voids rather than showing the hero's lit background through them.
     Radial only — a full-bleed linear layer ends on a hard edge and the
     whole shelf reads as a dark rectangle pasted onto the hero. */
  background: radial-gradient(64% 88% at 50% 72%,
    rgba(0,0,0,.5), rgba(0,0,0,.2) 58%, transparent 82%);
}
/* Shelf shadow: what the row casts onto the surface below the gilt rule.
   Two radials, both fading out on every side, for the same reason. */
.hero-shelf::before {
  content: ""; position: absolute; pointer-events: none;
  inset-inline: -8%; top: calc(100% + 3px); height: 60px;
  background:
    radial-gradient(48% 100% at 50% 0%, rgba(0,0,0,.58), rgba(0,0,0,.2) 54%, transparent 80%),
    radial-gradient(86% 64% at 50% 0%, rgba(0,0,0,.28), transparent 74%);
}
.hero-shelf::after { /* light sweep */
  content: ""; position: absolute; inset: -20px 0 0;
  background: linear-gradient(105deg, transparent 30%, rgba(253,251,246,.14) 46%, rgba(253,251,246,.2) 50%, rgba(253,251,246,.14) 54%, transparent 70%);
  background-size: 300% 100%;
  animation: sheen 9s var(--ease) infinite;
  pointer-events: none; mix-blend-mode: soft-light;
}
@keyframes sheen { 0%,20% {background-position: 120% 0} 60%,100% {background-position: -60% 0} }
/* A bound spine is round, not flat: dark at both hinges, catching light
   down the middle. Reads as a separate volume even edge-to-edge. */
.spine {
  width: clamp(34px, 5.8vw, 50px); height: clamp(200px, 30vw, 320px);
  border-radius: 3px 3px 2px 2px;
  background:
    linear-gradient(90deg,
      rgba(0,0,0,.58) 0%, rgba(0,0,0,.26) 7%,
      rgba(255,255,255,.05) 32%, rgba(255,255,255,.10) 50%, rgba(255,255,255,.04) 68%,
      rgba(0,0,0,.28) 93%, rgba(0,0,0,.54) 100%),
    var(--sp-bg, #123B31);
  display: flex; flex-direction: column; align-items: center; justify-content: space-between;
  padding-block: 18px 14px;
  box-shadow: inset 0 2px 0 rgba(255,255,255,.08);
}
.spine:nth-child(2n) { height: calc(clamp(200px, 30vw, 320px) - 8px); }
/* Gilt rules above and below the lettering, the way a binder tools a spine. */
.spine .rule {
  width: 58%; height: 1px; opacity: .9;
  background: linear-gradient(90deg, transparent, var(--brass-2) 20%, #E7D3A1 50%, var(--brass-2) 80%, transparent);
}
/* Gold leaf, not gold text: the letters carry a metallic gradient plus a
   dark inset below and a faint light above, so they read as stamped into
   the cloth rather than printed on top of it. */
.spine .st {
  writing-mode: vertical-rl; text-orientation: mixed;
  font-family: var(--f-display); font-weight: 700;
  font-size: clamp(.62rem, 1.15vw, .82rem);
  letter-spacing: .04em; line-height: 1;
  max-height: 74%; overflow: hidden; white-space: nowrap;
  background: linear-gradient(180deg, #E9D6A8 0%, #C2A566 38%, #8C6F2E 62%, #D9C089 100%);
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,.55)) drop-shadow(0 -1px 0 rgba(255,255,255,.07));
  padding-block: 2px;
}
/* Fallback for engines without background-clip:text — plain gold beats
   invisible lettering. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .spine .st { color: var(--brass-2); -webkit-text-fill-color: currentColor; background: none; }
}
.spine .vol {
  font-family: var(--f-display); font-size: .72rem; line-height: 1;
  color: var(--brass-2); opacity: .78;
  width: 20px; height: 20px; display: flex; align-items: center; justify-content: center;
}

/* Seam between the dark hero and the ivory content sheet. Reusable at any
   dark→light boundary: give it the incoming background colour and it works. */
.hero-seam { position: relative; z-index: 2; margin-top: -36px; }
.hero-seam-edge {
  height: 36px; background: var(--white);
  -webkit-mask: var(--deckle) repeat-x bottom / 1200px 36px;
          mask: var(--deckle) repeat-x bottom / 1200px 36px;
}
.hero-seam-orn {
  position: absolute; inset-inline: 0; bottom: -3px;
  text-align: center; line-height: 1;
  font-size: .85rem; color: var(--brass); opacity: .7;
}
/* the seam already is the boundary — a hairline under it would undo it */
.hero-seam + .section-alt { border-top: 0; }

/* ---------- 08 · SECTIONS ---------- */
.section { padding-block: var(--sp-7); }
/* From the tablet break up, sections breathe. The homepage runs several
   rails in sequence and at 3rem apart on a 1400px screen they read as one
   dense stack; the extra 1.5rem is what separates "a section ended" from
   "the list kept going". Below 900px the shorter rhythm stays — vertical
   space on a phone is the scarce thing, not the plentiful one. */
@media (min-width: 900px) { .section { padding-block: var(--sp-8); } }
.section-tight { padding-block: var(--sp-6); }
.section-alt { background: var(--white); border-block: 1px solid var(--line-soft); }
/* Two paper sections in a row (the featured rail and new arrivals) used
   to be separated by a band of white. The banding is gone — see the
   section order in index.html — so a hairline carries the boundary
   instead: quieter, and it does not chop the page into slabs.

   Both :not()s earn their place. .section-alt already draws its own
   border-block, and .collections is the dark band — either one would get
   a second hairline butted against the edge it already has. The pair this
   is actually for is two plain paper sections, which is the one case the
   removed banding left without a boundary. */
.section:not(.section-alt):not(.collections)
  + .section:not(.section-alt):not(.collections) {
  border-top: 1px solid var(--line-soft);
}
.sec-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--sp-4); margin-bottom: var(--sp-5);
}
.sec-head h2 { font-family: var(--f-display); font-size: var(--fs-h2); line-height: 1.3; }
.sec-head .more {
  font-size: var(--fs-small); font-weight: 600; color: var(--emerald);
  display: inline-flex; align-items: center; gap: .4em; white-space: nowrap;
  padding-block: .4em;
}
.sec-head .more svg { width: 16px; height: 16px; transition: transform .25s var(--ease); }
.sec-head .more:hover svg { transform: translateX(-4px); }
/* The arrow glyph points along the reading direction; it is drawn pointing
   left for RTL, so LTR flips it — and the hover nudge with it. */
[dir="ltr"] .sec-head .more svg { transform: scaleX(-1); }
[dir="ltr"] .sec-head .more:hover svg { transform: scaleX(-1) translateX(-4px); }

/* horizontal scroller (mobile-first product rows) */
.hscroll {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: clamp(158px, 44vw, 220px);
  gap: var(--sp-4);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  padding: 4px 4px var(--sp-4);
  margin-inline: -4px;
  scrollbar-width: none;
}
.hscroll::-webkit-scrollbar { display: none; }
.hscroll > * { scroll-snap-align: start; }
@media (min-width: 1000px) { .hscroll { grid-auto-columns: 208px; gap: var(--sp-5); } }

/* ---------- 08b · RAIL NAVIGATION ----------
   Arrows for a .hscroll. The rail itself is unchanged — it is still a
   native scroll container, so touch, trackpad and keyboard keep working
   exactly as before and these are purely an addition for pointer users.

   The buttons sit INSIDE the rail's box (inset, not outside it), because
   a control hanging off the edge of a full-bleed row is what pushes a
   page into horizontal overflow on a phone. */
.rail { position: relative; }
.rail-btn {
  position: absolute; top: calc(50% - 40px); z-index: 3;
  width: 38px; height: 38px; border-radius: 50%;
  background: rgba(253,251,246,.96); color: var(--emerald);
  border: 1px solid var(--line-soft); box-shadow: var(--shadow-1);
  display: none; align-items: center; justify-content: center;
  transition: opacity .2s var(--ease), background .2s var(--ease), box-shadow .2s var(--ease);
}
/* Only shown once the rail actually overflows — otherwise they are
   furniture that does nothing. .rail-on is set by initRails(). */
.rail.rail-on .rail-btn { display: flex; }
.rail-btn:hover { background: var(--white); box-shadow: var(--shadow-2); }
.rail-btn:disabled { opacity: 0; pointer-events: none; }
.rail-btn svg { width: 18px; height: 18px; }
.rail-back { inset-inline-start: 2px; }
.rail-fwd  { inset-inline-end: 2px; }
/* Phones lead with the swipe; the arrows stay available but small and
   quiet so they never sit on top of a card's title. */
@media (min-width: 1000px) {
  .rail-btn { width: 42px; height: 42px; }
  .rail-back { inset-inline-start: -8px; }
  .rail-fwd  { inset-inline-end: -8px; }
}
.section-alt .rail-btn { background: var(--paper); }

/* ---------- 09 · BOOK COVERS (typeset, no stock imagery) ---------- */
.bcover {
  aspect-ratio: 5 / 7.2; width: 100%;
  border-radius: 3px 6px 6px 3px;
  position: relative; overflow: hidden;
  background: var(--bc-bg, var(--emerald));
  box-shadow: inset -3px 0 6px rgba(0,0,0,.28), inset 1px 0 0 rgba(255,255,255,.06);
  display: flex; flex-direction: column; align-items: center;
  text-align: center; padding: 9% 10%;
  color: var(--bc-text, #EFE6D2);
  container-type: inline-size;
}
.bcover::before { /* spine shadow edge */
  content: ""; position: absolute; inset-block: 0; inset-inline-end: 0; width: 7%;
  background: linear-gradient(to left, rgba(0,0,0,.32), transparent);
}
.bcover::after { /* inner frame */
  content: ""; position: absolute; inset: 5.5%;
  border: 1px solid color-mix(in srgb, var(--bc-accent, var(--brass-2)) 55%, transparent);
  outline: 1px solid color-mix(in srgb, var(--bc-accent, var(--brass-2)) 25%, transparent);
  outline-offset: 3px;
  pointer-events: none; border-radius: 2px;
}
.bcover .bc-orn { color: var(--bc-accent, var(--brass-2)); font-size: 7cqw; margin-top: 6%; letter-spacing: .4em; }
/* Capped: real catalogue titles run long, and on a wide card an uncapped
   cqw size sets them at ~40px, which clips inside the cover. */
.bcover .bc-title {
  font-family: var(--f-display); font-weight: 700;
  font-size: min(10.5cqw, 30px); line-height: 1.5;
  margin-block: auto; padding-inline: 2%;
  display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden;
}
.bcover .bc-author { font-size: 6cqw; opacity: .8; font-family: var(--f-display); }
.bcover .bc-pub {
  font-size: 4.6cqw; margin-top: 7%; letter-spacing: .12em;
  color: var(--bc-accent, var(--brass-2)); opacity: .9;
}
.bcover .bc-vols {
  position: absolute; top: 8%; inset-inline-start: 0;
  background: color-mix(in srgb, var(--bc-accent, var(--brass-2)) 90%, black);
  color: #211E19;
  font-size: 5cqw; font-weight: 700; padding: .3em .9em .3em .7em;
  border-radius: 0 3px 3px 0;
}
[dir="rtl"] .bcover .bc-vols { border-radius: 3px 0 0 3px; }

/* Real cover artwork. The frame keeps the grid's rhythm — every card is
   still the same height — while the artwork keeps its own proportions:
   `contain`, never `cover`. A book cover is printed TEXT, so cropping it
   cuts the title and stretching it makes it unreadable. Whatever ratio
   the file happens to be, the whole cover is visible, centred, on a paper
   ground that reads as the shelf behind it. */
.bcover-img {
  background: var(--paper-2);
  padding: 0;
  box-shadow: none;
  justify-content: center;
  align-items: center;
}
.bcover-img::before, .bcover-img::after { content: none; }
.bcover-img > [data-cover-placeholder] { display: none; }
.bcover-img .bc-img {
  width: 100%; height: 100%;
  object-fit: contain;
  /* Reading position, not centre: a taller-than-frame cover should sit on
     the shelf line rather than float. */
  object-position: center;
}
.mini .bcover-img { padding: 6%; }

/* Mini covers (≤80px) — set text is illegible at this size and reads as
   noise, so the cover reduces to its ornament + frame: a clean, deliberate
   abstraction of a bound volume. Palette still distinguishes each title. */
.mini { display: block; }
.mini .bcover {
  border-radius: 2px 4px 4px 2px; padding: 12% 10%;
  justify-content: center;
}
.mini .bcover::after { inset: 9%; outline: none; }
.mini .bc-title, .mini .bc-author, .mini .bc-pub, .mini .bc-vols { display: none; }
.mini .bc-orn { margin: 0; font-size: 26cqw; letter-spacing: 0; line-height: 1; }

/* ---------- 10 · PRODUCT CARD ---------- */
.pcard { position: relative; display: flex; flex-direction: column; gap: var(--sp-3); }
.pcard-media {
  position: relative; border-radius: var(--r-md); overflow: visible;
}
.pcard-media > a { display: block; transition: transform .35s var(--ease); }
.pcard:hover .pcard-media > a { transform: translateY(-5px); }
.pcard-media .bcover { box-shadow: inset -3px 0 6px rgba(0,0,0,.28), var(--shadow-1); transition: box-shadow .35s var(--ease); }
.pcard:hover .bcover { box-shadow: inset -3px 0 6px rgba(0,0,0,.28), var(--shadow-2); }
.pcard-badges { position: absolute; top: 8px; inset-inline-end: 8px; display: flex; flex-direction: column; gap: 4px; z-index: 2; align-items: flex-end; }
.pcard-fav {
  position: absolute; bottom: 8px; inset-inline-end: 8px; z-index: 2;
  width: 38px; height: 38px; border-radius: 50%;
  background: rgba(253,251,246,.92); box-shadow: var(--shadow-1);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-soft); transition: color .2s, transform .2s var(--ease);
}
.pcard-fav:hover { transform: scale(1.08); }
.pcard-fav.active { color: var(--danger); }
.pcard-fav svg { width: 18px; height: 18px; }
.pcard-body { display: flex; flex-direction: column; gap: 2px; }
.pcard-cat { font-size: var(--fs-tiny); color: var(--brass); font-weight: 600; }
.pcard-title {
  font-family: var(--f-display); font-weight: 700;
  font-size: 1.02rem; line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: 3.05em;
}
.pcard-title a:hover { color: var(--emerald-2); }
.pcard-author { font-size: var(--fs-small); color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pcard-meta { font-size: var(--fs-tiny); color: var(--ink-faint); }
.pcard-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); margin-top: var(--sp-1); }
/* The card price stacks rather than sitting on a baseline: wholesale shows
   two figures (net, then list × rate) and side-by-side they read as one
   long number. */
.price { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.price .now { font-size: 1.06rem; }
.price .was { font-size: var(--fs-small); color: var(--ink-faint); text-decoration: line-through; font-weight: 400; }
/* "$97 −%60" — the list price is struck through because the dealer does
   not pay it; the rate beside it says why. */
.price-from {
  font-size: var(--fs-tiny); color: var(--ink-faint); font-weight: 400;
  text-decoration: line-through; white-space: nowrap;
}
.price-from i { font-style: normal; text-decoration: none; color: var(--brass); font-weight: 600; }

/* ---------- warehouse chip (cards) ----------
   Names the warehouses that have it, never a count. */
.stock-chip {
  font-size: var(--fs-tiny); font-weight: 600;
  display: inline-flex; align-items: center; gap: .35em;
  margin-top: 3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.stock-chip::before { content: "●"; font-size: .7em; }
.stock-chip.is-ok   { color: var(--emerald-2); }
.stock-chip.is-low  { color: var(--brass); }
.stock-chip.is-none { color: var(--ink-faint); }

/* An out-of-stock title is NOT dimmed. It was — opacity .62 on the cover
   — and it made a third of the catalogue look like the photographs had
   failed to load rather than like the stock had run out. The claim was
   also weaker than it looked: only Beirut reports today, so "0 in
   Beirut" is not "unavailable", and fading the picture said it was.

   The state is carried by the chip and the disabled button instead, which
   say the same thing without damaging the one part of the card a dealer
   is actually reading. */
.pcard-out {
  font-size: var(--fs-tiny); font-weight: 600; color: var(--ink-faint);
  border: 1px solid var(--line); border-radius: 999px; padding: .45em 1em;
}
.pcard-add {
  width: 42px; height: 42px; border-radius: 50%;
  background: var(--emerald); color: var(--white);
  display: flex; align-items: center; justify-content: center;
  transition: background .2s, transform .2s var(--ease);
  flex-shrink: 0;
}
.pcard-add:hover { background: var(--emerald-2); transform: scale(1.06); }
.pcard-add svg { width: 19px; height: 19px; }

/* Grid version. minmax(0, 1fr) — not plain 1fr — because a track's default
   floor is its min-content, and the cover title's cqw-based font size makes
   that min-content enormous, blowing the grid past its container. */
.pgrid {
  display: grid; gap: var(--sp-5) var(--sp-4);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 640px)  { .pgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .pgrid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-6) var(--sp-5); } }
@media (min-width: 1240px) { .pgrid-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

/* ---------- 11 · CATEGORY CARD ---------- */
.catgrid {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 640px)  { .catgrid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1000px) { .catgrid { grid-template-columns: repeat(5, 1fr); gap: var(--sp-4); } }
.catcard {
  background: var(--white); border: 1px solid var(--line-soft);
  border-radius: var(--r-md); padding: var(--sp-5) var(--sp-4);
  display: flex; flex-direction: column; gap: var(--sp-2);
  transition: border-color .25s var(--ease), box-shadow .25s var(--ease), transform .25s var(--ease);
}
.catcard:hover { border-color: var(--brass); box-shadow: var(--shadow-1); transform: translateY(-3px); }
.catcard .glyph {
  font-family: var(--f-display); font-size: 1.7rem; color: var(--brass);
  width: 48px; height: 48px; border: 1px solid var(--paper-3); border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--paper);
}
.catcard h3 { font-family: var(--f-display); font-size: 1.08rem; }
.catcard .count { font-size: var(--fs-tiny); color: var(--ink-faint); }

/* ---------- 12 · COLLECTIONS (multi-volume feature) ---------- */
.collections {
  background:
    radial-gradient(100% 120% at 15% 0%, #1B5244 0%, transparent 50%),
    linear-gradient(200deg, #0E322A, #081F1A);
  color: var(--white); overflow: hidden; position: relative;
}
.collections .t-kicker { color: var(--brass-2); }
.collections .t-kicker::before { background: var(--brass-2); }
.coll-grid { display: grid; gap: var(--sp-6); align-items: center; }
@media (min-width: 900px) { .coll-grid { grid-template-columns: 1fr 1fr; } }
.coll-copy h2 { font-family: var(--f-display); font-size: var(--fs-h2); margin-block: var(--sp-3) var(--sp-4); }
.coll-copy p { color: rgba(253,251,246,.72); max-width: 32em; font-weight: 300; }
.coll-points { margin-block: var(--sp-5); display: grid; gap: var(--sp-3); }
.coll-points li { display: flex; gap: .8em; align-items: baseline; font-size: var(--fs-small); color: rgba(253,251,246,.85); }
.coll-points li::before { content: "◆"; color: var(--brass-2); font-size: .6em; }
.coll-sets { display: grid; gap: var(--sp-3); }
.coll-set {
  display: flex; align-items: center; gap: var(--sp-4);
  background: rgba(253,251,246,.05);
  border: 1px solid rgba(253,251,246,.12);
  border-radius: var(--r-md); padding: var(--sp-3) var(--sp-4);
  transition: background .25s var(--ease), border-color .25s var(--ease);
}
.coll-set:hover { background: rgba(253,251,246,.09); border-color: var(--brass); }
.coll-set .mini { width: 52px; flex-shrink: 0; }
.coll-set-info { min-width: 0; }
.coll-set-info h3 { font-family: var(--f-display); font-size: 1.02rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.coll-set-info span { font-size: var(--fs-tiny); color: var(--brass-2); }
.coll-set .price { margin-inline-start: auto; color: var(--white); flex-shrink: 0; }
.coll-set .price .was { color: rgba(253,251,246,.45); }

/* ---------- 13 · EDITORIAL ---------- */
.edgrid { display: grid; gap: var(--sp-4); }
@media (min-width: 900px) { .edgrid { grid-template-columns: repeat(3, 1fr); gap: var(--sp-5); } }
.edcard {
  background: var(--white); border: 1px solid var(--line-soft); border-radius: var(--r-md);
  padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-3);
  transition: box-shadow .25s var(--ease), transform .25s var(--ease);
}
.edcard:hover { box-shadow: var(--shadow-1); transform: translateY(-3px); }
.edcard .t-kicker { font-size: .68rem; }
.edcard h3 { font-family: var(--f-display); font-size: 1.18rem; line-height: 1.55; }
.edcard p { font-size: var(--fs-small); color: var(--ink-soft); }
.edcard .link { margin-top: auto; font-size: var(--fs-small); font-weight: 600; color: var(--emerald); }

/* Blog card — the editorial card with an image slot and a date line. It
   deliberately reuses .edcard rather than introducing a second card
   shape: the same border, radius, shadow and spacing tokens, so a post
   sits beside the house cards without looking bolted on. */
.blogcard { padding: 0; overflow: hidden; }
.blogcard > *:not(.blogcard-media) { margin-inline: var(--sp-5); }
.blogcard > :last-child { margin-bottom: var(--sp-5); }
.blogcard-media {
  display: block; aspect-ratio: 16 / 9; background: var(--paper-2);
  border-bottom: 1px solid var(--line-soft);
}
.blogcard-media img { width: 100%; height: 100%; object-fit: cover; }
/* A post with no artwork gets the house ornament, not a grey box. */
.blogcard-orn {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 16 / 5; margin: 0 !important;
  background: linear-gradient(160deg, var(--paper-2), var(--paper-3));
  border-bottom: 1px solid var(--line-soft);
  color: var(--brass); font-size: 1.5rem; letter-spacing: .4em;
}
.blogcard-media + .blogcard-meta, .blogcard-orn + .blogcard-meta { margin-top: var(--sp-5); }
.blogcard-meta {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap;
}
.blogcard-meta time { font-size: var(--fs-tiny); color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.blogcard h3 { font-family: var(--f-display); font-size: 1.18rem; line-height: 1.55; }
.blogcard h3 a:hover { color: var(--emerald-2); }

/* ---------- 13b · BLOG PAGE ---------- */
.post { max-width: 46rem; margin-inline: auto; }
.post-head { display: flex; flex-direction: column; gap: var(--sp-3); }
.post-meta { display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap; }
.post-meta time { font-size: var(--fs-tiny); color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.post h1 { font-family: var(--f-display); font-size: var(--fs-h2); line-height: 1.4; }
.post-lede { color: var(--ink-soft); font-size: 1.05rem; line-height: 1.9; }
.post-cover {
  margin: var(--sp-6) 0 0; border-radius: var(--r-md); overflow: hidden;
  background: var(--paper-2); box-shadow: var(--shadow-1);
}
.post-cover img { width: 100%; height: auto; }
.post-body { margin-top: var(--sp-6); font-size: 1.02rem; line-height: 2; color: var(--ink-soft); }
.post-body p { margin-bottom: var(--sp-4); }
.post-foot {
  margin-top: var(--sp-7); padding-top: var(--sp-5);
  border-top: 1px solid var(--line-soft);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4); flex-wrap: wrap;
}
.post-foot .link { font-weight: 600; color: var(--emerald); font-size: var(--fs-small); }
.post-note {
  background: var(--paper-2); border: 1px solid var(--line-soft);
  border-radius: var(--r-md); padding: var(--sp-4);
  font-size: var(--fs-small); color: var(--ink-soft); margin-bottom: var(--sp-5);
}

/* ---------- 14 · TRUST / WHATSAPP ---------- */
.trust-strip {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--sp-4);
  padding-block: var(--sp-5);
}
@media (min-width: 900px) { .trust-strip { grid-template-columns: repeat(4, 1fr); } }
.trust-item { display: flex; gap: var(--sp-3); align-items: flex-start; }
.trust-item svg { width: 26px; height: 26px; color: var(--brass); flex-shrink: 0; margin-top: 2px; }
.trust-item b { display: block; font-size: var(--fs-small); }
.trust-item span { font-size: var(--fs-tiny); color: var(--ink-faint); }

.wa-band {
  background: var(--paper-2); border-block: 1px solid var(--line-soft);
  text-align: center; padding-block: var(--sp-7);
}
.wa-band h2 { font-family: var(--f-display); font-size: var(--fs-h3); margin-bottom: var(--sp-2); }
.wa-band p { color: var(--ink-soft); font-size: var(--fs-small); max-width: 36em; margin-inline: auto; margin-bottom: var(--sp-5); }
.btn-wa { background: #128C5A; color: var(--white); }
.btn-wa:hover { background: #0E7049; }
.btn-wa svg { width: 20px; height: 20px; }

/* Three languages, one number. Equal width so no language reads as the
   "real" one and the other two as afterthoughts. */
.wa-langs {
  display: grid; gap: var(--sp-3);
  grid-template-columns: 1fr;
  max-width: 34rem; margin-inline: auto;
}
@media (min-width: 640px) { .wa-langs { grid-template-columns: repeat(3, 1fr); } }
.wa-langs .btn-wa { width: 100%; }
/* The language code that labels each button. Set in a faint pill rather
   than plain text so it reads as a tag next to the language name instead
   of running into it as a second word. Sized in ch so all three codes come
   out the same width whatever the font does with the letters. */
.wa-code {
  flex: none;
  min-width: 2.75ch;
  padding: 0.15em 0.45em;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.18);
  font-size: 0.78em;
  font-weight: 700;
  line-height: 1.5;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
}

/* The product page's own enquiry button: full width under the buy row,
   where a reader who did not want to check out online will look. */
.pd-wa { margin-top: var(--sp-4); }

.wa-float {
  position: fixed; bottom: calc(var(--bottomnav-h) + 14px); inset-inline-start: 14px; z-index: 55;
  width: 52px; height: 52px; border-radius: 50%;
  background: #128C5A; color: var(--white);
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-2);
  transition: transform .2s var(--ease);
}
.wa-float:hover { transform: scale(1.07); }
.wa-float svg { width: 26px; height: 26px; }
@media (min-width: 1000px) { .wa-float { bottom: 22px; } }

/* ---------- 14b · SCROLL JUMP ----------
   Two explicit buttons rather than one that changes meaning as you scroll:
   a control whose destination flips under the cursor is the thing people
   misclick. Each is hidden when it would do nothing, so at the top you see
   only "down" and at the bottom only "up". Sits on the inline-end side —
   the WhatsApp float already owns inline-start. */
.scroll-jump {
  position: fixed; z-index: 54;
  bottom: calc(var(--bottomnav-h) + 14px); inset-inline-end: 14px;
  display: flex; flex-direction: column; gap: 8px;
}
@media (min-width: 1000px) { .scroll-jump { bottom: 22px; } }
.scroll-jump button {
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(253,251,246,.94); color: var(--emerald);
  border: 1px solid var(--line-soft);
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-1);
  opacity: 0; transform: translateY(6px); pointer-events: none;
  transition: opacity .25s var(--ease), transform .25s var(--ease), background .2s;
}
.scroll-jump button.on { opacity: 1; transform: none; pointer-events: auto; }
.scroll-jump button:hover { background: var(--white); box-shadow: var(--shadow-2); }
.scroll-jump svg { width: 20px; height: 20px; }
/* Nothing to jump to on a short page — the whole control stays out. */
.scroll-jump[hidden] { display: none; }

/* ---------- 15 · FOOTER ---------- */
.site-footer { background: var(--emerald-ink); color: rgba(253,251,246,.75); font-size: var(--fs-small); }
.footer-main { display: grid; gap: var(--sp-6); padding-block: var(--sp-7); }
@media (min-width: 900px) { .footer-main { grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: var(--sp-7); } }
.site-footer .brand-name { color: var(--white); font-size: 1.7rem; }
.site-footer .brand-name em { color: var(--brass-2); }
.footer-about p { margin-top: var(--sp-3); max-width: 30em; font-weight: 300; line-height: 1.9; }
.site-footer h4 {
  color: var(--white); font-size: .95rem; font-weight: 600;
  margin-bottom: var(--sp-4); letter-spacing: .02em;
}
.footer-links li { margin-bottom: .65em; }
.footer-links a { transition: color .2s; }
.footer-links a:hover { color: var(--brass-2); }
.footer-contact li { display: flex; gap: .7em; margin-bottom: .8em; align-items: baseline; }
.footer-contact svg { width: 15px; height: 15px; flex-shrink: 0; transform: translateY(2px); color: var(--brass-2); }
.footer-bottom {
  border-top: 1px solid rgba(253,251,246,.1);
  padding-block: var(--sp-4);
  display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; justify-content: space-between;
  font-size: var(--fs-tiny); color: rgba(253,251,246,.45);
}
.pay-marks { display: flex; gap: .6em; }
.pay-marks span {
  border: 1px solid rgba(253,251,246,.2); border-radius: 3px;
  padding: .15em .6em; letter-spacing: .04em;
}

/* ---------- 16 · BOTTOM NAV (mobile) ---------- */
.bottom-nav {
  position: fixed; bottom: 0; inset-inline: 0; z-index: 70;
  background: rgba(253,251,246,.96);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border-top: 1px solid var(--line-soft);
  display: grid; grid-template-columns: repeat(4, 1fr);
  height: var(--bottomnav-h);
  padding-bottom: env(safe-area-inset-bottom);
}
.bottom-nav a, .bottom-nav button {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  font-size: .64rem; font-weight: 500; color: var(--ink-faint);
  position: relative;
}
.bottom-nav svg { width: 22px; height: 22px; }
.bottom-nav .active { color: var(--emerald); }
.bottom-nav .cart-count { top: 6px; inset-inline-start: calc(50% - 22px); }
@media (min-width: 1000px) { .bottom-nav { display: none; } body { padding-bottom: 0; } }

/* ---------- 17 · CATEGORY PAGE ---------- */
.page-head { padding-block: var(--sp-6) var(--sp-4); }
.breadcrumb { font-size: var(--fs-tiny); color: var(--ink-faint); margin-bottom: var(--sp-3); display: flex; flex-wrap: wrap; gap: .5em; }
.breadcrumb a:hover { color: var(--emerald); }
.breadcrumb .sep { opacity: .5; }
.page-head h1 { font-family: var(--f-display); font-size: var(--fs-h2); }
.page-head .desc { color: var(--ink-soft); font-size: var(--fs-small); max-width: 44em; margin-top: var(--sp-2); }
.page-head .count { font-size: var(--fs-tiny); color: var(--ink-faint); margin-top: var(--sp-2); }

.filter-chips {
  display: flex; gap: var(--sp-2); overflow-x: auto; scrollbar-width: none;
  padding-block: var(--sp-2); margin-inline: calc(var(--sp-4) * -1); padding-inline: var(--sp-4);
}
.filter-chips::-webkit-scrollbar { display: none; }
.chip {
  flex-shrink: 0; padding: .45em 1.1em; border-radius: 999px;
  border: 1px solid var(--line); font-size: var(--fs-small); font-weight: 500;
  background: var(--white); color: var(--ink-soft); white-space: nowrap;
  transition: all .2s var(--ease);
}
.chip:hover { border-color: var(--ink); color: var(--ink); }
.chip.active { background: var(--emerald); border-color: var(--emerald); color: var(--white); }

/* Mobile: two even columns so the selects sit flush and the two
   checkboxes pair up. Desktop: a single row with sort pushed to the end. */
.toolbar {
  display: grid; grid-template-columns: 1fr 1fr; align-items: center;
  gap: var(--sp-3);
  padding-block: var(--sp-4); margin-bottom: var(--sp-4);
  border-bottom: 1px solid var(--line-soft);
}
.toolbar .select { width: 100%; }
.toolbar .spacer { display: none; }
.toolbar #pubFilter { order: 1; } .toolbar #sortSel { order: 2; }
.toolbar .toggle { order: 3; }
@media (min-width: 720px) {
  .toolbar { display: flex; flex-wrap: wrap; }
  .toolbar .select { width: auto; }
  .toolbar .spacer { display: block; margin-inline-start: auto; }
  .toolbar #pubFilter, .toolbar #sortSel, .toolbar .toggle { order: 0; }
}
.select {
  appearance: none; background: var(--white);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: .55em 2.4em .55em 1em; font-size: var(--fs-small);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2357503F' stroke-width='2.4'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: left .8em center;
  cursor: pointer; min-height: 42px;
}
[dir="rtl"] .select { padding: .55em 1em .55em 2.4em; }
.toggle {
  display: inline-flex; align-items: center; gap: .5em;
  font-size: var(--fs-small); color: var(--ink-soft); cursor: pointer; user-select: none;
}
.toggle input { accent-color: var(--emerald); width: 17px; height: 17px; cursor: pointer; }
.load-wrap { text-align: center; padding-block: var(--sp-6); }
.result-empty { text-align: center; padding-block: var(--sp-8); color: var(--ink-soft); }
.result-empty .glyph { font-family: var(--f-display); font-size: 3rem; color: var(--paper-3); }

/* ---------- 18 · PRODUCT PAGE ---------- */
.product-layout { display: grid; gap: var(--sp-6); padding-block: var(--sp-5) var(--sp-7); }
@media (min-width: 900px) {
  .product-layout { grid-template-columns: minmax(0, 460px) 1fr; gap: var(--sp-8); align-items: start; }
  .product-gallery { position: sticky; top: calc(var(--header-h) + var(--sp-4)); }
}
.gal-main {
  border-radius: var(--r-md); padding: clamp(1.2rem, 5vw, 2.6rem);
  background: linear-gradient(180deg, var(--paper-2), var(--paper-3));
  display: flex; justify-content: center;
}
.gal-main .bcover { max-width: 300px; box-shadow: inset -3px 0 6px rgba(0,0,0,.28), var(--shadow-2); }
.gal-main .setview { display: flex; align-items: flex-end; gap: 4px; filter: drop-shadow(0 14px 18px rgba(33,30,25,.3)); }
.gal-main .setview .spine { height: clamp(180px, 34vw, 280px); width: clamp(26px, 5vw, 40px); }
.setview-note { text-align: center; margin-top: var(--sp-4); font-size: var(--fs-tiny); color: var(--ink-faint); }
.gal-thumbs { display: flex; gap: var(--sp-2); margin-top: var(--sp-3); justify-content: center; }
.gal-thumb {
  width: 58px; height: 58px; border-radius: var(--r-sm);
  border: 1.5px solid var(--line); background: var(--paper-2);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-tiny); color: var(--ink-soft); font-weight: 600;
  transition: border-color .2s;
}
.gal-thumb.active { border-color: var(--emerald); color: var(--emerald); }

.pd-info { display: flex; flex-direction: column; gap: var(--sp-4); min-width: 0; }
.pd-cat { color: var(--brass); font-weight: 600; font-size: var(--fs-small); }
.pd-title { font-family: var(--f-display); font-size: clamp(1.6rem, 5vw, 2.3rem); line-height: 1.4; }
/* The export's Latin form of the title. A secondary line, never a
   replacement: it is a transliteration, not a translation. */
.pd-latin { color: var(--ink-faint); font-size: var(--fs-small); letter-spacing: .01em; margin-top: -.4em; }
.pd-author { color: var(--ink-soft); font-size: 1.02rem; }
.pd-author a { color: var(--emerald); font-weight: 500; }
.pd-author a:hover { text-decoration: underline; }
.pd-metarow { display: flex; flex-wrap: wrap; gap: .6em; }
.pd-price { padding-block: var(--sp-2); }
.pd-price .now { font-size: 1.9rem; font-weight: 700; color: var(--emerald); }
.pd-price .was { font-size: 1.1rem; color: var(--ink-faint); text-decoration: line-through; }
.pd-price .badge-discount { transform: translateY(-6px); }

/* ---------- wholesale price table ----------
   Three rows showing the arithmetic a dealer would otherwise do by hand:
   list, less the rate, equals what they pay. The net row is separated by a
   rule because it is the answer, not another term. */
.price-table {
  border: 1px solid var(--line); border-radius: var(--r-md);
  background: var(--white); padding: var(--sp-3) var(--sp-4);
  display: flex; flex-direction: column; gap: .35em;
}
.pr-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); }
.pr-row > span { color: var(--ink-soft); font-size: var(--fs-small); }
.pr-row > b { font-weight: 600; font-variant-numeric: tabular-nums; }
.pr-row.pr-disc > b { color: var(--brass); }
/* The dealer's own points, and then the two added up. The total is ruled
   off like a subtotal because that is what it is: the end of the rate
   arithmetic, before the net. Both rows appear only for an account that
   actually has extra points — otherwise the table is the three rows it
   has always been. */
.pr-row.pr-extra > b { color: var(--emerald-2); }
.pr-row.pr-total {
  border-top: 1px solid var(--line-soft);
  margin-top: .3em; padding-top: .45em;
}
.pr-row.pr-total > span { color: var(--ink); font-weight: 600; }
.pr-row.pr-total > b { color: var(--brass); }
.pr-net {
  border-top: 1px solid var(--line-soft);
  margin-top: .3em; padding-top: .55em;
}
.pr-net > span { color: var(--ink); font-weight: 600; font-size: var(--fs-base); }
.pr-net > b { font-size: 1.65rem; font-weight: 700; color: var(--emerald); }
.pr-note { font-size: var(--fs-tiny); color: var(--ink-faint); text-align: end; }

/* ---------- warehouse table (product page) ---------- */
.stock-box {
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: var(--sp-3) var(--sp-4); background: var(--paper);
}
.stock-head {
  display: block; font-size: var(--fs-tiny); font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint);
  margin-bottom: .5em;
}
.stock-list { display: flex; flex-wrap: wrap; gap: var(--sp-2) var(--sp-5); }
.stock-list li { display: flex; align-items: baseline; gap: .5em; font-size: var(--fs-small); }
.stock-list .wh { color: var(--ink-soft); }
.stock-list .st { font-weight: 600; }
.stock-list .st::before { content: "●"; font-size: .7em; margin-inline-end: .35em; }
.stock-list .is-ok   .st { color: var(--emerald-2); }
.stock-list .is-low  .st { color: var(--brass); }
.stock-list .is-none .st { color: var(--ink-faint); }
.stock-none-note { margin-top: .6em; font-size: var(--fs-tiny); color: var(--ink-soft); }

/* Packing floor and the running line total. */
.pd-min-note { font-size: var(--fs-small); color: var(--brass); font-weight: 500; }
.pd-linetotal { font-size: var(--fs-small); color: var(--ink-soft); min-height: 1.4em; }
.pd-linetotal b { color: var(--ink); font-variant-numeric: tabular-nums; }

.badge-min { background: var(--brass); color: var(--white); }
.badge-imprint { background: var(--paper-3); color: var(--ink-soft); border: 1px solid var(--line); }

.variant-box { border: 1px solid var(--line); border-radius: var(--r-md); overflow: hidden; }
.variant {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); cursor: pointer;
  border-top: 1px solid var(--line-soft); background: var(--white);
  transition: background .2s;
}
.variant:first-child { border-top: 0; }
.variant:hover { background: var(--paper); }
.variant input { accent-color: var(--emerald); width: 18px; height: 18px; }
.variant .vlabel { font-weight: 600; font-size: var(--fs-small); }
.variant .vsub { font-size: var(--fs-tiny); color: var(--ink-faint); }
.variant .vprice { margin-inline-start: auto; font-weight: 700; font-variant-numeric: tabular-nums; }
.variant.selected { background: color-mix(in srgb, var(--emerald) 5%, var(--white)); box-shadow: inset 3px 0 0 var(--emerald); }

.qty {
  display: inline-flex; align-items: center; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--white); height: 48px;
}
.qty button { width: 44px; height: 100%; font-size: 1.2rem; color: var(--ink-soft); }
.qty button:hover { color: var(--emerald); }
.qty output { min-width: 2.2em; text-align: center; font-weight: 600; font-variant-numeric: tabular-nums; }
.pd-actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.pd-actions .btn-primary { flex: 1; min-width: 180px; }
.pd-trust { display: flex; flex-wrap: wrap; gap: var(--sp-4); font-size: var(--fs-tiny); color: var(--ink-faint); }
.pd-trust span { display: inline-flex; gap: .45em; align-items: center; }
.pd-trust svg { width: 15px; height: 15px; color: var(--brass); }

.pd-tabs { border-top: 1px solid var(--line-soft); margin-top: var(--sp-2); }
.pd-tab { border-bottom: 1px solid var(--line-soft); }
.pd-tab summary {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--sp-4) 0; font-weight: 600; cursor: pointer; list-style: none;
  font-family: var(--f-display); font-size: 1.08rem;
}
.pd-tab summary::-webkit-details-marker { display: none; }
.pd-tab summary::after { content: "+"; font-size: 1.3rem; color: var(--brass); transition: transform .25s var(--ease); font-family: var(--f-body); }
.pd-tab[open] summary::after { transform: rotate(45deg); }
.pd-tab .tab-body { padding-bottom: var(--sp-5); color: var(--ink-soft); font-size: .95rem; line-height: 1.9; }
.spec-table { width: 100%; border-collapse: collapse; font-size: var(--fs-small); }
.spec-table td { padding: .6em 0; border-bottom: 1px dashed var(--line-soft); }
.spec-table td:first-child { color: var(--ink-faint); width: 38%; }

/* Uploaded gallery images on the product page. Same rule as the cover:
   contained, never cropped — a back cover and a sample page both carry
   text that a buyer is reading to judge the edition. */
.gal-figure {
  margin: 0; display: flex; align-items: center; justify-content: center;
  aspect-ratio: 5 / 7.2; background: var(--paper-2);
  border-radius: var(--r-md); overflow: hidden;
}
.gal-figure img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }

/* ---------- 19 · CART ---------- */
.cart-layout { display: grid; gap: var(--sp-5); padding-block: var(--sp-5) var(--sp-7); align-items: start; }
@media (min-width: 900px) { .cart-layout { grid-template-columns: 1.6fr 1fr; gap: var(--sp-7); } }
.cart-items { display: flex; flex-direction: column; }
.cart-item {
  display: grid; grid-template-columns: 76px 1fr auto; gap: var(--sp-4);
  padding-block: var(--sp-4); border-bottom: 1px solid var(--line-soft);
  align-items: center;
}
.ci-info { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.ci-title { font-family: var(--f-display); font-weight: 700; font-size: 1.02rem; line-height: 1.5; }
.ci-title a:hover { color: var(--emerald-2); }
.ci-meta { font-size: var(--fs-tiny); color: var(--ink-faint); }
.ci-controls { display: flex; align-items: center; gap: var(--sp-3); margin-top: var(--sp-2); flex-wrap: wrap; }
.ci-controls .qty { height: 38px; }
.ci-controls .qty button { width: 36px; }
.ci-remove { font-size: var(--fs-tiny); color: var(--ink-faint); text-decoration: underline; }
.ci-remove:hover { color: var(--danger); }
.ci-price { text-align: end; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.ci-price .was { display: block; font-size: var(--fs-tiny); color: var(--ink-faint); text-decoration: line-through; font-weight: 400; }

.cart-summary {
  background: var(--white); border: 1px solid var(--line-soft); border-radius: var(--r-md);
  padding: var(--sp-5);
  position: sticky; top: calc(var(--header-h) + var(--sp-4));
}
.cart-summary h2 { font-family: var(--f-display); font-size: 1.3rem; margin-bottom: var(--sp-4); }
.sum-row { display: flex; justify-content: space-between; font-size: var(--fs-small); padding-block: .5em; color: var(--ink-soft); }
.sum-row b { color: var(--ink); font-variant-numeric: tabular-nums; }
.sum-row.total { border-top: 1px solid var(--line); margin-top: var(--sp-3); padding-top: var(--sp-4); font-size: 1.05rem; color: var(--ink); }
.sum-row.total b { font-size: 1.3rem; color: var(--emerald); }
.sum-row .free { color: var(--emerald-2); font-weight: 600; }
/* The free-shipping ladder (.ship-note / .ship-bar) is gone with the
   shipping itself — see cart.js. */
.sum-row.sum-save b { color: var(--brass); }
.sum-note {
  font-size: var(--fs-tiny); color: var(--ink-faint);
  margin-top: var(--sp-3); line-height: 1.7;
}
.ci-unit { display: block; font-size: var(--fs-tiny); color: var(--ink-faint); font-weight: 400; }
.ci-min { font-size: var(--fs-tiny); color: var(--brass); font-weight: 600; }

.cart-empty { text-align: center; padding-block: var(--sp-8); }
.cart-empty .glyph { font-family: var(--f-display); font-size: 3.4rem; color: var(--paper-3); }
.cart-empty h2 { font-family: var(--f-display); margin-block: var(--sp-3); }
.cart-empty p { color: var(--ink-soft); font-size: var(--fs-small); margin-bottom: var(--sp-5); }

/* ---------- order form ----------
   Sits below the sheet on the same page: a dealer reconciling their list
   against their own records should not have to navigate away from one to
   fill in the other. */
.order-form {
  margin-top: var(--sp-7); padding: var(--sp-6);
  background: var(--white); border: 1px solid var(--line); border-radius: var(--r-md);
}
.of-head h2 { font-family: var(--f-display); font-size: 1.4rem; }
.of-head p { color: var(--ink-soft); font-size: var(--fs-small); margin-top: var(--sp-2); max-width: 54ch; line-height: 1.8; }

.of-grid { display: grid; gap: var(--sp-4); margin-top: var(--sp-5); }
@media (min-width: 700px) { .of-grid { grid-template-columns: 1fr 1fr; } }

.of-field { display: flex; flex-direction: column; gap: 6px; }
.of-field > span { font-size: var(--fs-small); font-weight: 600; color: var(--ink-soft); }
.of-field > span i { color: var(--danger); font-style: normal; }
.of-field input,
.of-field textarea {
  font: inherit; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: .75em .9em; width: 100%;
  transition: border-color .2s, box-shadow .2s;
}
.of-field textarea { resize: vertical; min-height: 5.5em; }
.of-field input:focus-visible,
.of-field textarea:focus-visible {
  outline: 0; border-color: var(--emerald-2);
  box-shadow: 0 0 0 3px rgba(27, 82, 68, .13);
}
/* :user-invalid, not :invalid — the latter matches an empty required field
   from the moment it renders, so a form the dealer has not touched yet
   greets them with a wall of red. :user-invalid waits until they have
   actually typed in the field and left it. */
.of-field.is-req input:user-invalid { border-color: var(--danger); }

.of-pay { border: 0; padding: 0; margin-top: var(--sp-5); }
.of-pay legend { font-size: var(--fs-small); font-weight: 600; color: var(--ink-soft); margin-bottom: var(--sp-2); }
.of-radio {
  display: inline-flex; align-items: center; gap: .55em;
  padding: .6em 1.1em; margin-inline-end: var(--sp-3);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--paper); cursor: pointer; font-size: var(--fs-small);
  transition: border-color .2s, background .2s;
}
.of-radio:has(input:checked) { border-color: var(--emerald); background: var(--white); font-weight: 600; }

.of-field:has(textarea) { margin-top: var(--sp-5); }
.of-legal {
  font-size: var(--fs-tiny); color: var(--ink-faint);
  margin-block: var(--sp-5) var(--sp-4); line-height: 1.8; max-width: 70ch;
}
.btn-lg { padding-block: 1em; font-size: 1.02rem; }

.of-status { margin-top: var(--sp-3); font-size: var(--fs-small); min-height: 1.5em; text-align: center; }
.of-status.is-err  { color: var(--danger); }
.of-status.is-busy { color: var(--ink-soft); }
/* Bayi hesabının onaylandığını ve başvurunun alındığını bildirir —
   bkz. assets/js/dealer.js. Yeşil, çünkü bu satırların hepsi "işlem
   oldu" diyor; is-busy'nin grisi "bekleyin" demektir. */
.of-status.is-ok   { color: var(--emerald); font-weight: 600; }
.of-status a { color: var(--emerald); font-weight: 600; text-decoration: underline; }

.order-sent { text-align: center; padding-block: var(--sp-8); }
.order-sent .glyph {
  width: 62px; height: 62px; margin: 0 auto var(--sp-4);
  display: grid; place-items: center; font-size: 1.9rem;
  border-radius: 50%; background: var(--emerald); color: var(--white);
}
.order-sent h2 { font-family: var(--f-display); margin-bottom: var(--sp-3); }
.order-sent p { color: var(--ink-soft); font-size: var(--fs-small); max-width: 46ch; margin: 0 auto var(--sp-3); line-height: 1.8; }
.os-ref { font-size: var(--fs-base) !important; }
.os-ref b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* ---------- 20 · SEARCH OVERLAY / MODAL / TOAST ---------- */
.search-overlay {
  position: fixed; inset: 0; z-index: 100; background: var(--paper);
  display: none; flex-direction: column;
}
.search-overlay.open { display: flex; }
.search-head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-4); border-bottom: 1px solid var(--line-soft);
  max-width: var(--container); margin-inline: auto; width: 100%;
}
.search-head > span { flex: none; }
.search-head > span svg { width: 22px; height: 22px; }
.search-input {
  flex: 1; border: 0; background: transparent; font-size: 1.15rem;
  font-family: var(--f-body); min-width: 0;
}
.search-input:focus { outline: none; }
.search-body { flex: 1; overflow-y: auto; padding: var(--sp-4); max-width: var(--container); margin-inline: auto; width: 100%; }
.search-hint { font-size: var(--fs-small); color: var(--ink-faint); margin-bottom: var(--sp-3); }
.search-pop { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.sr-list { display: flex; flex-direction: column; }
.sr-item {
  display: grid; grid-template-columns: 44px 1fr auto; gap: var(--sp-3);
  align-items: center; padding: var(--sp-3) var(--sp-2);
  border-radius: var(--r-sm); transition: background .15s;
}
.sr-item:hover { background: var(--white); }
.sr-item .t { font-family: var(--f-display); font-weight: 700; font-size: .98rem; }
.sr-item .a { font-size: var(--fs-tiny); color: var(--ink-faint); }
.sr-item .p { font-weight: 700; font-size: var(--fs-small); white-space: nowrap; }

.modal {
  position: fixed; inset: 0; z-index: 110; display: none;
  align-items: center; justify-content: center; padding: var(--sp-4);
}
.modal.open { display: flex; }
.modal-scrim { position: absolute; inset: 0; background: rgba(20,18,14,.55); }
.modal-card {
  position: relative; background: var(--paper); border-radius: var(--r-lg);
  padding: var(--sp-6); max-width: 420px; width: 100%; text-align: center;
  box-shadow: var(--shadow-2);
}
.modal-card .glyph { font-family: var(--f-display); font-size: 2.4rem; color: var(--brass); }
.modal-card h3 { font-family: var(--f-display); font-size: 1.3rem; margin-block: var(--sp-3) var(--sp-2); }
.modal-card p { font-size: var(--fs-small); color: var(--ink-soft); margin-bottom: var(--sp-5); }

.toast {
  position: fixed; bottom: calc(var(--bottomnav-h) + 16px); inset-inline: var(--sp-4); z-index: 120;
  display: flex; justify-content: center; pointer-events: none;
}
@media (min-width: 1000px) { .toast { bottom: 24px; } }
.toast-card {
  background: var(--ink); color: var(--paper);
  border-radius: var(--r-md); padding: .8em 1.4em;
  font-size: var(--fs-small); box-shadow: var(--shadow-2);
  display: flex; align-items: center; gap: .8em;
  opacity: 0; transform: translateY(12px);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
  pointer-events: auto; max-width: 100%;
}
.toast-card.show { opacity: 1; transform: translateY(0); }
.toast-card a { color: var(--brass-2); font-weight: 600; white-space: nowrap; }

/* ---------- 22 · INTERACTIVE SHELF ---------- */
/* Each spine is its own button, so "slicing" is just styling.
   Siblings dim on shelf-hover to point at the one under the cursor. */
/* Resting state: each volume casts onto its neighbour and sits a hair under
   full size, so the hover lift has somewhere to travel from. The hover rule
   below is one pseudo-class more specific and still wins outright. */
.hero-shelf .spine {
  border: 0; cursor: pointer; position: relative;
  min-width: 0; flex: 0 1 50px;
  transform: scale(.985);
  box-shadow:
    4px 8px 14px rgba(0,0,0,.42),
    -3px 6px 12px rgba(0,0,0,.26),
    inset 0 2px 0 rgba(255,255,255,.1);
  transition: transform .45s var(--ease), box-shadow .45s var(--ease), opacity .35s var(--ease);
  -webkit-tap-highlight-color: transparent;
}
.hero-shelf:hover .spine, .hero-shelf:focus-within .spine { opacity: .55; }
.hero-shelf .spine:hover, .hero-shelf .spine:focus-visible {
  opacity: 1; z-index: 2;
  transform: translateY(-8px) scale(1.03);
  box-shadow: 0 18px 34px rgba(0,0,0,.5), inset 0 2px 0 rgba(255,255,255,.16);
}
.hero-shelf .spine:focus-visible { outline: 2px solid var(--brass-2); outline-offset: 4px; }
.hero-shelf .spine::after { /* gilt edge that lights up on hover */
  content: ""; position: absolute; inset-inline: 20%; bottom: 6px; height: 1px;
  background: var(--brass-2); opacity: 0; transition: opacity .35s var(--ease);
}
.hero-shelf .spine:hover::after, .hero-shelf .spine:focus-visible::after { opacity: .9; }
.shelf-hint {
  text-align: center; margin-top: var(--sp-3);
  font-size: var(--fs-tiny); color: rgba(253,251,246,.5); letter-spacing: .04em;
}
@media (max-width: 600px) {
  .hero-shelf { padding-inline: 10px; gap: 4px; }
  .hero-shelf .spine { flex-basis: 34px; padding-inline: 0; }
}
@media (max-width: 360px) {
  .hero-shelf { padding-inline: 12px; gap: 4px; }
}

/* ---------- 23 · BOOKFLIP MODAL ---------- */
:root {
  --parchment:   #F3E8D2;
  --parchment-2: #E8D9BC;
  --parch-ink:   #3A3122;
}
.flip { position: fixed; inset: 0; z-index: 130; display: flex; }
.flip[hidden] { display: none; }
.flip-scrim {
  position: absolute; inset: 0; background: rgba(12,20,17,.78);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  opacity: 0; transition: opacity .3s var(--ease);
}
.flip.open .flip-scrim { opacity: 1; }
.flip-shell {
  position: relative; margin: auto; width: min(1040px, 100%);
  padding: var(--sp-5) var(--sp-4);
  opacity: 0; transform: scale(.96) translateY(10px);
  transition: opacity .32s var(--ease), transform .32s var(--ease);
  max-height: 100dvh;
  /* The swinging cover sweeps past the spread's edge. On desktop it lands
     on the facing page and stays inside the book; on phones the pages are
     stacked, so it swings clear of the card and its transform overflows
     this box for the length of the animation. In RTL that overflow lands
     on the scrollable side.

     `hidden` — not `clip`, which would be the better tool. `clip` is the
     one that hides overflow WITHOUT making the element a scroll container,
     but CSS does not allow it next to a scrolling axis: with
     `overflow-y: auto` here, `overflow-x: clip` computes back to `hidden`
     (verified in Chrome). So this box is unavoidably scrollable sideways
     by script even though no scrollbar exists, and the guarantee that
     nothing ever scrolls it has to live in bookflip.js — see the comment
     above open(), which is where the off-centre-on-open bug came from. */
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
}
.flip.open .flip-shell { opacity: 1; transform: none; }
/* Closes at the inline END of its row — top-left in Arabic, top-right in
   Latin — matching the drawer and the search overlay. It rides in the bar's
   flex flow rather than being absolutely positioned on top of it, or it
   lands on the sound toggle, which also ends up at the inline end. */
.flip-x {
  order: 2; margin-inline-start: auto; z-index: 6;
  width: 44px; height: 44px; border-radius: 50%; flex: none;
  background: rgba(253,251,246,.94); color: var(--ink);
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-2);
  transition: transform .2s var(--ease);
}
.flip-x:hover { transform: rotate(90deg); }
.flip-x svg { width: 20px; height: 20px; }

/* the spread */
.flip-book {
  display: grid; grid-template-columns: 1fr 1fr;
  perspective: 2400px; perspective-origin: 50% 45%;
  border-radius: 3px;
  box-shadow: 0 40px 80px rgba(0,0,0,.55);
  position: relative;
}
.flip-book::after { /* gutter shadow down the spine */
  content: ""; position: absolute; inset-block: 0; inset-inline-start: 50%;
  width: 60px; transform: translateX(50%); pointer-events: none; z-index: 3;
  background: linear-gradient(90deg, transparent, rgba(58,49,34,.22), transparent);
}
.pg {
  background: var(--parchment);
  background-image:
    radial-gradient(120% 100% at 50% 0%, rgba(255,255,255,.5), transparent 60%),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.75' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 .42 0 0 0 0 .34 0 0 0 0 .19 0 0 0 .09 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23p)'/%3E%3C/svg%3E");
  color: var(--parch-ink);
  padding: clamp(1.4rem, 3.4vw, 2.6rem);
  min-height: min(560px, 72vh);
  position: relative; overflow: hidden; min-width: 0;
}
/* Both pages are placed explicitly: the leaves also sit in cell 1/1, and
   auto-placement would otherwise push each page one cell further on. */
/* Rounded on the outer (fore-)edge only; the spine edge stays square. */
.pg-right { grid-area: 1 / 1; border-radius: 0 3px 3px 0; box-shadow: inset -22px 0 30px -22px rgba(58,49,34,.5); }
.pg-left  { grid-area: 1 / 2; border-radius: 3px 0 0 3px; box-shadow: inset  22px 0 30px -22px rgba(58,49,34,.5); background-color: var(--parchment-2); }
.pg-inner { display: flex; flex-direction: column; gap: var(--sp-3); height: 100%; }
.pg .t-kicker { color: #8A6E2F; }
.pg .t-kicker::before { background: #8A6E2F; }
.pg-folio {
  position: absolute; top: var(--sp-4); inset-inline-start: var(--sp-4);
  font-size: var(--fs-tiny); color: rgba(58,49,34,.45); letter-spacing: .08em;
}
.pg-title { font-family: var(--f-display); font-size: clamp(1.3rem, 3vw, 1.8rem); line-height: 1.45; }
.pg-vol { font-family: var(--f-display); font-size: 1.1rem; color: #8A6E2F; }
.pg-rule { display: flex; align-items: center; gap: .8em; color: rgba(138,110,47,.6); }
.pg-rule::before, .pg-rule::after { content: ""; height: 1px; background: currentColor; flex: 1; }
.pg-rule span { font-size: .8rem; }
.pg-kutub { font-family: var(--f-display); font-size: 1.02rem; line-height: 1.9; }
.pg-note { font-size: var(--fs-small); line-height: 1.95; color: rgba(58,49,34,.82); }
.pg-specs { margin: auto 0 0; display: grid; gap: .45em; font-size: var(--fs-small); }
.pg-specs > div { display: flex; gap: .6em; border-bottom: 1px dashed rgba(58,49,34,.2); padding-bottom: .45em; }
.pg-specs dt { color: rgba(58,49,34,.5); min-width: 6.5em; }
.pg-specs dd { margin: 0; font-weight: 600; }
.pg-price { display: flex; align-items: baseline; gap: .6em; }
.pg-price .now { font-family: var(--f-display); font-size: clamp(2rem, 5vw, 2.7rem); font-weight: 700; color: #1B5244; }
.pg-price .per { font-size: var(--fs-tiny); color: rgba(58,49,34,.55); }
.pg-qty { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); font-size: var(--fs-small); }
.pg-qty .qty { background: rgba(253,251,246,.7); border-color: rgba(58,49,34,.28); }
.pg-actions { display: grid; gap: var(--sp-2); }
.pg-actions .btn-outline { border-color: rgba(58,49,34,.35); color: var(--parch-ink); }
.pg-actions .btn-outline:hover { border-color: var(--parch-ink); background: rgba(253,251,246,.5); }
.pg-setnote {
  margin-top: auto; font-size: var(--fs-tiny); line-height: 1.9;
  border-top: 1px dashed rgba(58,49,34,.28); padding-top: var(--sp-3);
  display: flex; flex-direction: column; gap: 2px;
}
.pg-setnote b { font-size: var(--fs-small); }
.pg-setnote span { color: #7A5F28; }
.pg-setnote a { color: #1B5244; font-weight: 600; }
.pg-setnote a:hover { text-decoration: underline; }
.pg-trust { font-size: var(--fs-tiny); color: rgba(58,49,34,.5); display: flex; align-items: center; gap: .4em; }
.pg-trust svg { width: 14px; height: 14px; }
.pg-latin { font-size: var(--fs-tiny); color: rgba(58,49,34,.5); letter-spacing: .01em; }
.pg-body { font-size: var(--fs-small); line-height: 1.95; color: rgba(58,49,34,.85); overflow-y: auto; }
.pg-body p { margin-bottom: .7em; }
.pg-body b { color: var(--parch-ink); }
.pg-empty { font-size: var(--fs-small); color: rgba(58,49,34,.5); font-style: italic; }
.pg-specs-full dt { min-width: 7.5em; }
.pg-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: auto; padding-top: var(--sp-3); }
.pg-tags span {
  font-size: var(--fs-tiny); color: #7A5F28;
  border: 1px solid rgba(138,110,47,.35); border-radius: 3px; padding: .15em .55em;
}
.pg-full { font-size: var(--fs-tiny); color: #1B5244; font-weight: 600; margin-top: var(--sp-2); }
.pg-full:hover { text-decoration: underline; }
/* Sample page scan. `contain` is the whole point: an interior page is
   text, and cropping it to fill the leaf cuts off exactly the margins and
   headers a reader is checking. The parchment shows through around it,
   so a portrait scan on a landscape leaf reads as a page laid on a page. */
.pg-scan {
  margin: 0; flex: 1; min-height: 0;
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-2);
}
.pg-scan img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
  border-radius: 2px;
  box-shadow: 0 2px 10px rgba(58,49,34,.28);
  background: var(--parchment);
}
@media (max-width: 719px) { .pg-scan { min-height: 46vh; } }

/* Empty review state — deliberately quiet: no stars, no invented voices. */
.pg-none { margin: auto 0; text-align: center; display: grid; gap: 6px; }
.pg-none .g { font-family: var(--f-display); font-size: 2rem; color: rgba(138,110,47,.4); }
.pg-none p { font-size: var(--fs-small); color: rgba(58,49,34,.7); }
.pg-none .sub { font-size: var(--fs-tiny); color: rgba(58,49,34,.45); }

/* turning leaves */
.leaf {
  grid-area: 1 / 1; position: relative;
  transform-style: preserve-3d; transform-origin: 0% 50%;
  z-index: 4; pointer-events: none;
}
.leaf-face {
  position: absolute; inset: 0; backface-visibility: hidden;
  border-radius: 0 3px 3px 0; overflow: hidden;
}
.leaf-back { transform: rotateY(180deg); background: var(--parchment-2); }
.leaf-cover .leaf-front {
  background: var(--bc-bg, var(--emerald)); color: var(--bc-text, #EFE6D2);
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 12% 12%; container-type: inline-size;
  box-shadow: inset 14px 0 22px -14px rgba(0,0,0,.6);
}
.leaf-cover .leaf-front::after {
  content: ""; position: absolute; inset: 6%;
  border: 1px solid color-mix(in srgb, var(--bc-accent, var(--brass-2)) 55%, transparent);
  outline: 1px solid color-mix(in srgb, var(--bc-accent, var(--brass-2)) 25%, transparent);
  outline-offset: 4px; border-radius: 2px;
}
.lf-vol {
  font-size: 3.6cqw; letter-spacing: .1em; color: var(--bc-accent, var(--brass-2));
  border: 1px solid currentColor; border-radius: 999px; padding: .3em 1.1em;
}
.lf-orn { color: var(--bc-accent, var(--brass-2)); font-size: 6cqw; margin-top: 6%; letter-spacing: .4em; }
.lf-title { font-family: var(--f-display); font-weight: 700; font-size: 8.5cqw; line-height: 1.55; margin: auto 0; }
.lf-author { font-family: var(--f-display); font-size: 4.6cqw; opacity: .82; }
.lf-pub { font-size: 3.4cqw; letter-spacing: .12em; color: var(--bc-accent, var(--brass-2)); margin-top: 5%; }
.leaf-page .leaf-front, .leaf-page .leaf-back { background: var(--parchment); }

/* Cover swings open about the spine (its inner edge), sweeping toward the
   viewer, then fades once it is edge-on so it never masks the left page.
   A thinner leaf follows it for the page-turn beat. */
@keyframes leafOpen {
  0%   { transform: rotateY(0) translateZ(3px); opacity: 1; }
  52%  { opacity: 1; }
  100% { transform: rotateY(-179deg) translateZ(3px); opacity: 0; }
}
@keyframes pgIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.flip.open .leaf-cover { animation: leafOpen .95s cubic-bezier(.5,0,.28,1) both; }
.flip.open .leaf-page  { animation: leafOpen .62s cubic-bezier(.5,0,.28,1) .52s both; }
.flip.open .pg-right .pg-inner { animation: pgIn .5s var(--ease) .46s both; }
.flip.open .pg-left  .pg-inner { animation: pgIn .5s var(--ease) .78s both; }

/* ---------- 23b · READER: bar, nav, turn, ribbon ---------- */
.flip-bar {
  position: absolute; top: 6px; inset-inline: 6px; z-index: 6;
  display: flex; gap: 6px; pointer-events: none;
}
.flip-bar > * { pointer-events: auto; }
.flip-sfx {
  order: 1;
  width: 38px; height: 38px; border-radius: 50%;
  background: rgba(253,251,246,.9); box-shadow: var(--shadow-1);
  font-size: 15px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.flip-sfx:hover { background: var(--white); }

.flip-nav {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
  margin-top: var(--sp-4); flex-wrap: wrap;
}
.flip-arrow {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  border: 1px solid rgba(253,251,246,.3); color: var(--white);
  display: flex; align-items: center; justify-content: center;
  transition: background .2s var(--ease), opacity .2s;
}
.flip-arrow:hover:not(:disabled) { background: rgba(253,251,246,.12); }
.flip-arrow:disabled { opacity: .25; cursor: default; }
.flip-arrow svg { width: 18px; height: 18px; }
.flip-dots { display: flex; gap: 6px; }
.flip-dot {
  padding: 5px 12px; border-radius: 999px; font-size: var(--fs-tiny);
  color: rgba(253,251,246,.6); border: 1px solid transparent;
  transition: color .2s, background .2s, border-color .2s;
}
.flip-dot:hover { color: var(--white); }
.flip-dot.on { color: #2A2113; background: var(--brass-2); border-color: var(--brass-2); font-weight: 600; }

/* Outer third of each page turns it — the way a thumb finds a page edge. */
.pg-edge {
  position: absolute; inset-block: 0; width: 22%; max-width: 90px;
  background: transparent; border: 0; cursor: pointer; z-index: 2;
}
.pg-edge-prev { inset-inline-end: 0; }
.pg-edge-next { inset-inline-start: 0; }
.pg-edge:hover { background: linear-gradient(to var(--edge-dir, left), rgba(58,49,34,.07), transparent); }
.pg-right .pg-edge { --edge-dir: right; }

/* The turning leaf. Forward lifts the LEFT page about the spine and lays it
   on the right; back mirrors it. Both faces carry real page content, so the
   spread never blanks or jumps mid-turn. */
.turn-leaf {
  position: absolute; inset-block: 0; width: 50%;
  transform-style: preserve-3d; z-index: 5; pointer-events: none;
  opacity: 0; visibility: hidden;
}
.turn-leaf.from-left  { inset-inline-start: 0;  transform-origin: 100% 50%; }
.turn-leaf.from-right { inset-inline-start: 50%; transform-origin: 0% 50%; }
.turn-leaf .leaf-face {
  position: absolute; inset: 0; backface-visibility: hidden; overflow: hidden;
  border-radius: 3px;
}
.turn-leaf .pg-face { position: absolute; inset: 0; min-height: 0; border-radius: 0; }
.turn-leaf.from-left  .turn-back { transform: rotateY(180deg); }
.turn-leaf.from-right .turn-back { transform: rotateY(180deg); }
.turn-leaf.turning { opacity: 1; visibility: visible; }
.turn-leaf.from-left.turning  { animation: turnFwd .62s cubic-bezier(.42,0,.3,1) both; }
.turn-leaf.from-right.turning { animation: turnBack .62s cubic-bezier(.42,0,.3,1) both; }
@keyframes turnFwd  { from { transform: rotateY(0); }      to { transform: rotateY(-180deg); } }
@keyframes turnBack { from { transform: rotateY(0); }      to { transform: rotateY(180deg); } }
/* A leaf lifting off catches light on its way over. */
.turn-leaf.turning::after {
  content: ""; position: absolute; inset: 0; z-index: 3; pointer-events: none;
  background: linear-gradient(90deg, rgba(0,0,0,.22), transparent 40%);
  animation: leafShade .62s cubic-bezier(.42,0,.3,1) both;
}
@keyframes leafShade { 0% { opacity: 0; } 45% { opacity: 1; } 100% { opacity: 0; } }

/* Bookmark ribbon. A real one lives INSIDE the book — only the tail shows,
   emerging from the gutter at the foot. Drawing it full height turns it into
   a red bar across the spread, which is not what a ribbon looks like. The
   shading across its width is what sells silk over paper. */
.ribbon {
  position: absolute; top: calc(100% - 24px); inset-inline-start: calc(50% - 8px);
  width: 16px; height: 64px;
  z-index: 4; pointer-events: none;
  background: linear-gradient(90deg, #4E101A 0%, #7E1E2D 26%, #A62B3C 48%, #6E1826 74%, #450E17 100%);
  box-shadow: 0 3px 7px rgba(0,0,0,.38);
  /* notched swallowtail */
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% calc(100% - 13px), 0 100%);
}
/* gilt thread near the tail */
.ribbon i {
  position: absolute; inset-inline: 2px; bottom: 17px; height: 1px;
  background: rgba(212,184,126,.7);
  box-shadow: 0 3px 0 rgba(212,184,126,.4);
}

/* Phones: a two-page spread is unreadable at 390px, so the pages stack
   and the cover flips off the top card only. */
@media (max-width: 719px) {
  .flip-shell { padding: var(--sp-6) var(--sp-3) var(--sp-3); }
  /* the shell scrolls on phones, so pin the controls to the viewport */
  .flip-bar { position: fixed; top: 10px; inset-inline: 10px; }
  .flip-sfx { width: 34px; height: 34px; }
  /* Stacked pages: the leaf would swing off the card, so turns cross-fade
     instead. Same content, same timing, no motion that leaves the page. */
  .turn-leaf { display: none; }
  .flip-book { grid-template-columns: 1fr; grid-template-rows: auto auto; }
  .pg-edge { display: none; }          /* swipe covers this on touch */
  /* Stacked pages have no centre gutter — hang the tail near the fore-edge. */
  .ribbon { inset-inline-start: auto; inset-inline-end: 22px; top: calc(100% - 20px); height: 52px; width: 13px; }
  .flip-nav { margin-top: var(--sp-3); gap: var(--sp-2); }
  .flip-dot { padding: 5px 9px; }
  .flip-arrow { width: 36px; height: 36px; }
  .flip-book::after { display: none; }
  .pg { min-height: 0; }
  .pg-right { grid-area: 1 / 1; border-radius: 3px 3px 0 0; box-shadow: none; }
  .pg-left  { grid-area: 2 / 1; border-radius: 0 0 3px 3px; box-shadow: inset 0 22px 26px -22px rgba(58,49,34,.45); }
  .leaf-face { border-radius: 3px 3px 0 0; }
  .pg-specs { margin-top: var(--sp-3); }
  .pg-setnote { margin-top: var(--sp-4); }
}

/* ---------- 21 · MOTION / UTIL ---------- */
.reveal { opacity: 0; transform: translateY(22px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.reveal.in { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: .08s; } .reveal-d2 { transition-delay: .16s; } .reveal-d3 { transition-delay: .24s; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; }
  /* Killing the animation would strand the leaves in their closed state
     on top of the pages, so retire them outright and show the spread. */
  .leaf { display: none; }
  .flip-scrim, .flip-shell { opacity: 1; transform: none; }
}

/* =========================================================
   ÖN-RENDER BLOKLARI
   ---------------------------------------------------------
   tools/prerender.js'in ürettiği statik içerik. JS yüklenince
   #pdRoot ve #grid kendi çıktısıyla değiştirilir, yani bu
   kurallar yalnızca iki durumda görünür:

     · JS henüz çalışmadan geçen ilk kareler
     · JS'i hiç çalıştırmayan istemciler — ki asıl hedef
       kitle bunlar: GPTBot, ClaudeBot, PerplexityBot

   Gizlemek yerine biçimlendirilmiş: `display:none` verilen bir
   metni Google "kullanıcıya gösterilmeyen içerik" sayar ve
   cloaking'e yakın durur. Burada yazan her şey ziyaretçinin de
   gördüğü şey.
   ========================================================= */
.prerender { padding-block: var(--sp-5); max-width: 78ch; }
.prerender h1 { font-size: clamp(1.4rem, 3.5vw, 2rem); line-height: 1.35; margin: 0 0 var(--sp-2); }
.prerender h2 { font-size: 1.1rem; margin: var(--sp-5) 0 var(--sp-2); }
.pre-latin { color: var(--ink-soft); margin: 0 0 var(--sp-4); }
.pre-cover { max-width: 240px; height: auto; border-radius: 6px; margin-block: var(--sp-4); }

/* Künye. Tarayıcıda iki kolon, dar ekranda tek — ama <dl> yapısı
   korunuyor: terim/tanım ilişkisi bir botun okuduğu şeyin parçası. */
.pre-facts { display: grid; grid-template-columns: auto 1fr; gap: 4px var(--sp-4);
  margin: 0 0 var(--sp-4); font-size: var(--fs-small); }
.pre-facts dt { color: var(--ink-faint); }
.pre-facts dd { margin: 0; color: var(--ink); }

.pre-desc { line-height: 1.8; }
.pre-note { color: var(--ink-faint); font-size: var(--fs-small); margin-top: var(--sp-5); }

.pre-list { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-3); }
.pre-list li { padding-bottom: var(--sp-3); border-bottom: 1px solid var(--line); }
.pre-list a { font-size: 1.02rem; }
.pre-author, .pre-price { display: block; color: var(--ink-faint); font-size: var(--fs-small); }
