/* ═══════════════════════════════════════════════════════════════════════════
   מגנוליה — the SHOP layer.  (step 13 · the 24 dead routes)
   Loaded by the six category pages, the five collection pages and the 2,284
   product pages. Nothing here is a new value: every colour, size, duration and
   easing is a token already derived in BRAND-DIRECTION.md and declared in
   styles.css. Two things are deliberately REUSED rather than re-cut —

     · the product card — .cat__p / .cat__ph / .cat__n / .cat__pr / .cat__was —
       is the home page's card, unchanged, so a card cannot drift between the
       catalogue and a category page. Only the CONTAINER differs: the home grid
       is a bounded, internally-scrolling section (max-height 64vh) because it
       sits inside a 1.0vh composition; a category page IS the grid, so the
       bound is lifted below.
     · the document furniture — .doc / .crumb / .kv / .law — is legal.css's,
       written for the branch and legal pages. A category page is a document
       with a grid in it, not a third layout system.

   ⚠ minmax(0,1fr), never a bare 1fr. A bare `1fr` is minmax(AUTO,1fr) and auto
   resolves to MIN-CONTENT, which for a 460px WebP is 460px whatever
   img{max-width:100%} says. Four of those made the home grid 1,918px inside a
   1,440px page (measured 13.8.2026). Every grid in this file states the zero.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── the page ─────────────────────────────────────────────────────────────
   .doc gives the rail and the bottom padding. .doc__body's 680px reading
   measure is for CLAUSES; a grid of photographs is not read line by line. */
.shop__body{ max-width:none; }

/* ── the rail, narrowed for the shop ──────────────────────────────────────
   BRAND-DIRECTION's own committed levers say "alignment right, edge-to-edge,
   0% margin". The build did not deliver it: every shop template measured
   content width 73.8% against a field median of 99% and a p10 of 93.5%, and a
   side margin of 13.1% against a p90 of 11.1% — outside the field on the SAFE
   side, on all four page types, which is what "dry" measures like.
   SIGNATURE.json already records both under "acceptedAccidents … NOT a
   signature … the style frame was composed on a 210px rail", which is the
   honest description of a number nobody chose.

   So the shop runs a 44px rail (2.75% a side; content width ~95%). The 210px rail stays on the home page, where
   it IS the composition the style frame was approved on, and on the nav and
   the footer: chrome inset while the merchandise runs to the frame is a
   contrast the page can carry, and 8 of 11 sites in this category touch both
   edges while this build touched neither. */
.doc.shop{ --rail:44px; }

/* The home page's catalogue is a bounded viewport inside a taller section, so
   styles.css caps it and lets it scroll inside itself. Here the page is the
   catalogue: an inner scroller would trap the wheel and hide 40 of 48
   products from anything that does not run JavaScript. */
.shop .cat__grid{ max-height:none; overflow:visible; }

/* A section inside .doc, without styles.css's full-bleed 110px/var(--rail)
   composition padding — same reset legal.css makes for .doc__s, and for the
   same reason: a <section> here is a block in a document, not a screen. */
.shop__s{
  padding:64px 0 0; border-top:1px solid var(--c-line); margin-top:72px;
}
.shop__h{
  font-family:"Magnolia Display","Magnolia",sans-serif;
  font-size:var(--t-sub); line-height:var(--lh-sub); letter-spacing:-0.01em;
  font-weight:var(--w-strong); font-variation-settings:'wght' 600;
  margin:0 0 22px;
}
.shop__p{ margin:0 0 18px; max-width:680px; line-height:var(--lh-body); }
.shop__p:last-child{ margin-bottom:0; }
.shop__p strong{ font-weight:var(--w-strong); font-variation-settings:'wght' 600; }
.shop__p a{ border-bottom:1px solid var(--c-line); }
.shop__p a:hover{ border-bottom-color:var(--c-ink); }
.shop__src{ font-size:var(--t-meta); color:var(--c-ink-muted); margin:22px 0 0; max-width:680px; }

/* The count bar. .cat__bar and .cat__count are the home page's own, so the
   sentence that states the cap looks identical wherever it is said. */
.shop__sort{ font-size:var(--t-meta); color:var(--c-ink-muted); margin-inline-start:auto; }

/* ── THE MASTHEAD — four page types stop being one ────────────────────────
   /necklaces/, /c/pearls/, /personal/ and /branches/<x>/ returned BYTE-
   IDENTICAL layout measurements: same 92px heading, same eyebrow, same lede,
   same bar, same uniform grid. One template, four names. The fix is not four
   decorations — it is that a category and a collection are not the same kind
   of thing, and the page should say which one it is.

   A CATEGORY IS A LETTER. --t-display appeared in NO rule in this file before
   now, which is precisely how the 9.5× signature came to live on exactly one
   URL. Here it is a claim and not a repeat: the home page's א״ב section
   already assigns this shelf this letter and prints the anatomical reason, and
   this masthead is that sentence at full size. It REPLACES the 92px heading,
   so first-screen text coverage goes DOWN — the box of one glyph against a
   heading, a lede and an eyebrow. CONCEPT's guardrail holds exactly: one
   letter, never a display sentence. */
