@font-face{font-family:'Frank Ruhl Hebrew';font-style:normal;font-weight:500;font-display:swap;src:url(/assets/fonts/frank-ruhl-hebrew.woff2) format('woff2');unicode-range:U+0590-05FF, U+200F, U+FB1D-FB4F}
@font-face{font-family:'Bodoni Moda';font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/bodoni-display.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}
@font-face{font-family:'Archivo';font-style:normal;font-weight:400 700;font-display:swap;src:url(/assets/fonts/archivo.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD}

:root{
  /* --ink-faint was #7d8ba1: 3.23:1 on ivory, which fails WCAG AA for normal
     text and is used for product metadata and counts at ~12px. Darkened within
     the same blue-grey family to 5.17:1 on ivory and 4.83:1 on cream. */
  --ink:#14233b; --ink-soft:#4a5a72; --ink-faint:#5c6982;
  /* --gold-deep was #8f6a1f: 4.32:1 on the cream surface, which fails AA for
     normal text — and the eyebrow that uses it is 11.7px uppercase sitting on
     exactly that surface in the maker section.

     --gold was #b88a2e, and the note that used to sit here said it "only ever
     carries white text on itself" as though that made it safe. That IS the
     failing case: white on #b88a2e is 3.13:1, and .btn--gold is 15.04px — the
     Add to cart button, the hero CTA, the cart badge and the Best seller flag
     all failed 1.4.3 on every page. The same token as a foreground (the word
     "Judaica" in the wordmark, the selected-thumbnail border) was 2.93:1.

     Moved one step down its own lightness ramp — same hue, same family:
       #8f6b24  white on it 4.89:1 · on ivory 4.57:1 · on cream 4.27:1
       #6f5219  (hover) white on it 7.25:1, 1.74x darker so the state still reads
     --coral splits by role. It stays as a border/graphic at 3.65:1 (clears the
     3:1 non-text bar) and gains --coral-ink for TEXT: every validation error on
     the site was 3.41:1 coral-on-ivory at 13px. */
  --gold:#8f6b24; --gold-soft:#f3e6c8; --gold-deep:#6f5219;
  --blue:#2a4cd0; --coral:#e2556e; --coral-ink:#b02a45; --green:#2f7d5b;
  --ivory:#fbf7ef; --cream:#f6efe2; --line:#ece3d3; --white:#fff;
  --shadow-sm:0 4px 14px rgba(20,35,59,.06);
  --shadow-md:0 14px 34px rgba(20,35,59,.10);
  --radius:18px; --radius-lg:28px; --radius-md:14px; --radius-sm:10px;
  --wrap:min(1200px, calc(100% - 40px));
  /* ---- type scale ----------------------------------------------------
     Nine steps, and everything on the storefront uses one of them.

     Before this there were 32 distinct rem font sizes in the stylesheet and
     122 more in inline style attributes across the route files — twenty-two of
     them below 1rem, ten of those inside a 3.5px band. .85 / .86 / .87 / .88rem
     are not four levels of hierarchy; they are noise, and they are the clearest
     fingerprint of a stylesheet assembled decision by decision rather than
     designed. A human picks steps.

     Ratio is roughly 1.08 at the small end where the eye needs the steps to be
     distinguishable but close, opening to 1.25 at the top. The two display
     sizes stay as clamp() because they are the only type on the site that
     should respond to viewport width. */
  --fs-micro:.75rem;    /* 12px  flags, counts, the cart badge   */
  --fs-meta:.8125rem;   /* 13px  captions, hints, footer legal   */
  --fs-ui:.875rem;      /* 14px  nav, chips, table cells, meta   */
  --fs-ctl:.9375rem;    /* 15px  buttons, summaries, form labels */
  --fs-body:1rem;       /* 16px  body copy                       */
  --fs-lede:1.125rem;   /* 18px  hero sub, section intro, story  */
  --fs-h3:1.3125rem;    /* 21px                                  */
  --fs-h2:1.4375rem;    /* 23px  the PDP price                   */
  /* Didone display over neutral grotesque — the pairing every jewellery shop
     worth copying uses. See the note in src/assets/fonts.ts for why, and for
     which shops. Didot is the fallback because it is the one high-contrast
     serif that ships on macOS; Georgia would land somewhere else entirely. */
  --serif:"Bodoni Moda",Didot,"Bodoni MT",Georgia,serif;
  --sans:"Archivo",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  --focus:#2a4cd0;
}
/* Light only, deliberately. Every product photograph carries its own light
   background; inverted, the grid becomes 56 glowing rectangles on black and the
   gold goes muddy. Declaring it stops form controls, scrollbars and the address
   bar from guessing. This is a decision, not an omission — do not "add dark
   mode" without re-shooting the catalogue. */
:root{color-scheme:light}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;font-family:var(--sans);color:var(--ink);background:var(--ivory);line-height:1.6;font-size:var(--fs-body);-webkit-font-smoothing:antialiased}
/* A Didone is not a heavier version of a text serif and must not be set like
   one. Three things change from how Fraunces was set here:

   WEIGHT. Fraunces was set at 600 because it needed the mass. Bodoni's whole
   character is the contrast between hairline and stem, and adding weight fills
   the hairlines in and destroys it. Display sizes take 400; the smaller
   headings take 500 because at 21px the hairlines start to disappear on a
   low-DPI screen and need the stem back.

   RANGE. Fraunces ran h1 through h4. Bodoni stops after h2 — below that, and
   for every product title, the grotesque is the right voice. This is exactly
   how the reference set behaves: Missoma and Catbird set a display serif for
   headlines and Helvetica for absolutely everything else. A Didone used down
   to 16px is a Didone nobody notices.

   TRACKING. Unchanged in principle and retuned in value: a high-contrast serif
   at 48px wants to be tighter than the same face at 21px, and tracking in em
   is proportional to size, so one value cannot serve both. */
h1,h2{font-family:var(--serif);font-weight:400;margin:0 0 .5em;text-wrap:balance;
  font-variant-numeric:lining-nums;font-optical-sizing:auto}
h3,h4{font-family:var(--sans);font-weight:600;margin:0 0 .5em;text-wrap:balance}
/* Tracking in "em" is proportional to font-size, so a single value is the SAME
   optical tracking at 32px and at 48px — which is precisely the thing the note
   above says it is correcting. -.017em was measurably too tight on a 390px
   screen (the "tt" in "Shabbat Charm Earrings" closed up) and not tight enough
   at 48px. It is now a small-screen value with a desktop override. */
/* Bigger than before, because a display serif earns its size: at 3rem Bodoni
   read as a slightly odd body face. The clamp ceiling goes to 3.9rem and the
   line-height tightens to match — display type at 1.08 leading looked airy
   once the letterforms stopped being slabs. */
h1{font-size:clamp(2.35rem,5vw,3.9rem);line-height:1.02;letter-spacing:-.012em}
h2{font-size:clamp(1.6rem,3.2vw,2.4rem);line-height:1.1;letter-spacing:-.008em}
@media(min-width:900px){
  h1{letter-spacing:-.02em}
  h2{letter-spacing:-.014em}
}
/* h2 at the small end of its clamp is where Bodoni's hairlines get thin, so it
   takes 500 on narrow screens and drops back to 400 once it is big enough. */
@media(max-width:640px){ h2{font-weight:500} }
h3{font-size:var(--fs-h3);line-height:1.32;letter-spacing:-.004em}
h4{font-size:var(--fs-body);line-height:1.35;letter-spacing:-.002em}
p{margin:0 0 1rem;text-wrap:pretty}
a{color:inherit;text-decoration:none}
/* Prose links are underlined; controls are not.
   This was a deny-list — :not(.btn):not(.pcard__link):not(.chip)… — and a
   deny-list has to be told about every component ever added. It had not been
   told about .giftcard, so the gift finder rendered as twenty-one underlined
   lines of gold text in one viewport and read as an unstyled fallback, on the
   highest-intent page in the shop. An allow-list cannot fail that way: a new
   component is un-underlined until someone decides otherwise.
   text-decoration-thickness because the default rule under Fraunces at 16px is
   heavier than the stems it sits below. */