.mast{ padding:56px 0 0; }
.mast--letter{
  display:grid; grid-template-columns:auto minmax(0,1fr);
  gap:0 44px; align-items:end;
  /* PULSE — the same fault the product page had, one level up. The category's
     first screen is a large STATIC ink letter plus whatever tiles fit under
     it, and .cat__ph's mg-cross keyframe is opaque for only 43% of its cycle.
     Twelve staggered tiles cover that on the catalogue; three or four above
     the fold of a category page do not, so the gate measured 7.56% on one pass
     and 4.44% on the next and refused to judge — spread 22.221, exit 2.
     Correctly: a page alive half the time is not an alive page.
     The masthead is the biggest thing on that screen and it was contributing
     nothing, so it carries the continuous crawl. `.lit`'s 1→0 wrap is
     bit-identical, so there is no moment where the streak is absent, and it is
     driven by the one lamp at the measured 105° rather than by a keyframe that
     would own `transform` and lock the pointer out. */
  position:relative;
  --sp:560px; --rate:1; --rmp:96px;
}
.mast--letter > *{ position:relative; z-index:1; }
.mast--letter::after{
  content:""; position:absolute; top:0; bottom:0;
  left:calc(var(--sp) * var(--rate) * -1.1 - 90px); right:-90px;
  pointer-events:none; z-index:2;
  background:repeating-linear-gradient(var(--az),
    transparent 0px,
    transparent calc(var(--sp) - var(--rmp) * 2.9),
    var(--sheen-shade) calc(var(--sp) - var(--rmp) * 2),
    var(--sheen-plate) calc(var(--sp) - var(--rmp)),
    transparent var(--sp));
  transform:translate3d(
    calc(var(--sheen) * var(--sp) * var(--rate) * 1.0353 + var(--key-x) * 84px), 0, 0);
}
@media (prefers-reduced-motion:reduce){
  .mast--letter::after{ transform:none; }
}
.mast__l{
  font-family:"Magnolia Display","Magnolia",sans-serif;
  font-size:var(--t-display); line-height:.78;
  font-weight:var(--w-display); font-variation-settings:'wght' 400;
  letter-spacing:var(--tr-display); color:var(--c-ink);
  display:block; margin-block:-.09em -.06em;
  /* into the frame edge, and tied to the LETTER rather than to --rail: the
     shop rail is now 56px, and a bleed that shrinks with the margin would have
     quietly pulled the signature back inside the safe box the narrower rail
     exists to leave. 0.12em of a 380px glyph is ~46px of overhang. */
  margin-inline-start:-0.12em;
}
.mast__t{ padding-bottom:.5em; max-width:46ch; }
.mast__h{
  font-family:"Magnolia Display","Magnolia",sans-serif;
  font-size:var(--t-sub); line-height:var(--lh-sub); letter-spacing:-0.01em;
  font-weight:var(--w-strong); font-variation-settings:'wght' 600;
  margin:0;
}
/* the anatomical reason, quoted from the א״ב section so the two cannot drift */
.mast__role{
  margin:10px 0 0; font-size:var(--t-meta); color:var(--c-ink-muted);
  max-width:34ch; line-height:1.5;
}
/* The lede sits BESIDE the letter, not under it. Full-width it pushed the grid
   ~150px down and left the whole left half of the first screen empty — a
   category page whose first screen carries a letter, four lines of type and
   almost no merchandise. Beside it, the first row of products is on the screen
   the visitor lands on, which is both the better composition and the better
   commerce. */
.mast--letter .doc__lede{ margin:22px 0 0; font-size:var(--t-body);
  line-height:var(--lh-body); font-variation-settings:'wght' 400;
  font-weight:var(--w-body); color:var(--c-ink-muted); max-width:46ch; }
.mast--letter{ margin-bottom:30px; }

/* עיצוב אישי — THE NAME. Not our letter (they are the customer's here) and not
   a photograph: the product IS a name cut in this typeface, so the masthead is
   one, at --t-display, in the display cut. It is also the only masthead on the
   site where the display type is a WORD rather than a glyph — which is exactly
   the case CONCEPT's guardrail allows, because the guardrail is about the HERO
   staying inside 6.3–17.1% first-screen text coverage, and a 7-character name
   at the top of a category page is a specimen of the merchandise. */
.mast--name{ display:grid; grid-template-columns:auto minmax(0,1fr);
  gap:0 44px; align-items:end; margin-bottom:30px; }
.mast__name{
  font-family:"Magnolia Display","Magnolia",sans-serif;
  font-size:var(--t-display); line-height:.82;
  font-weight:var(--w-display); font-variation-settings:'wght' 400;
  letter-spacing:var(--tr-display); color:var(--c-ink);
  display:block; margin-block:-.1em -.06em; margin-inline-start:-0.06em;
  white-space:nowrap;
}
.mast--name .doc__lede{ margin:22px 0 0; font-size:var(--t-body);
  line-height:var(--lh-body); font-variation-settings:'wght' 400;
  font-weight:var(--w-body); color:var(--c-ink-muted); max-width:46ch; }
@media (max-width:900px){
  .mast--name{ grid-template-columns:minmax(0,1fr); gap:0; }
  .mast__name{ font-size:clamp(96px,26vw,180px); margin-inline-start:0; }
}

/* A COLLECTION IS NOT A LETTER — it is a set of photographs. This is the
   field's own image-carries-the-page (5 of 11 jewelry sites), which we were
   not doing anywhere: one full-bleed frame, edge to edge, and the type small
   underneath it. */
.mast--band{ padding-top:26px; }
.mast__band{
  position:relative; margin:0 calc(var(--rail) * -1) 34px;
  height:min(62vh,620px); overflow:hidden; background:var(--c-paper-deep);
}
.mast__band img{ width:100%; height:100%; object-fit:cover; object-position:50% 42%;
  mix-blend-mode:multiply; filter:brightness(1.06); }
.mast__h--band{ font-size:var(--t-head); line-height:var(--lh-head);
  letter-spacing:var(--tr-head); }
.mast--band .doc__lede{ margin:26px 0 40px; }

@media (max-width:900px){
  .mast--letter{ grid-template-columns:minmax(0,1fr); gap:0; }
  .mast__l{ margin-inline-start:0; }
  .mast__t{ padding-bottom:0; margin-top:18px; }
  .mast__band{ height:46vh; }
}

/* ── the second act on a product page ─────────────────────────────────────
   The attribute table, the description and the legal block used to share the
   sticky column with the price, which is why the first screen carried
   19.1–30.4% text against a field p90 of 17.1%. They are reference — read
   after the decision, not with it. */
.pdp__more{
  /* ⚠ the spec takes the WIDE column and the photograph the narrow one, which
     is the opposite of the obvious arrangement and the reason is hierarchy:
     with 1fr on the picture the second view rendered ~1,000px wide — larger
     than the seated hero above it, with the piece smaller inside it. A
     supporting view that outsizes the subject inverts the page. Caught in a
     full-page capture; nothing measured on the first screen can see it. */
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,420px); gap:0 64px;
  align-items:start; margin-top:88px; padding-top:44px;
  border-top:1px solid var(--c-line);
}
.pdp__more-note{ min-height:1px; }
.pdp__more .pdp__ph{ max-width:420px; }
.pdp__spec .kv{ margin-top:0; }
.pdp__spec .kv div{ grid-template-columns:118px minmax(0,1fr); gap:0 16px; }
/* the relation, said in one line: the letter, and why it is this letter */
.pdp__rel{ display:flex; align-items:baseline; gap:16px; margin:0 0 26px;
  padding-bottom:20px; border-bottom:1px solid var(--c-line); }
.pdp__rel-l{
  font-family:"Magnolia Display","Magnolia",sans-serif;
  font-size:var(--t-sub); line-height:1; font-weight:var(--w-display);
  font-variation-settings:'wght' 400; color:var(--c-ink);
}
.pdp__rel-t{ font-size:var(--t-meta); color:var(--c-ink-muted); line-height:1.5; }
.pdp__desc{ margin:22px 0 0; }

@media (max-width:900px){
  .pdp__more{ grid-template-columns:minmax(0,1fr); gap:30px; margin-top:52px; }
}

/* ── the sub-index — what is actually inside this category ────────────────
   Real sub-category names with real counts, straight out of the harvest. It
   is the single most useful block on a 738-product page and it is the one
   thing their own category pages do not print. Not links: those sub-listings
   have no route on this site, and a dead link is the defect this whole step
   exists to remove. */
.shop__subs{ display:flex; flex-wrap:wrap; gap:10px 26px; margin:0 0 22px;
  font-size:var(--t-meta); }
.shop__sub{ color:var(--c-ink-muted); }
.shop__sub b{ color:var(--c-ink); font-weight:var(--w-body);
  font-variation-settings:'wght' 600; margin-inline-start:6px; }

/* ── pagination ──────────────────────────────────────────────────────────
   Real URLs, server-rendered, one page per 48 products — 48 because that is
   the page size Magnolia's own category listings use (FACTS §6). "Load more"
   would put 690 of 738 necklaces behind a click no crawler makes. */