.prose a,.rte a,.acc__body a,.crumbs a,.motif-body a,main p:not([class]) a{
  text-decoration:underline;text-underline-offset:3px;
  text-decoration-thickness:.06em;text-decoration-color:var(--gold)}
img,svg{max-width:100%;height:auto;display:block}
.wrap{width:var(--wrap);margin-inline:auto}
/* One left rail, page-wide.
   Four pages set "style="max-width:760px"" (or 700/600) on .wrap itself, which
   re-centres a narrower column inside the 1200px one. The result was three
   different left edges stacked in a single view: header at 8% of the viewport,
   prose at 24%, and the product row directly beneath the prose back at 8%. Two
   hard vertical edges 220px apart in the same colour field is the first thing
   a trained eye sees. The reading column now starts on the same rail as the
   logo and the footer and simply stops earlier. */
.prose{max-width:66ch}
.prose>h1,.prose>h2,.prose>.section-head{max-width:24ch}
/* Prose wants a measure. 95 characters a line — which is what /about was
   running at 1440px — is roughly double a comfortable return sweep, on the one
   page where a shopper decides whether Leia is a real person. */
.rte p,.rte li,.pdp__story{max-width:64ch}
.section{padding:clamp(40px,6vw,78px) 0}
.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* Focus is never removed — only restyled.
   Two-tone deliberately. outline-offset:2px puts the ring on the PARENT's
   background, and this site has two dark ones: the navy footer and the whole of
   admin. --focus on --ink is 2.28:1, i.e. an invisible focus indicator on ~14
   footer links and every admin nav control (SC 1.4.11 / 2.4.11). The white
   inner ring is 15.75:1 there, and on ivory the blue outer ring carries it at
   6.46:1 — so whichever surface it lands on, one of the two rings is visible. */