.pager{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:6px 16px;
  border-top:1px solid var(--c-line); padding-top:22px; margin-top:56px;
  font-size:var(--t-meta);
}
.pager a{ color:var(--c-ink-muted); border-bottom:1px solid transparent; padding-bottom:2px; }
.pager a:hover{ color:var(--c-ink); border-bottom-color:var(--c-line); }
.pager [aria-current="page"]{ color:var(--c-ink); font-variation-settings:'wght' 600;
  border-bottom:1px solid var(--c-ink); padding-bottom:2px; }
.pager__gap{ color:var(--c-ink-muted); }
.pager__step{ font-variation-settings:'wght' 600; color:var(--c-ink); }
.pager__of{ margin-inline-start:auto; color:var(--c-ink-muted); }

/* ── THE SEAT — the invention, below the fold ─────────────────────────────
   Measured before this existed: the product template's largest display type
   was 40px — the jewelry corpus's median to the decimal, across 2,283 pages —
   `--t-display` appeared in NO rule in this file, and grep for glyph/watermark
   /rail on a product, a category and a branch page returned 0, 0, 0. The
   signature stopped at the home page and the shop was a different website.

   What it is: the shelf's own letter (the one the home page's א״ב section
   already gives it, with its anatomical reason printed underneath) at
   architectural scale, bleeding off the reading edge, with the photograph
   seated on the exact point of the outline where that piece would really hang,
   sit, thread or pass through — data/glyph-anchors.json, rastered from Narkiss
   Block's own contours at wght 400.

   Why an inline <svg> and not text: at ~100vh a glyph is hinted and snapped, a
   path is not — and, load-bearing here, a path is not TEXT, so it does not
   enter the first screen's text coverage. That number was already 19.1–30.4%
   against the field's p90 of 17.1%, which is why CONCEPT's guardrail forbids
   simply repeating the 380px letter down here.

   The ink is IN FRONT of the photograph. SCENE.md §1: "האות מסתירה את האובייקט.
   occlusion הוא רמז העומק הזול והמשכנע ביותר שקיים." Across the variant round
   that single overlap is the whole difference between a picture beside a big
   shape and a piece hanging off a letter — and it costs no shadow (the system
   has none), no border and no third colour.

   ⚠ RTL sign trap, paid for once in qa/pdp-variants: inset-inline-start
   measures from the RIGHT edge, so a LARGER value moves the photograph AWAY
   from the letter. --bite is therefore SUBTRACTED. With the sign inverted the
   picture slid left and the sku, the title and the price all rendered on top
   of it — and nothing in the gate can see text over a photograph. */
.seat{
  /* Two columns, and the letter is STRUCTURALLY unable to reach the second.
     ⚠ This is not tidiness. The first build of this section positioned the
     glyph against the viewport and let the information column float over it on
     z-index. It rendered a 1,235px-wide ש across the right 58% of the frame —
     directly over the product name, the price and the add-to-cart button, all
     of which are --c-ink on --c-ink and therefore INVISIBLE. score-layout said
     "✓ passes" (coverage 27.6%, dominance 110, scale 110×) and the tone probe
     said L* range 85. Neither can see ink on ink. A z-index would have hidden
     the symptom on this letter and let the next one through, so the merchandise
     lives in a column the decoration cannot enter. */
  display:grid; grid-template-columns:minmax(0,1fr) 420px; gap:0 56px;
  align-items:start;
  /* Only the START side breaks the rail, so the letter reaches the frame edge
     and the information column stays inside it. Content width measured 73.8%
     against a field median of 99% and side margin 13.1% against a p90 of 11.1%
     — both outside the field on the safe side, which is what "dry" measures
     like. */
  margin-inline:calc(var(--rail) * -1);
  padding-top:26px;
  /* THREE caps on the letter, and the third is the one that matters.
     1 · 96vh   — it is architecture, not a background.
     2 · 46vw / aspect — so a wide letter (ש is 1.19:1) and a narrow one
         (ל is 0.62:1) both land inside the field instead of one flooding it.
     3 · its own ANATOMY — see --kh in tools/seat.mjs. A letter whose highest
         stroke sits 68% down its body (ע, which has two arms and no rail) must
         run smaller, or the piece hanging from it falls off the first screen.
         It did: two hoop tips and nothing else, at 106.75 dominance and a pass. */
  --fh:min(90vh,860px);
  --phh:calc(var(--phw) * 1.3335);
  --gh:min(96vh, calc(46vw / var(--aspect)));
  --gw:calc(var(--gh) * var(--aspect));
}
/* the third cap, and it is not the same sum for the two placements — a piece
   HANGING below the letter has to clear the fold, a piece INSIDE it only has
   to have its counter clear the fold. Sharing one formula shrank ס to 421px
   and dropped the ring page to 10.8% ink and 88.6% of the frame in one tone,
   which is the flat page this whole section exists to end. */
.seat--hang{
  --gh:min(96vh, calc(46vw / var(--aspect)),
        calc((var(--fh) - var(--phh) * 0.88) * var(--kh)));
}
.seat--inside{
  --gh:min(96vh, calc(46vw / var(--aspect)),
        calc((var(--fh) - 60px) * var(--kh)));
}
/* RESTS ON — the piece sits in the valley between two peaks and the peaks rise
   in FRONT of it. Here --kh caps the intrusion rather than the drop: 25% of the
   photograph's height, so the ink can never reach the piece in the middle. */
.seat--rest{
  --gh:min(96vh, calc(46vw / var(--aspect)), calc(var(--phh) * var(--kh)));
}
.seat--rest .seat__ph{
  position:absolute;
  top:calc(var(--g-top) + var(--gh) * (var(--ay) + var(--tuck)));
  transform:translateY(-100%);
  /* centred ON the valley, not hung from it — a chain drapes across a dip */
  inset-inline-start:max(0px,
    calc(var(--g-start) + var(--gw) * (1 - var(--ax)) - var(--phw) / 2));
}
/* ⚠ THE LETTER IS FRAMED FIRST, AND THE SEAT FOLLOWS IT — not the other way
   round. The previous pass fixed the SEAT at a target point in the field and
   let the letter fall wherever its anchor put it, which meant a letter whose
   highest stroke sits near its own right edge (ש: anchor x 0.92) was pushed
   almost entirely off-frame and rendered as an abstract black wedge. The
   letter has to stay READABLE AS A LETTER — CONCEPT calls destroying the
   script the one failure that cannot be repaired later — so the glyph gets a
   fixed bleed off the start edge and the top, and the photograph is placed
   from the anchor relative to THAT. One rule, no per-letter tuning, and every
   letter is framed identically however its anatomy is arranged. */
.seat__field{
  position:relative; min-height:var(--fh); overflow:hidden;
  /* the bleed. Enough for the letter to reach the frame — 8 of 11 jewelry
     sites in the corpus run content into both edges and we ran into neither —
     and small enough that the letter is still legible AS a letter, which
     CONCEPT calls the one failure that cannot be repaired later. */
  --g-start:calc(var(--gw) * -0.045);
  --g-top:calc(var(--gh) * -0.04);
}
.seat__g{
  position:absolute; z-index:2; pointer-events:none;
  height:var(--gh); width:var(--gw);
  top:var(--g-top); inset-inline-start:var(--g-start);
}
.seat__g path{ fill:var(--c-ink); }

.seat__ph{
  position:relative; z-index:1; margin:0; width:var(--phw);
  background:var(--c-paper-deep);   /* BRAND-DIRECTION §3.5's grade target,
     L* 79.9 — the value the page's own luminance budget is computed against,
     and the reason a masked cut-out reads as the same material in shade
     instead of a patch stuck on. It is also where the midtones come from: the
     first screen measured 2.09% of its pixels between L* 20 and 80. */
  overflow:hidden;
}
.seat__ph img{ width:100%; height:auto; mix-blend-mode:multiply; filter:brightness(1.06); }

/* PULSE LAW — and this is where the gate was actually failing.
   The old sheen here was .cat__ph's keyframe, mg-cross, which is opaque from
   3% to 46% of its 13s cycle and INVISIBLE for the other 54%. On the catalogue
   that is deliberate and it works: twelve staggered tiles mean two or three are
   always crossing, so the section never dies. On a product page there is ONE
   photograph on the first screen, so for seven seconds in every thirteen the
   page had no moving pixel at all. That is what "the two measurement passes
   disagreed (spread 16.185) — the value is not reproducible" was: not a flaky
   probe, a page that is alive slightly over half the time. The gate refused to
   judge it, correctly, and refusing is not passing.

   The fix is the mechanism craft.css already has and this file was not using:
   .lit's repeating-gradient crawl, whose 1→0 wrap is bit-identical so the
   streak never leaves and never restarts. It is driven by light.js — one lamp,
   locked to the measured 105°, with the pointer freedom CONCEPT asks for
   ("הסמן הוא מקור האור") — which the keyframe could never give, because a
   keyframe owns `transform` and the pointer's contribution lives there.
   The figure carries `lit lit--photo` in the markup; these two values size the
   period to the 34vw box. */
.seat__ph{ --sp:340px; --rate:2; }
/* the no-JS path SCENE.md §8.5 promises — "the sheen still crawling in CSS,
   never a dead poster". background-position, not transform, so it cannot
   collide with the lamp's own transform the moment the lamp arrives. */
@media (prefers-reduced-motion:no-preference){
  html:not(.mg-ready) .seat__ph::after{
    animation:mg-crawl var(--travel) linear infinite;
  }
}
@keyframes mg-crawl{
  from{ background-position:0 0; }
  to{ background-position:calc(var(--sp) * 1.0353) 0; }
}