:focus-visible{outline:3px solid var(--focus);outline-offset:2px;
  box-shadow:0 0 0 2px #fff;border-radius:4px}
.skip-link{position:absolute;left:-9999px;top:0;background:var(--ink);color:#fff;padding:12px 18px;z-index:200}
.skip-link:focus{left:8px;top:8px}

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
  font-family:var(--sans);font-weight:600;font-size:var(--fs-ctl);letter-spacing:.005em;padding:13px 26px;border-radius:999px;
  border:1.5px solid transparent;cursor:pointer;transition:transform .15s,box-shadow .15s,background .15s;
  min-height:46px;text-align:center}
.btn:active{transform:translateY(1px)}
.btn--primary{background:var(--ink);color:#fff}
.btn--primary:hover{background:#1d3252;box-shadow:var(--shadow-md)}
.btn--gold{background:var(--gold);color:#fff}
.btn--gold:hover{background:var(--gold-deep);box-shadow:var(--shadow-md)}
.btn--ghost{background:transparent;color:var(--ink);border-color:var(--ink)}
.btn--ghost:hover{background:var(--ink);color:#fff}
.btn--sm{padding:9px 16px;font-size:var(--fs-ui);min-height:40px}
.btn--block{width:100%}
.btn[disabled],.btn[aria-disabled="true"]{opacity:.5;cursor:not-allowed}

/* ---------- announcement + header ---------- */
.announce{background:var(--ink);color:#fbf7ef;text-align:center;font-size:var(--fs-micro);font-weight:400;
  padding:10px 16px;letter-spacing:.12em;text-transform:uppercase;margin:0}
/* The sticky header scrolls a newly focused element under itself when tabbing
   backwards — a 46px input or a 17px footer link ends up entirely hidden,
   which is WCAG 2.2 SC 2.4.11 Focus Not Obscured (Minimum), not just Enhanced. */
html{scroll-padding-top:80px}
#main{scroll-margin-top:80px}
#main:focus{outline:none}
.hdr{position:sticky;top:0;z-index:60;background:rgba(251,247,239,.93);backdrop-filter:blur(10px);border-bottom:1px solid var(--line)}
.hdr__in{display:flex;align-items:center;gap:18px;min-height:64px}
/* inline-BLOCK, not inline-flex. Flex made the whitespace between "Leia’s"
   and its <span>Judaica</span> an anonymous flex item, which collapses — the
   wordmark rendered as "Leia’sJudaica". Padding reaches the 44px target
   without changing the formatting context. */
/* Weight 700 made the wordmark a slab. A Didone wordmark is set light and
   slightly open — the contrast does the work, not the mass. */
.hdr__logo{font-family:var(--serif);font-size:1.5rem;font-weight:500;letter-spacing:-.004em;font-optical-sizing:auto;
  white-space:nowrap;display:inline-block;line-height:1.15;padding-block:11px}
.hdr__logo span{color:var(--gold)}
/* A fourth control (Saved) joined the header and pushed it 5px past a 390px
   viewport — caught by qa:matrix as a horizontal overflow on every page.
   The icon buttons cannot give way: 44px is the touch-target floor the
   accessibility invariant sets. So the wordmark does. It is still the largest
   thing in the header at this size, and 5px of overflow makes the whole page
   scroll sideways, which is a far worse trade. */
@media (max-width:430px){ .hdr__logo{font-size:1.22rem} }
.hdr__nav{display:flex;gap:22px;margin-left:auto;align-items:center}
/* Small, light and wide-tracked. Nav at 15px/500 with no tracking is the
   default every admin panel ships; the shops in the reference set all set
   theirs a step smaller and let the spacing carry it. */
.hdr__nav a{font-size:var(--fs-ui);font-weight:400;letter-spacing:.04em;padding:8px 2px;border-bottom:2px solid transparent}
.hdr__nav a:hover,.hdr__nav a[aria-current="page"]{border-bottom-color:var(--gold)}
.hdr__tools{display:flex;gap:6px;align-items:center;margin-left:auto}
.hdr__nav+.hdr__tools{margin-left:10px}
/* Below ~380px there is not room for a wordmark plus four 44px targets at any
   comfortable spacing, so the spacing goes.
   This block lives AFTER .hdr__tools deliberately: the first attempt sat
   beside .hdr__logo higher up the sheet, lost to the base rule on source
   order, and silently did nothing — the gap stayed 6px and 320px still
   overflowed. Same specificity means later wins, so it has to be here. */
@media (max-width:380px){
  .hdr__logo{font-size:1.02rem}
  .hdr__tools{gap:0}
  .hdr__nav+.hdr__tools{margin-left:4px}
  /* The last 3px at 320px. 20px of gutter each side is generous on a screen
     that narrow, and 12px still keeps text off the bezel. */
  :root{--wrap:min(1200px, calc(100% - 24px))}
}
.iconbtn{font-size:var(--fs-ui);display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border:0;background:transparent;border-radius:50%;cursor:pointer;color:var(--ink);position:relative}
.iconbtn:hover{background:var(--cream)}
.cartcount{position:absolute;top:4px;right:2px;background:var(--gold);color:#fff;font-size:var(--fs-micro);font-weight:700;
  min-width:18px;height:18px;border-radius:9px;display:grid;place-items:center;padding:0 4px;font-family:var(--sans)}
.navtoggle{display:none}
@media(max-width:900px){
  .hdr__nav{display:none;position:absolute;top:100%;left:0;right:0;background:var(--ivory);
    flex-direction:column;align-items:stretch;gap:0;padding:8px 20px 20px;border-bottom:1px solid var(--line);box-shadow:var(--shadow-md);
    /* The rendered menu is 23 links, and the mobile rule below forces every
       submenu open at once — roughly 1,050px of panel against 780px of space
       under a sticky 64px header. The last several links, "Our Story" among
       them, could not be reached by scrolling, because the panel is anchored
       to a bar that does not move. */
    max-height:calc(100dvh - 64px);overflow-y:auto;overscroll-behavior:contain}
  .hdr__nav[data-open="true"]{display:flex}
  .hdr__nav a{padding:14px 4px;border-bottom:1px solid var(--line)}
  .navtoggle{display:inline-flex}
  .hdr__tools{margin-left:auto}
}

/* ---------- nav submenus ----------
   Shown on hover for pointers and on focus-within for keyboards, and on small
   screens the panel is simply always open inside the drawer. No interaction
   depends on a pointer hovering, because on a phone nothing ever does. */
.hdr__item{position:relative;display:flex;align-items:center}
.submenu{display:none;position:absolute;top:100%;left:50%;transform:translateX(-50%);padding-top:10px;z-index:70}
.hdr__item:hover>.submenu,.hdr__item:focus-within>.submenu{display:block}
.submenu__in{background:var(--ivory);border:1px solid var(--line);border-radius:var(--radius-md);
  box-shadow:var(--shadow-md);padding:10px;display:grid;grid-template-columns:1fr 1fr;gap:2px;min-width:340px}
.submenu__in a{display:flex;justify-content:space-between;gap:12px;padding:9px 12px;border-radius:8px;
  font-size:var(--fs-ui);border-bottom:0;white-space:nowrap;min-height:40px;align-items:center}
.submenu__in a:hover{background:var(--cream)}
.submenu__in a span{color:var(--ink-faint);font-size:var(--fs-meta)}
.submenu__all{grid-column:1/-1;font-weight:600;color:var(--gold-deep)}
@media(max-width:900px){
  .hdr__item{display:block}
  .submenu{display:block;position:static;transform:none;padding-top:0}
  .submenu__in{border:0;box-shadow:none;background:transparent;padding:0 0 8px 14px;
    grid-template-columns:1fr;min-width:0}
  .submenu__in a{padding:11px 4px;border-bottom:1px solid var(--line)}
}

/* ---------- hero ---------- */
.hero{background:linear-gradient(180deg,var(--cream),var(--ivory));border-bottom:1px solid var(--line);overflow:hidden}
.hero__in{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(24px,5vw,64px);align-items:center;padding:clamp(36px,6vw,76px) 0}
/* contain, not cover.
 *
 * cover cropped the hero photograph to a square and cut the ear wire off the
 * top of the frame. Which photograph appears here is now the owner's choice,
 * so it has to be a treatment that cannot amputate ANY product — a hero that
 * beheads one earring in three is not a hero. The piece sits whole on a warm
 * panel, letterboxed where the source is not square, which reads as a
 * deliberate presentation rather than a bad crop. */
/* No forced square.
 *
 * cover cropped the ear wire off the top. contain fixed the crop but, because
 * every product photograph already carries its own background, it produced a
 * picture inside a frame inside a frame — letterbox, then the photo's own
 * stone backdrop, then the page. Letting the image keep its natural shape
 * avoids both: nothing is cropped and there is only one rectangle. The
 * width/height attributes still reserve the space, so nothing shifts on load. */
/* Every product photograph is 3:4, 4:3 or something odd — none is square. The
   width/height attributes on the <img> say 1:1, so the browser reserved a
   square, then replaced it with the natural ratio on decode: a 65-119px
   downward shift of the H1, the subtitle and BOTH CTA buttons, at exactly the
   moment a thumb is arriving at them. On mobile the art sits ABOVE the
   headline, so everything moves. */
.hero__art img{aspect-ratio:1;object-fit:cover;border-radius:var(--radius-lg);width:100%;height:100%;
  box-shadow:0 14px 36px rgba(20,35,59,.12)}
.hero p.hero__sub{font-size:clamp(var(--fs-body),1.6vw,var(--fs-lede));color:var(--ink-soft);max-width:52ch}
.hero__cta{display:flex;gap:12px;flex-wrap:wrap;margin:22px 0 20px}
.hero__trust{display:flex;gap:18px;flex-wrap:wrap;font-size:var(--fs-ui);color:var(--ink-soft);font-weight:500}
.hero__trust span{display:inline-flex;align-items:center;gap:6px}
@media(max-width:840px){.hero__in{grid-template-columns:1fr;gap:26px}.hero__art{order:-1}}

/* A section marker, not a heading. It was 700 weight at .14em tracking, which
   is the letterspaced-bold-caps look that reads as amateur however good the
   face is. Semibold and roughly half the tracking still separates it from body
   copy without shouting. */
.eyebrow{display:inline-block;font-weight:500;font-size:var(--fs-micro);letter-spacing:.14em;
  text-transform:uppercase;color:var(--gold-deep);margin-bottom:.65rem;line-height:1.4}
.section-head{margin-bottom:clamp(20px,3vw,34px);max-width:62ch}
/* A reading measure. On a 1440px screen an intro paragraph was running the
   full container width — around 150 characters a line, roughly twice what the
   eye tracks comfortably. */
.section-head p{color:var(--ink-soft);margin:0;max-width:58ch;font-size:var(--fs-body);line-height:1.6}

/* ---------- Hebrew ----------
   The names of the symbols and holidays, in Hebrew, beside the English.

   Strip the photographs off this site and nothing about it is specifically
   Jewish — cream, navy, one gold accent, a serif and a sans, a square product
   grid. It could be a candle shop. This is the one piece of specificity
   available that invents nothing: מגן דוד IS what a Star of David is called,
   and the shop already names it in English two lines up.

   Set slightly larger than the Latin beside it because Hebrew has no
   ascenders or descenders to speak of, so at matched point size it reads
   noticeably smaller than Fraunces. The gold is the deep, accessible one. */
.hebrew{font-family:"Frank Ruhl Hebrew",serif;font-weight:500;
  /* direction:rtl orders the characters correctly; unicode-bidi:isolate stops
     the Hebrew reordering the Latin around it. text-align stays with the page,
     because in a stacked label the Hebrew and the English should share a left
     edge — RTL block alignment stranded it at the far side of the tile with a
     gap between the two names of the same thing. */
  direction:rtl;unicode-bidi:isolate;text-align:left;
  color:var(--gold-deep);letter-spacing:0;line-height:1.5}
.collection-hebrew{display:block;font-size:1.35em;margin:0 0 .1em}
.tile-hebrew{display:block;font-size:1.15em;margin-top:2px;opacity:.92}

/* ---------- product grid + cards ---------- */
.pgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:clamp(14px,2.2vw,26px)}
@media(max-width:560px){.pgrid{grid-template-columns:repeat(2,1fr);gap:12px}}
/* The photograph IS the card.
 *
 * These used to be white boxes with a border and a shadow, sitting on an ivory
 * page. Forty-odd of them in a grid read as a dashboard, and the white panel
 * under each one put a hard edge between the earrings and the page. Dropping
 * the container leaves the product photograph as the only object on the
 * surface, which is what a shop window does — the merchandise sits on the
 * material, it is not mounted in a frame.
 *
 * The image keeps its own radius and a very soft shadow, so it still reads as
 * a physical thing lying on the page rather than as a hole cut into it. */
.pcard{position:relative;display:flex;flex-direction:column;background:transparent;border:0}
.pcard__link{display:flex;flex-direction:column;flex:1}
/* Fixed ratio + explicit dimensions: the grid never shifts as images load. */
.pcard__media{position:relative;aspect-ratio:1;overflow:hidden;border-radius:var(--radius-md);
  background:linear-gradient(165deg,var(--cream),#fdfaf4 72%);
  box-shadow:0 2px 10px rgba(20,35,59,.05);transition:box-shadow .18s,transform .18s}
.pcard:hover .pcard__media,.pcard:focus-within .pcard__media{
  box-shadow:0 12px 30px rgba(20,35,59,.13);transform:translateY(-3px)}
.pcard__media img{width:100%;height:100%;object-fit:cover;transition:transform .4s}
.pcard:hover .pcard__media img.pcard__primary{transform:scale(1.04)}
.pcard__alt{position:absolute;inset:0;opacity:0;transition:opacity .3s}
.pcard:hover .pcard__alt,.pcard:focus-within .pcard__alt{opacity:1}
/* Text sits on the page itself, not on a second surface. */
.pcard__body{padding:12px 2px 0;display:flex;flex-direction:column;gap:4px;flex:1}
.pcard__title{font-family:var(--sans);font-size:var(--fs-ctl);font-weight:500;line-height:1.4;margin:0;color:var(--ink);
  /* Two lines maximum keeps every row of the grid the same height; a long
     name that wrapped to three used to shove its neighbour's price down. */
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* One price treatment everywhere. 700 made every price shout across a grid of
   forty; 600 is still unmistakably the price without competing with the
   photograph above it. */
.pcard__price{font-size:var(--fs-ctl);font-weight:600;color:var(--ink);margin-top:auto;font-variant-numeric:tabular-nums}
.pcard__price s{color:var(--ink-faint);font-weight:500;margin-right:6px}
.pcard__ctx{font-size:var(--fs-micro);color:var(--ink-faint)}
/* Clamped, so a long sentence cannot push one card's price out of line with
   its neighbour's — the grid only stays a grid if every row is the same
   height. Three lines rather than two: at 390px in two columns a card is ~168px
   wide, and two lines cut most of these sentences off mid-word. On a desktop
   card (~260px) three lines fits the whole thing. */
.pcard__sub{font-size:var(--fs-meta);line-height:1.42;color:var(--ink-soft);margin:0;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;
  text-wrap:pretty}
.flag{position:absolute;top:10px;left:10px;background:var(--white);color:var(--ink);font-size:var(--fs-micro);font-weight:600;
  letter-spacing:.045em;text-transform:uppercase;padding:5px 11px;border-radius:999px;box-shadow:var(--shadow-sm)}
.flag--sold{background:var(--ink);color:#fff}
.flag--new{background:var(--green);color:#fff}
.flag--best{background:var(--gold);color:#fff}
.flag--limited{background:var(--coral-ink);color:#fff}
/* The quick-add form is a SIBLING of the card link — a <form> cannot live
 * inside an <a> — so it has no natural relationship to the image. It used to
 * be clipped by overflow:hidden on the card itself; once the card stopped
 * being a box, the bar had nothing to hide it and appeared stranded below the
 * price. This wrapper reproduces the image's square box exactly, so the button
 * slides up from the bottom edge of the photograph and is clipped by it. */
.pcard__quickwrap{position:absolute;top:0;left:0;right:0;aspect-ratio:1;overflow:hidden;
  border-radius:var(--radius-md);display:flex;align-items:flex-end;pointer-events:none}
.pcard__quick{width:100%;background:var(--ink);color:#fff;border:0;pointer-events:auto;
  padding:11px;font-size:var(--fs-ui);font-weight:600;cursor:pointer;transform:translateY(100%);transition:transform .2s;
  font-family:var(--sans);min-height:44px}
.pcard:hover .pcard__quick,.pcard:focus-within .pcard__quick{transform:translateY(0)}
/* No hover on touch: show it permanently, in normal flow under the image,
   rather than covering the bottom of the product the shopper is looking at. */
@media(hover:none){
  .pcard__quickwrap{position:static;aspect-ratio:auto;overflow:visible;margin-top:10px}
  .pcard__quick{transform:none;border-radius:999px;min-height:44px}
}

/* ---------- theme tiles ---------- */
.tiles{display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:14px}
.tile{position:relative;aspect-ratio:1;border-radius:var(--radius);overflow:hidden;background:var(--cream);border:1px solid var(--line)}
.tile img{width:100%;height:100%;object-fit:cover;transition:transform .4s}
.tile:hover img{transform:scale(1.05)}
/* Product photography has wildly varying backgrounds (grey fabric, marble,
   black, blue), so a light scrim left labels unreadable on some tiles. This
   ramp stays legible over any of them. */
.tile__label{position:absolute;inset:auto 0 0 0;padding:38px 14px 13px;color:#fff;font-weight:600;font-size:var(--fs-ctl);
  text-shadow:0 1px 3px rgba(0,0,0,.55);
  background:linear-gradient(180deg,transparent,rgba(12,22,38,.55) 42%,rgba(12,22,38,.9))}
.tile__count{display:block;font-size:var(--fs-micro);font-weight:500;opacity:.85}

/* ---------- value props ---------- */
.vprops{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:18px}
.vprop{background:var(--white);border:1px solid var(--line);border-radius:var(--radius);padding:24px}
.vprop h3{font-family:var(--sans);font-size:var(--fs-body);margin-bottom:.35rem}
.vprop p{margin:0;color:var(--ink-soft);font-size:var(--fs-ui)}

/* ---------- PDP ---------- */
.pdp{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(24px,4vw,56px);padding:clamp(24px,4vw,48px) 0;align-items:start}
/* The buy column is far taller than one square photo. Without this the image
   scrolls away and leaves a large void beside the copy. */
@media(min-width:861px){.pdp__media{position:sticky;top:88px}}
@media(max-width:860px){.pdp{grid-template-columns:1fr;gap:24px}}
/* 53 of 55 products have exactly one photo. Rather than leaving a lonely
   square, the single image gets a framed, inset presentation that reads as a
   deliberate composition. */
.gallery__main{border-radius:var(--radius-lg);overflow:hidden;aspect-ratio:1;
  background:linear-gradient(160deg,var(--cream),#fff 70%);
  border:1px solid var(--line);box-shadow:var(--shadow-sm);
  display:grid;place-items:center;padding:clamp(10px,2.4vw,26px)}
/* contain, not cover.
   Sources are 3:4 (47 of 58) and the frame is square, so "cover" discarded 25%
   of the height — top and bottom — of the photograph on the page where a
   shopper is judging how long a dangle is. With no published measurements
   anywhere (length_mm is 0 of 56), that crop removed the only length cue that
   exists. The box already has a cream gradient and generous padding, so
   letterboxing onto it reads as a presentation rather than as a mistake. */
.gallery__main img{border-radius:var(--radius);object-fit:contain;width:100%;height:100%}
.gallery--single .gallery__main{padding:clamp(16px,3.4vw,38px)}
.gallery__thumbs{display:flex;gap:10px;margin-top:12px;flex-wrap:wrap}
.gallery__thumbs img{width:100%;height:100%;object-fit:cover}
.gallery__thumbs button{width:70px;height:70px;border-radius:var(--radius-sm);overflow:hidden;border:2px solid var(--line);background:var(--cream);padding:0;cursor:pointer}
.gallery__thumbs button[aria-current="true"]{border-color:var(--gold)}
/* The one price on the site that is display type rather than data. Set in
   the serif with lining figures, the way a jeweller writes it. Every OTHER
   price — cards, cart lines, order tables — stays in the grotesque with
   tabular figures, because those are columns that have to align. */
.pdp__price{font-family:var(--serif);font-size:1.85rem;font-weight:400;font-optical-sizing:auto;margin:.35rem 0 1.1rem;font-variant-numeric:lining-nums;letter-spacing:-.008em;line-height:1.2}
.pdp__price s{font-size:.68em;letter-spacing:0}
.pdp__story{color:var(--ink-soft);font-size:var(--fs-body)}
.qtyrow{display:flex;gap:12px;align-items:center;margin:20px 0}
.qty{display:inline-flex;align-items:center;border:1.5px solid var(--line);border-radius:999px;background:var(--white);overflow:hidden}
.qty button{width:44px;height:46px;border:0;background:transparent;font-size:var(--fs-lede);cursor:pointer;color:var(--ink)}
.qty button:hover{background:var(--cream)}
.qty input{width:48px;height:46px;border:0;text-align:center;font-family:var(--sans);font-size:var(--fs-body);font-weight:600;background:transparent;color:var(--ink);-moz-appearance:textfield}
.qty input::-webkit-outer-spin-button,.qty input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.trustrow{display:flex;flex-wrap:wrap;gap:14px;font-size:var(--fs-ui);color:var(--ink-soft);margin:18px 0;padding:14px 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.acc{border-bottom:1px solid var(--line)}
.acc summary{cursor:pointer;padding:15px 0;font-weight:600;font-size:var(--fs-ctl);list-style:none;display:flex;justify-content:space-between;align-items:center;min-height:44px}
.acc summary::-webkit-details-marker{display:none}
.acc summary::after{content:"+";font-size:var(--fs-h3);color:var(--gold);font-weight:400}
.acc[open] summary::after{content:"−"}
.acc__body{padding:0 0 16px;color:var(--ink-soft);font-size:var(--fs-ctl)}
/* Spec list, converted from the recovered Shopify feature tables. */
.rte dl{display:grid;grid-template-columns:minmax(88px,26%) 1fr;gap:0;margin:18px 0;
  border-top:1px solid var(--line);font-size:var(--fs-ctl)}
.rte dt{font-weight:600;padding:9px 12px 9px 0;border-bottom:1px solid var(--line);color:var(--ink)}
.rte dd{margin:0;padding:9px 0;border-bottom:1px solid var(--line);color:var(--ink-soft)}
@media(max-width:520px){
  .rte dl{grid-template-columns:1fr}
  .rte dt{padding-bottom:0;border-bottom:0}
  .rte dd{padding-top:2px}
}
/* Headings inside product copy are subordinate to the product title, not
   competing display type. */
.rte h2{font-family:var(--sans);font-size:var(--fs-body);font-weight:700;letter-spacing:.01em;
  margin:22px 0 .4rem;color:var(--ink)}
.rte h3{font-family:var(--sans);font-size:var(--fs-ctl);font-weight:700;margin:18px 0 .3rem}
.rte p{color:var(--ink-soft)}
.rte ul{color:var(--ink-soft);padding-left:20px;margin:0 0 1rem}
.rte li{margin-bottom:4px}
.rte>*:first-child{margin-top:0}

.meaning{background:var(--cream);border:1px solid var(--line);border-left:4px solid var(--gold);border-radius:var(--radius-sm);padding:20px 22px;margin:22px 0}
.meaning h2{font-size:var(--fs-lede);margin-bottom:.4rem}
.meaning p{margin:0;color:var(--ink-soft);font-size:var(--fs-ctl)}

/* ---------- cart ---------- */
/* THE reason the cart "popped up" instead of opening.
   visibility flipped hidden -> visible in the same frame the panel's transform
   changed. A browser will not animate a transition on an element that was not
   being rendered a moment ago, so the slide was skipped every single time and
   the panel simply appeared. Delaying visibility only on CLOSE lets it become
   visible first on open, so the transform has something to animate — and keeps
   the panel on screen long enough to slide out again. */
.drawer{position:fixed;inset:0;z-index:100;visibility:hidden;
  transition:visibility 0s linear .28s}
.drawer[data-open="true"]{visibility:visible;transition-delay:0s}
.drawer__scrim{position:absolute;inset:0;background:rgba(20,35,59,.45);opacity:0;transition:opacity .25s}
.drawer[data-open="true"] .drawer__scrim{opacity:1}
/* A sliver of the page stays visible behind it. At 390px "min(420px,100%)"
   was the whole screen, so the cart read as a page replacement rather than a
   panel over the shop — no sense of where you were or how to get back. */
.drawer__panel{position:absolute;top:0;right:0;bottom:0;width:min(420px,92%);background:var(--ivory);
  display:flex;flex-direction:column;transform:translateX(100%);transition:transform .28s;box-shadow:var(--shadow-md)}
.drawer[data-open="true"] .drawer__panel{transform:none}
.drawer__head{display:flex;align-items:center;justify-content:space-between;padding:16px 18px;border-bottom:1px solid var(--line)}
.drawer__head h2{margin:0;font-size:var(--fs-lede)}
.drawer__body{flex:1;overflow-y:auto;padding:16px 18px}
.drawer__foot{border-top:1px solid var(--line);padding:16px 18px;background:var(--white)}
.citem{display:grid;grid-template-columns:70px 1fr auto;gap:12px;padding:12px 0;border-bottom:1px solid var(--line)}
.citem__img{width:70px;height:70px;border-radius:var(--radius-sm);object-fit:cover;background:var(--cream)}
.citem__title{font-size:var(--fs-ui);font-weight:600;margin:0 0 2px}
.citem__meta{font-size:var(--fs-meta);color:var(--ink-faint)}
.citem__price{font-weight:600;font-size:var(--fs-ui);white-space:nowrap;font-variant-numeric:tabular-nums}
.linkbtn{background:none;border:0;padding:4px 0;color:var(--ink-faint);font-size:var(--fs-meta);cursor:pointer;text-decoration:underline;font-family:var(--sans);min-height:32px}
.linkbtn:hover{color:var(--coral-ink)}
.shipbar{margin:10px 0 14px}
.shipbar__track{height:7px;background:var(--line);border-radius:99px;overflow:hidden}
.shipbar__fill{height:100%;background:var(--gold);border-radius:99px;transition:width .4s}
.shipbar__label{font-size:var(--fs-meta);color:var(--ink-soft);margin-bottom:6px;display:block}
/* The cart totals are the only place on the site where numbers are stacked in
   a right-aligned column, and they were the only price treatment WITHOUT
   tabular figures — so $18.00 and $27.00 did not line up on the decimal in the
   one table where alignment is the entire point. Inter's subset carries tnum,
   so this is free. */
.totals{width:100%;font-size:var(--fs-ctl);font-variant-numeric:tabular-nums}
.totals td{padding:3px 0}
.totals td:last-child{text-align:right;font-weight:600}
.totals tr.grand td{font-size:var(--fs-lede);font-weight:600;padding-top:9px;border-top:1px solid var(--line)}

/* ---------- forms ---------- */
.field{margin-bottom:14px}
.field label{display:block;font-size:var(--fs-ui);font-weight:600;margin-bottom:5px}
.field input,.field select,.field textarea{width:100%;padding:12px 14px;border:1.5px solid var(--line);border-radius:var(--radius-sm);
  font-family:var(--sans);font-size:var(--fs-body);background:var(--white);color:var(--ink);min-height:46px}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--focus);outline:2px solid var(--focus);outline-offset:0}
.field input[aria-invalid="true"]{border-color:var(--coral)}
.field__err{color:var(--coral-ink);font-size:var(--fs-meta);margin-top:4px;display:block;font-weight:500}
.field__hint{color:var(--ink-faint);font-size:var(--fs-meta);margin-top:4px;display:block}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
@media(max-width:560px){.grid2{grid-template-columns:1fr}}

.notice{border-radius:var(--radius-sm);padding:13px 16px;font-size:var(--fs-ui);margin:0 0 16px;border:1px solid}
.notice--warn{background:#fdf6e3;border-color:#e8d9a8;color:#6b5514}
.notice--err{background:#fdeff1;border-color:#f3c6ce;color:#8f2337}
.notice--ok{background:#eef7f2;border-color:#c3e2d2;color:#1f5c42}
.notice--info{background:var(--cream);border-color:var(--line);color:var(--ink-soft)}

/* Cart line actions sit on one row so "Remove" and "Save for later" read as a
   pair of choices rather than two stacked afterthoughts. */
.citem__actions{display:flex;gap:14px;align-items:center;flex-wrap:wrap;margin-top:2px}
.citem__actions form{margin:0}

/* ---- save for later ---------------------------------------------------
   The filled state is a fill AND a colour change, never colour alone: whether
   something is on your shortlist has to survive being colour-blind. */
.save{position:absolute;top:10px;right:10px;z-index:2;display:grid;place-items:center;
  width:36px;height:36px;border:0;border-radius:50%;cursor:pointer;color:var(--ink-soft);
  background:rgba(255,255,255,.92);box-shadow:0 1px 5px rgba(20,35,59,.15);
  transition:color .14s ease,transform .14s ease}
.save[hidden]{display:none}
.save:hover{color:var(--gold-deep);transform:scale(1.06)}
.save:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
.save[aria-pressed="true"]{color:#b3123c}
.save[aria-pressed="true"] svg{fill:currentColor}
/* The PDP control is a labelled button in the flow, not a floating heart —
   at that size and position an unlabelled icon reads as decoration. */
.savebtn{position:static;width:auto;height:auto;display:inline-flex;align-items:center;gap:8px;
  margin-top:10px;border-radius:999px;box-shadow:none;background:transparent}
.savebtn[aria-pressed="true"]{color:#b3123c;border-color:currentColor}
.savebtn[aria-pressed="true"] svg{fill:currentColor}
@media (prefers-reduced-motion:reduce){ .save{transition:none} .save:hover{transform:none} }

/* ---- sticky buy bar ---------------------------------------------------
   Mobile and narrow tablet only. On a wide screen the buy column is beside
   the photograph and stays in view on its own; a fixed bar there would be
   covering content to solve a problem that does not exist. */
.buybar{position:fixed;left:0;right:0;bottom:0;z-index:70;background:rgba(255,255,255,.97);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
  border-top:1px solid var(--line);box-shadow:0 -6px 24px rgba(20,35,59,.10);
  padding-bottom:env(safe-area-inset-bottom)}
.buybar[hidden]{display:none}
.buybar__in{display:flex;align-items:center;gap:12px;padding:10px 16px;max-width:var(--wrap,1180px);margin:0 auto}
.buybar__in img{width:44px;height:44px;border-radius:8px;object-fit:cover;flex:0 0 auto;background:var(--cream)}
.buybar__text{display:flex;flex-direction:column;min-width:0;flex:1}
.buybar__name{font-size:var(--fs-ui);font-weight:500;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.buybar__price{font-size:var(--fs-meta);color:var(--ink-soft);font-variant-numeric:tabular-nums}
.buybar form{flex:0 0 auto;margin:0}
.buybar .btn{white-space:nowrap;min-height:44px}
@media (min-width:861px){ .buybar{display:none} }

/* ---- recently viewed --------------------------------------------------
   A row, not a grid: this is a trail rather than a catalogue, and it should
   read as smaller and quieter than "Pair it with" above it. Scrolls
   horizontally on narrow screens instead of wrapping into a second grid that
   competes with the real one. */
.rv[hidden]{display:none}
.rv__row{display:flex;gap:14px;overflow-x:auto;padding-bottom:6px;
  scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch}
.rv__card{flex:0 0 150px;scroll-snap-align:start;display:flex;flex-direction:column;gap:7px}
.rv__card img,.rv__noimg{width:150px;height:150px;border-radius:11px;object-fit:cover;
  background:var(--cream);display:block}
.rv__name{font-size:var(--fs-ui);line-height:1.35;color:var(--ink);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.rv__price{font-size:var(--fs-meta);color:var(--ink-soft)}
.rv__card:hover .rv__name{text-decoration:underline}

/* ---- search overlay ---------------------------------------------------
   Anchored to the top rather than centred: the input should land where the
   header search icon already was, so the overlay reads as that control
   expanding rather than as a new thing arriving from nowhere. */
.srch{position:fixed;inset:0;z-index:1100}
.srch[hidden]{display:none}
.srch__backdrop{position:absolute;inset:0;background:rgba(20,35,59,.42);
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
.srch__panel{position:relative;max-width:640px;margin:8vh auto 0;background:var(--white);
  border-radius:18px;box-shadow:0 24px 70px rgba(20,35,59,.28);overflow:hidden}
.srch__form{display:flex;align-items:center;gap:10px;padding:6px 8px 6px 18px;
  border-bottom:1px solid var(--line)}
.srch__icon{display:grid;place-items:center;color:var(--ink-faint);flex:0 0 auto}
.srch__form input{flex:1;border:0;outline:0;background:transparent;font:inherit;
  font-size:var(--fs-lede);padding:16px 0;color:var(--ink);min-width:0}
.srch__form input::-webkit-search-cancel-button{display:none}
.srch__results{max-height:min(58vh,460px);overflow-y:auto;overscroll-behavior:contain}
.srch__hit{display:flex;align-items:center;gap:14px;padding:11px 18px;border-bottom:1px solid var(--line-soft,#f0e9dc)}
.srch__hit img,.srch__noimg{width:52px;height:52px;border-radius:9px;object-fit:cover;
  background:var(--cream);flex:0 0 auto}
.srch__hittext{display:flex;flex-direction:column;gap:2px;min-width:0}
.srch__hitname{font-weight:500;font-size:var(--fs-ctl);color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srch__hitmeta{font-size:var(--fs-meta);color:var(--ink-soft)}
/* Hover and keyboard selection are the SAME state. Two different highlights
   for "the thing you are about to open" is how a combobox starts feeling
   like two widgets stapled together. */
.srch__hit:hover,.srch__hit[aria-selected="true"]{background:var(--cream)}
.srch__hit[aria-selected="true"]{outline:2px solid var(--focus);outline-offset:-2px}
.srch__seed{padding:16px 18px 20px}
.srch__seed[hidden]{display:none}
.srch__seedhead{margin:0 0 10px;font-size:var(--fs-micro);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-faint);font-weight:500}
.srch__chips{display:flex;flex-wrap:wrap;gap:8px}
.srch__all,.srch__empty{display:block;padding:14px 18px;font-size:var(--fs-ui);color:var(--ink-soft)}
.srch__all{font-weight:600;color:var(--gold-deep);text-align:center}
.srch__empty a{text-decoration:underline}
@media (max-width:560px){
  .srch__panel{margin:0;border-radius:0;height:100%;display:flex;flex-direction:column}
  .srch__results{max-height:none;flex:1}
}
@media (prefers-reduced-motion:reduce){ .srch__backdrop{backdrop-filter:none} }

/* ---- zoom -------------------------------------------------------------
   The overlay is near-black rather than the site's ivory on purpose: the
   photographs are the point, and a cream surround throws warm light back at
   a picture whose colour balance we spent a whole pipeline getting right. */
.gallery__zoom{display:block;position:relative;cursor:zoom-in;border-radius:inherit}
.gallery__zoomhint{position:absolute;right:12px;bottom:12px;display:inline-flex;gap:6px;
  align-items:center;background:rgba(255,255,255,.94);color:var(--ink);border-radius:999px;
  padding:7px 13px;font-size:var(--fs-micro);font-weight:500;letter-spacing:.02em;
  box-shadow:0 1px 6px rgba(20,35,59,.18);opacity:0;transition:opacity .16s ease}
.gallery__zoom:hover .gallery__zoomhint,
.gallery__zoom:focus-visible .gallery__zoomhint{opacity:1}
/* Touch has no hover, so the affordance would never appear — and a photograph
   that silently becomes tappable is a feature nobody finds. */
@media (hover:none){ .gallery__zoomhint{opacity:1} }

.zoom{position:fixed;inset:0;z-index:1000;display:grid;place-items:center}
.zoom[hidden]{display:none}
.zoom__backdrop{position:absolute;inset:0;background:rgba(12,17,26,.94);cursor:zoom-out}
.zoom__panel{position:relative;width:100%;height:100%;display:grid;place-items:center;padding:56px 16px 64px}
.zoom__stage{margin:0;max-width:min(1100px,94vw);max-height:82vh;overflow:hidden;display:grid;place-items:center}
.zoom__stage img{max-width:100%;max-height:82vh;width:auto;height:auto;display:block;
  border-radius:6px;transition:transform .12s ease-out}
@media (hover:hover){ .zoom__stage img{cursor:zoom-in} }
.zoom__stage img.is-panning{cursor:zoom-out;transition:none}
.zoom__btn{position:absolute;display:grid;place-items:center;width:46px;height:46px;
  border:0;border-radius:50%;background:rgba(255,255,255,.14);color:#fff;cursor:pointer;
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.zoom__btn:hover{background:rgba(255,255,255,.26)}
.zoom__btn:focus-visible{outline:2px solid #fff;outline-offset:3px}
.zoom__close{top:14px;right:14px}
.zoom__prev{left:14px;top:50%;transform:translateY(-50%)}
.zoom__next{right:14px;top:50%;transform:translateY(-50%)}
.zoom__hint{position:absolute;left:0;right:0;bottom:18px;margin:0;text-align:center;
  color:rgba(255,255,255,.66);font-size:var(--fs-meta);letter-spacing:.02em}
@media (max-width:560px){
  .zoom__panel{padding:52px 8px 56px}
  .zoom__btn{width:42px;height:42px}
  .zoom__prev{left:6px} .zoom__next{right:6px}
}
/* Respect a stated preference; the scale transition is decoration. */
@media (prefers-reduced-motion:reduce){
  .zoom__stage img,.gallery__zoomhint{transition:none}
}

/* Stock line. Quiet on purpose — it is information, not a countdown clock.
   No red, no flame, no animation: it appears at all only when the counts in
   this catalogue actually vary (see stockCountsAreDistinguishable), and a
   number that has earned the right to be shown does not need decoration. */
.stocknote{margin:0 0 12px;font-size:var(--fs-ui);color:var(--ink-soft);font-weight:600}
.stocknote::before{content:"";display:inline-block;width:7px;height:7px;border-radius:50%;
  background:#c08a2e;margin-right:8px;vertical-align:middle}

/* "Tell me when it's back" on a sold-out product. */
.restock{margin:14px 0 4px}
.restock label{display:block;margin-bottom:8px}
.restock__row{display:flex;gap:8px;flex-wrap:wrap}
.restock__row input{flex:1;min-width:190px;min-height:44px;padding:10px 14px;
  border:1.5px solid var(--line);border-radius:999px;background:#fff;font:inherit}
.restock__row button{min-height:44px;white-space:nowrap}
.restock .hint{margin:8px 0 0}
@media (max-width:420px){.restock__row input,.restock__row button{width:100%}}

.empty{text-align:center;padding:44px 20px;color:var(--ink-soft)}
.empty h2{margin-bottom:.3rem}

/* ---------- footer ---------- */
.ftr{background:var(--ink);color:#e8e3d8;padding:52px 0 26px;margin-top:40px}
.ftr a{color:#e8e3d8;opacity:.85} .ftr a:hover{opacity:1;color:var(--gold-soft)}
.ftr__grid{display:grid;grid-template-columns:1.4fr repeat(3,1fr);gap:30px}
@media(max-width:760px){.ftr__grid{grid-template-columns:1fr 1fr;gap:24px}}
.ftr h2.ftr__h,.ftr h3{color:#fff;font-family:var(--sans);font-size:var(--fs-meta);letter-spacing:.12em;text-transform:uppercase;margin-bottom:.8rem}
.ftr ul{list-style:none;padding:0;margin:0;display:grid;gap:8px;font-size:var(--fs-ui)}
.ftr__signup{margin-top:36px;padding-top:26px;border-top:1px solid rgba(255,255,255,.14);
  display:grid;grid-template-columns:1.2fr 1fr;gap:22px;align-items:center}
.ftr__signup p{font-size:var(--fs-ui);opacity:.82;margin:0;max-width:46ch}
.signup{display:flex;gap:8px;flex-wrap:wrap}
.signup input{flex:1;min-width:200px;min-height:46px;padding:10px 14px;border-radius:10px;
  border:1px solid rgba(255,255,255,.24);background:rgba(255,255,255,.07);color:#fff;font-family:var(--sans)}
.signup input::placeholder{color:rgba(255,255,255,.5)}
@media(max-width:760px){.ftr__signup{grid-template-columns:1fr}}

/* ---------- gift finder ---------- */
.giftgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:16px}
.giftcard{display:grid;grid-template-columns:84px 1fr;gap:14px;align-items:center;background:var(--white);
  border:1px solid var(--line);border-radius:var(--radius-md);padding:14px;transition:border-color .15s ease}
.giftcard:hover{border-color:var(--gold)}
.giftcard img{width:84px;height:84px;object-fit:cover;border-radius:10px;background:var(--cream)}
.giftcard h3{font-size:var(--fs-body);margin:0 0 3px}
.giftcard p{margin:0;font-size:var(--fs-ui);color:var(--ink-soft)}
.giftcard span{font-size:var(--fs-micro);color:var(--ink-faint);display:block;margin-top:4px}

/* ---------- seasonal / drop banner ---------- */
.seasonbar{background:var(--cream);border:1px solid var(--line);border-radius:var(--radius-md);
  padding:16px 18px;display:flex;gap:16px;align-items:center;justify-content:space-between;flex-wrap:wrap}
.seasonbar p{margin:0;color:var(--ink-soft);font-size:var(--fs-ctl)}
.seasonbar strong{display:block;font-family:var(--serif);font-size:var(--fs-lede);color:var(--ink)}
.cutoff{font-size:var(--fs-meta);color:var(--gold-deep);font-weight:600}

/* ---------- payment choice ----------
   A radio group with real labels, not a stack of branded buttons. The whole
   row is the target so it is easy to hit one-handed. */
.payfield{border:1.5px solid var(--line);border-radius:var(--radius-md);padding:14px 16px;margin:22px 0 0}
.payfield legend{font-weight:600;font-size:var(--fs-ctl);padding:0 6px}
.paychoice{display:flex;gap:12px;align-items:flex-start;padding:11px 4px;cursor:pointer;min-height:48px}
.paychoice+.paychoice{border-top:1px solid var(--line)}
.paychoice input{margin-top:2px;flex:none}
.paychoice strong{display:block;font-weight:600;font-size:var(--fs-ctl)}
.paychoice__hint{display:block;color:var(--ink-soft);font-size:var(--fs-meta);margin-top:2px}
.paychoice:has(input:checked) strong{color:var(--gold-deep)}

/* ---------- pdp buying context ---------- */
.pdp__ship{font-size:var(--fs-ui);color:var(--ink-soft);margin:12px 0 4px}
.pdp__gift{font-size:var(--fs-ui);color:var(--ink-soft);margin:4px 0 0;display:flex;gap:7px;align-items:center}

/* ---------- reviews ---------- */
.rvw{border-top:1px solid var(--line);padding:16px 0}
.rvw__head{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap}
.rvw__name{font-weight:600}
.rvw__verified{font-size:var(--fs-micro);color:#1d5c3f;background:#e2f4ea;border-radius:999px;padding:2px 9px;font-weight:600}
.stars{color:var(--gold-deep);letter-spacing:.08em}
.ratingline{display:flex;gap:8px;align-items:center;font-size:var(--fs-ui);color:var(--ink-soft);margin:-6px 0 10px}

.ftr__bot{margin-top:34px;padding-top:18px;border-top:1px solid rgba(255,255,255,.14);font-size:var(--fs-meta);opacity:.7;
  display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap}

/* ---------- filters / search ---------- */
/* WCAG 2.2 AA (2.5.8) minimum target size is 24x24 CSS px. */
input[type="checkbox"],input[type="radio"]{width:24px;height:24px;min-height:24px;accent-color:var(--ink);flex:none}
.chips{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:20px}
.chip{border:1.5px solid var(--line);background:var(--white);border-radius:999px;padding:8px 15px;font-size:var(--fs-ui);
  font-weight:500;cursor:pointer;font-family:var(--sans);color:var(--ink);min-height:40px;display:inline-flex;align-items:center}
.chip:hover{border-color:var(--gold)}
.chip[aria-pressed="true"],.chip[aria-current="true"]{background:var(--ink);color:#fff;border-color:var(--ink)}
.toolbar{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap;margin-bottom:18px}
.toolbar__count{font-size:var(--fs-ui);color:var(--ink-soft)}
.searchform{display:flex;gap:8px;max-width:520px;margin:0 0 22px}
.searchform input{flex:1}

/* Overflow collapse for long filter rows. Native <details>, so it is
   keyboard-operable and needs no script. */
.chips__more{position:relative;display:inline-block}
.chips__more>summary{list-style:none;cursor:pointer}
.chips__more>summary::-webkit-details-marker{display:none}
.chips__more[open]>summary{background:var(--ink);color:#fff;border-color:var(--ink)}
.chips__rest{display:flex;gap:8px;flex-wrap:wrap;padding:12px 0 0;width:100%}


/* ---------- Meet the maker ---------- */
/* An editorial split rather than a card. The maker is a person, not a
   dashboard tile, and a rounded white box with a shadow would say the
   opposite. Warm surface separates it from the product sections above and
   below without introducing another saturated colour. */
.maker{background:var(--cream)}
.maker__in{display:grid;gap:48px;align-items:center;grid-template-columns:minmax(0,420px) minmax(0,1fr);justify-content:center}
.maker__body h2{margin:6px 0 12px;max-width:16ch}
.maker__body p{margin:0 0 20px;color:var(--ink-soft);max-width:46ch;font-size:var(--fs-body);line-height:1.65}

.maker__portrait img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:var(--radius-md);display:block}

/* Three real product photographs, overlapped. Authentic, and a considered
   arrangement reads as intent where a single centred image would read as a
   gap waiting for the portrait that has not been taken yet. */
.maker__stack{position:relative;aspect-ratio:1/1;max-width:400px;width:100%}
/* Square, explicitly. The source photographs are not all the same shape, and
   width/height attributes alone let a portrait source render tall — which
   cropped the earrings off at the bottom edge of every tile. aspect-ratio plus
   object-fit does the cropping deliberately and identically for all three. */
.maker__stack-img{position:absolute;aspect-ratio:1/1;height:auto;
  border-radius:14px;box-shadow:0 8px 26px rgba(20,35,59,.13);
  background:var(--white);object-fit:cover;object-position:center}
.maker__stack-img--1{width:58%;left:0;top:6%;transform:rotate(-4deg)}
.maker__stack-img--2{width:54%;right:0;top:0;transform:rotate(5deg)}
.maker__stack-img--3{width:50%;left:24%;bottom:2%;transform:rotate(-1deg)}

/* Phone: text first, then the visual. A large image above several screens of
   copy is the exact failure the brief calls out. */
@media (max-width:840px){
  .maker__in{grid-template-columns:1fr;gap:24px}
  .maker__body{order:1}
  .maker__stack,.maker__portrait{order:2;margin:0 auto}
  .maker__stack{max-width:300px}
}
@media (prefers-reduced-motion:reduce){
  .maker__stack-img{transform:none}
  .maker__stack-img--1{left:0;top:2%}
  .maker__stack-img--2{right:0;top:0}
  .maker__stack-img--3{left:24%;bottom:0}
}


/* ---------- Meaning Map ---------- */
.motif-body{max-width:60ch;margin:0 0 30px;font-size:var(--fs-body);line-height:1.65}
.motif-body p{margin:0 0 14px}
.motif-more{font-size:var(--fs-body);margin:34px 0 12px}



/* ---------- discovery tiles (shared) ---------- */
/* One tile, used by Find Your Jewish Joy AND the Meaning Map.
 *
 * The photograph does the work; the label sits on the page beneath it,
 * exactly like a product card. Sharing the component is the point: these are
 * two doors into the same shop, and giving each its own card style is how a
 * site ends up feeling like several small applications stitched together. */
.joy-tiles,.motif-tiles{list-style:none;margin:0;padding:0;display:grid;gap:clamp(14px,2.2vw,26px);
  grid-template-columns:repeat(auto-fit,minmax(min(100%,215px),1fr))}
.joy-tile,.motif-tile{display:flex;flex-direction:column;text-decoration:none;color:var(--ink)}
.joy-tile__media,.motif-tile__media{display:block;aspect-ratio:1;overflow:hidden;border-radius:var(--radius-md);
  background:linear-gradient(165deg,var(--cream),#fdfaf4 72%);
  box-shadow:0 2px 10px rgba(20,35,59,.05);transition:box-shadow .18s,transform .18s}
.joy-tile__media img,.motif-tile__media img{width:100%;height:100%;object-fit:cover;transition:transform .4s}
.joy-tile:hover .joy-tile__media,.joy-tile:focus-visible .joy-tile__media,
.motif-tile:hover .motif-tile__media,.motif-tile:focus-visible .motif-tile__media{
  box-shadow:0 12px 30px rgba(20,35,59,.13);transform:translateY(-3px)}
.joy-tile:hover .joy-tile__media img,.motif-tile:hover .motif-tile__media img{transform:scale(1.04)}
.joy-tile__text,.motif-tile__text{display:block;padding:12px 2px 0}
.joy-tile__label,.motif-tile__label{display:block;font-family:var(--serif);font-size:var(--fs-lede);font-weight:600;line-height:1.3;letter-spacing:-.008em}
.joy-tile__meta,.motif-tile__meta{display:block;font-size:var(--fs-meta);color:var(--ink-soft);margin-top:3px;line-height:1.45}

.joy-out{margin-top:30px;display:flex;gap:12px;flex-wrap:wrap;align-items:center;font-size:var(--fs-ui)}
.crumbs{font-size:var(--fs-ui);color:var(--ink-soft);margin-bottom:10px}
/* A single surprise product should not stretch across a 1440px grid. */
.section-head--center{text-align:center;margin-left:auto;margin-right:auto}
.surprise{max-width:340px;margin:0 auto}

@media (prefers-reduced-motion:reduce){
  .joy-tile__media,.joy-tile__media img,.motif-tile__media,.motif-tile__media img{transition:none}
  .joy-tile:hover .joy-tile__media,.motif-tile:hover .motif-tile__media{transform:none}
  .joy-tile:hover .joy-tile__media img,.motif-tile:hover .motif-tile__media img{transform:none}
}

/* Reading measure: meaning text is prose and prose does not want 1400px. */



/* ---------- specifications & Size Studio ---------- */
/* A definition list, because that is what it is: terms and their values. The
   grid is on the rows so a long value wraps under its own label instead of
   dragging the whole table wider at 390px. */
.spec-list{margin:0;display:grid;gap:2px}
.spec{display:grid;grid-template-columns:minmax(6.5rem,34%) 1fr;gap:10px;padding:7px 0;border-bottom:1px solid var(--line)}
.spec:last-child{border-bottom:0}
.spec dt{margin:0;color:var(--ink-soft);font-size:var(--fs-ui)}
.spec dd{margin:0;font-weight:600;font-size:var(--fs-ctl)}

.sizestudio__fig{margin:16px 0 4px;padding:0}
/* The drawing is a proportion, so it must never be stretched. Capping the
   width keeps it from becoming a billboard on a wide screen, where scaling it
   up would not add a single millimetre of information. */
.sizestudio__fig svg{max-width:340px;display:block}
.sizestudio__fig figcaption{margin-top:10px;font-size:var(--fs-meta);color:var(--ink-soft);max-width:52ch;line-height:1.5}

.cmp-wrap{display:flex;gap:26px;align-items:flex-end;flex-wrap:wrap;margin:16px 0}
.cmp{display:flex;flex-direction:column;align-items:center;gap:10px;min-width:120px}
.cmp__bar{width:34px;border-radius:6px;background:var(--tool-piece,#c2452f);opacity:.9}
.cmp__label{font-size:var(--fs-meta);color:var(--ink-soft);text-align:center;line-height:1.4}