/* the two placements — see tools/seat.mjs for why there are two and not four */
/* HANGS FROM — the underside of the highest stroke. Ink crossing the TOP edge
   of a photograph can never reach the piece, whatever the letter's anatomy;
   that is the whole reason this is the placement every carrying letter uses. */
.seat--hang .seat__ph{
  position:absolute;
  top:calc(var(--g-top) + var(--gh) * (var(--ay) - var(--tuck)));
  /* ⚠ THE ONE RULE, AND IT IS STATED HERE BECAUSE IT COST FOUR REBUILDS:
     THE INK MAY CROSS THE PHOTOGRAPH'S EDGE. IT MAY NEVER CROSS ITS CENTRE.

     A letter's highest stroke is not in the same place in every letter. צ's is
     at 0.128 of its own box — near its far edge — so the photograph naturally
     lands clear of the letter's body and only the left stroke crosses its
     corner. ש's is at 0.920 and ע's at 0.896, right against their start edge,
     so the same arithmetic put the photograph directly UNDER the whole letter:
     rendered, ש's centre arm ran straight down the pendant and ע's arm covered
     one of the two hoops. Both scored well. Nothing in score-layout or the tone
     probe can see a letter sitting on the merchandise.

     So the second term is a floor, not a nudge: whatever the anchor says, the
     photograph is pushed far enough that its CENTRE — where a cut-out puts the
     piece — clears the letter's near edge by 56px. The occlusion survives on
     the corner, which is where it was always doing the work. */
  inset-inline-start:max(
    calc(var(--g-start) + var(--gw) * (1 - var(--ax) - var(--bite))),
    calc(var(--g-start) + var(--gw) - var(--phw) / 2 + 56px));
}
/* INSIDE — ס and ם are the only two letters in the alphabet with a real
   enclosed counter (contour count, data/glyph-paths-all.json; the concept was
   corrected once for putting ט here). The piece goes IN the hole: the picture
   is centred on the counter, and the paper runs on behind the ink above and
   below it. --ax is the counter's far edge and --ay its top, both fractions of
   the glyph box, both measured. */
.seat--inside .seat__ph{
  position:absolute;
  /* the counter IS the frame — the picture is cut to it exactly, so no corner
     of the paper escapes the letter. It escaped in the first render and the
     "inside" reading collapsed instantly: a rectangle poking out of a ס is a
     photograph BEHIND a letter, not a ring IN one. Cropping is safe here and
     only here, because the counter is 0.84:1 against a 0.75:1 source — 6% off
     the top and 6% off the bottom of a centred cut-out. */
  width:calc(var(--gw) * var(--cw));
  height:calc(var(--gh) * var(--cth));
  top:calc(var(--g-top) + var(--gh) * var(--ay));
  inset-inline-start:calc(var(--g-start) + var(--gw) * (1 - var(--ax)));
}
.seat--inside .seat__ph img{ height:100%; object-fit:cover; }
/* cut to the counter's own contour, not to its bounding box — see counterClip */
.seat--inside .seat__ph{ clip-path:url(#seat-counter); }
/* and a smaller bleed here: at 4.5% the frame ate half of ס's right stroke and
   the closed counter — the entire reason ס is the ring's letter — stopped
   reading as closed. */
.seat--inside{ --g-start:calc(var(--gw) * -0.015); }

.seat__info{ position:relative; z-index:3; padding-top:7vh;
  padding-inline-end:var(--rail); }

/* ── the standing bar ─────────────────────────────────────────────────────
   The home page's own .ship bar, on the product page, carrying the three facts
   a person actually needs before deciding: free delivery over ₪249, free
   collection at 89 branches, 14 days to cancel. They were a --t-meta paragraph
   buried under the button.

   It also fixes something measured. 8 of 11 jewelry sites in the corpus run
   content into BOTH frame edges; this template ran into neither, at content
   width 73.8% against a field median of 99%. And score-layout counted 8
   alignment edges here against a target of ≤4 — cropping the header away drops
   that to 2, i.e. the eight were the navigation's six links, spaced 65px apart
   against a 56px merge threshold. A rule that crosses the whole frame is the
   honest fix for both: it is the reason the home page scores 1. */
.seat__bar{
  grid-column:1 / -1; align-self:end;
  display:flex; flex-wrap:wrap; justify-content:space-between; gap:6px 34px;
  margin-top:34px; padding:14px var(--rail);
  border-top:1px solid var(--c-line);
  font-size:var(--t-meta); color:var(--c-ink-muted);
}
.seat__bar a{ border-bottom:1px solid var(--c-line); }
.seat__bar a:hover{ border-bottom-color:var(--c-ink); }
@media (max-width:900px){
  .seat__bar{ margin-top:22px; padding-inline:0; gap:4px 18px; }
}
/* The price at display scale. CONCEPT §Type brief 9: "ספרות אמיתיות — המחירים
   הם העסק." In a system with no red, no badge and no timer — all three on the
   kill list — scale is the only instrument left to say which number decides,
   and this is the number the page exists to make a person answer.
   ⚠ It carries the markdown WITHOUT becoming a poster about the markdown: the
   struck former price stays at --t-meta and the percentage stays in a sentence.
   The variant that set the price at this size with no ink behind it (v7) read
   as a discount flyer and was rejected on exactly that. */
.seat__info .pdp__pr{
  font-size:var(--t-head); line-height:var(--lh-head);
  letter-spacing:var(--tr-head); margin:26px 0 0;
}
/* The name at --t-lead, not --t-sub. Product names here run to 84 characters
   and at 40px in a 420px column that is four ragged lines — measured on
   "עגילי חישוק ציפוי זהב קוטר 2 ס״מ". The hierarchy the page actually wants is
   plain: the letter says which shelf, the photograph says which piece, the
   NAME identifies it and the PRICE is the question. 24px at wght 600 against
   92px is a 3.8× jump, and both sizes are already in the six the system
   allows — no seventh size was cut to make this fit. */
.seat__info .pdp__title{
  font-size:var(--t-lead); line-height:var(--lh-lead); margin:0 0 4px;
  letter-spacing:0;
}
.seat__info .pdp__add{ margin-top:30px; }
/* At 92px the struck former price can no longer sit on the same baseline —
   measured, the two numbers overlapped. It goes under, where it reads as what
   it is: the price this replaced. */
.seat__info .pdp__was{ display:block; margin:6px 0 0; margin-inline-start:0; }
@media (max-width:900px){
  .seat__info .pdp__pr{ font-size:var(--t-sub); }
}

@media (max-width:900px){
  /* On a phone the letter cannot both bleed and hold: at 375px a 52vw glyph is
     195px and the seat lands off-frame. It becomes a band the photograph hangs
     under — the same relation, one dimension flatter. Checked at 375 as this
     was built, not after. */
  .seat{ grid-template-columns:minmax(0,1fr); gap:0; margin-inline-start:0;
    padding-top:0; --gh:32vh; }
  .seat__field{ min-height:0; overflow:visible; }
  .seat__g{ position:relative; top:0; inset-inline-start:auto;
    height:var(--gh); width:auto; max-width:74vw; margin-inline-start:-9vw;
    display:block; }
  .seat--hang .seat__ph,.seat--rest .seat__ph,.seat--inside .seat__ph{
    position:relative; top:auto; inset-inline-start:auto; transform:none;
    width:100%; margin-top:-7vh; }
  .seat__info{ padding-top:26px; }
}

/* ── the product page ────────────────────────────────────────────────────
   Gallery on the START edge — the right, in RTL — because that is where
   .pers__rig already puts the piece and .gold__rig already puts the stage.
   The information column is sticky against a gallery of two or three tall
   photographs, so the price and the button never scroll away from the piece
   they belong to. */
.pdp{ display:grid; grid-template-columns:minmax(0,1fr) 400px; gap:0 64px;
  align-items:start; padding-top:34px; }
.pdp__gal{ display:grid; gap:var(--gut); }
.pdp__info{ position:sticky; top:28px; }

/* The photograph, seated ON the paper rather than floating over it — same
   multiply + brightness pair as .cat__ph in craft.css, so a product shot is
   the same material at 1,120px as it is at 460. */
.pdp__ph{ position:relative; overflow:hidden; background:var(--c-paper-deep); margin:0; }
.pdp__ph img{ width:100%; height:auto; mix-blend-mode:multiply; filter:brightness(1.1); }
/* PULSE LAW. The catalogue's own wave, on the piece itself: pure CSS, so the
   page still has 0.2%+ of its pixels moving at rest with JavaScript off — and
   under `reduce` the streak is parked, not deleted, exactly as craft.css does
   it for the grid. --sheen-photo, because the photograph already carries its
   own key and ours only assists. */
.pdp__ph::after{
  content:""; position:absolute; inset:-30% -70%; pointer-events:none; z-index:2;
  background:linear-gradient(var(--az),
    transparent 33%, var(--sheen-shade) 43%,
    var(--sheen-photo) 51%, transparent 61%);
  opacity:0; transform:translate3d(-52%,0,0);
}
@media (prefers-reduced-motion:no-preference){
  .pdp__ph::after{ animation:mg-cross var(--travel) linear infinite; }
  .pdp__gal figure:nth-child(2) .pdp__ph::after{ animation-delay:-4.33s; }
  .pdp__gal figure:nth-child(3) .pdp__ph::after{ animation-delay:-8.66s; }
}
@media (prefers-reduced-motion:reduce){
  .pdp__ph::after{ animation:none; opacity:.85; transform:translate3d(-4%,0,0); }
}

.pdp__sku{ display:block; font-size:var(--t-meta); color:var(--c-ink-muted); margin:0 0 14px; }
.pdp__title{
  font-family:"Magnolia Display","Magnolia",sans-serif;
  font-size:var(--t-sub); line-height:var(--lh-sub); letter-spacing:-0.01em;
  font-weight:var(--w-strong); font-variation-settings:'wght' 600;
  margin:0 0 20px;
}
.pdp__pr{ margin:0; font-size:var(--t-sub); font-variation-settings:'wght' 600;
  font-weight:var(--w-strong); }
/* Never in red. Red is the signal of a discount site and it is retired from
   this system — the markdown is carried by the strike and by the word. */
.pdp__was{ font-size:var(--t-meta); color:var(--c-ink-muted); font-weight:var(--w-body);
  font-variation-settings:'wght' 400; text-decoration:line-through; margin-inline-start:12px; }
.pdp__valid{ margin:8px 0 0; font-size:var(--t-meta); color:var(--c-ink-muted); }

.pdp__add{
  display:block; width:100%; margin:26px 0 0; font:inherit; font-size:var(--t-body);
  font-variation-settings:'wght' 600; cursor:pointer; text-align:center;
  background:var(--c-ink); color:var(--c-ground);
  border:0; border-radius:0; padding:15px;
  transition:background var(--d-settle) var(--e-answer);
}
.pdp__add:hover{ background:var(--c-ink-deep); transition-duration:var(--d-answer); }
.pdp__out{ margin:26px 0 0; border-top:1px solid var(--c-ink); padding-top:14px;
  font-size:var(--t-body); }
.pdp__out b{ font-weight:var(--w-strong); font-variation-settings:'wght' 600; }
.pdp__note{ margin:14px 0 0; font-size:var(--t-meta); color:var(--c-ink-muted); line-height:1.5; }
.pdp__note a{ border-bottom:1px solid var(--c-line); }
.pdp__note a:hover{ border-bottom-color:var(--c-ink); }
.pdp__desc{ margin:0; line-height:var(--lh-body); }

/* the attribute table — .kv is legal.css's, narrowed for a 400px column */
.pdp__info .kv div{ grid-template-columns:118px minmax(0,1fr); gap:0 16px; }

/* ── personalisation ─────────────────────────────────────────────────────
   Every label, every character limit and every surcharge below is printed
   verbatim from the product's own published option set. Nothing is inferred:
   the store's own wording disagrees with itself across SKUs (7 characters
   here, 8 there, +₪10 / +₪30 / +₪80), and normalising that would mean
   choosing a number the customer would be held to. */
.pers__fields{ margin:22px 0 0; }
.pers__f{ margin:0 0 18px; border:0; padding:0; }
.pers__f .pers__label{ margin-bottom:6px; }
.pers__f .pers__input{ font-size:var(--t-body); }
.pers__max{ display:block; margin-top:6px; font-size:var(--t-meta); color:var(--c-ink-muted); }
.pers__pick{
  width:100%; font:inherit; font-size:var(--t-body); color:var(--c-ink);
  background:transparent; border:0; border-bottom:1px solid var(--c-ink);
  border-radius:0; padding:8px 0; appearance:none;
}
.pers__pick:focus{ outline:0; border-bottom-width:2px; }

/* ── related ─────────────────────────────────────────────────────────────
   Four pieces from the same sub-category. The rail exists so every product in
   the catalogue is reachable from every other one — an orphan product page is
   a page no crawler and no visitor ever arrives at. */
/* The LAST content section before the footer, and therefore the one that
   decides whether the invention continued or the page quietly became a normal
   website below the fold. It carries the shelf's letter at --t-head, so the
   final thing a visitor passes is still made of the same idea as the first. */
.shop__h--letter{ display:flex; align-items:baseline; gap:22px; }
.shop__h-l{
  font-family:"Magnolia Display","Magnolia",sans-serif;
  font-size:var(--t-head); line-height:.8; font-weight:var(--w-display);
  font-variation-settings:'wght' 400; letter-spacing:var(--tr-head);
  margin-inline-start:-0.06em;
}
.shop__rail{ display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:38px var(--gut); }
@media (max-width:900px){ .shop__h--letter{ gap:14px; } }

/* ── mobile: checked at 375 as this was built, not after ─────────────────── */
@media (max-width:900px){
  .pdp{ grid-template-columns:minmax(0,1fr); gap:34px; padding-top:20px; }
  /* Sticky is wrong on a phone: the information column IS the next screen. */
  .pdp__info{ position:static; }
  .pdp__title{ font-size:var(--t-lead); }
  .shop__rail{ grid-template-columns:repeat(2,minmax(0,1fr)); gap:26px 16px; }
  .shop__s{ padding-top:44px; margin-top:52px; }
  .shop__sort{ margin-inline-start:0; }
  .pager__of{ margin-inline-start:0; width:100%; }
}
