/* ═══════════════════════════════════════════════════════════════════════
   FIDA — SHOP
   The public page AND the builder's preview both load this file. That is the
   whole point: one stylesheet renders the blocks, so what FIDA arranges in the
   panel is literally the same DOM under the same rules as what a visitor gets.
   Nothing here may be builder-only, and nothing in builder.css may style a
   block — if a rule leaks the wrong way, WYSIWYG quietly stops being true.

   Unlike every other public page this one is FLUID, not a 1440 artboard under
   transform:scale(). It has to be: there is no Figma frame for a page whose
   content does not exist yet. It keeps the design's vocabulary — her palette,
   her five faces, her hairlines and 3px radii — and lays them out responsively.
   ═══════════════════════════════════════════════════════════════════════ */

*,*::before,*::after{box-sizing:border-box}
html,body{margin:0;padding:0}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
a{color:inherit;text-decoration:none}
img,video{max-width:100%;display:block}
h1,h2,h3,p,figure{margin:0}

:root{
  --ink:#000000;
  --lilac:#ddd2f0;
  --lilac-logo:#ded1f2;
  --white:#ffffff;
  --page:#181717;

  --ff-sans:'Inter',sans-serif;
  --ff-display:'Pujarelah',serif;
  --ff-name:'Romelu Vomelu',serif;
  --ff-script:'Edwardian Script ITC',cursive;
  /* Identical to main.css — see the long note there. Short version: Miller
     Banner ROMAN is what the design names and no Roman file exists, so
     Playfair Display stands in at +0.4% of her width. The Extra Compressed
     cut is deliberately NOT here: it is 47% narrower and is what FIDA saw as
     the wrong font. */
  --ff-banner:'Miller Banner','Playfair Display',serif;

  --img-logo-nav:url('../assets/img/fida-logo-nav.svg');
  --img-logo-footer:url('../assets/img/fida-logo-footer.png');

  --shop-pad:clamp(18px, 5vw, 64px);
  --line:rgba(221,210,240,.18);
}

body{background:var(--page);color:var(--white);font:400 calc(16px * var(--fs))/1.6 var(--ff-sans)}

/* ── the chrome ────────────────────────────────────────────────────────
   shop.html carries the site's REAL .sec-nav and .sec-footer, so main.css
   already styles both and main.js already gives the navbar its drop-in panel.
   Only two things need saying here.

   One: the fixed navbar overlaps the top of the page by its own height,
   exactly as it does everywhere else — so the first block needs that much
   clearance or the cover's title sits under the menu. That height is --barh
   now, REAL screen pixels at every width, so the clearance is the same number
   and no longer scales. Leaving the old scaled 101.5 here would open a gap
   above the cover on a wide window.

   Two: the footer lives in a .stage of its own that holds nothing else, so it
   needs no offset — --stage-h on <html> is its height and no more. */
.shop-body .sh-page{padding-top:var(--barh)}
/* a cover is a full-bleed band and swallows the offset into its own height,
   which is what keeps the bar sitting ON the photograph as it does on ABOUT */
.shop-body .sh-page > .blk-cover:first-child{
  margin-top:calc(0px - var(--barh));
  padding-top:var(--barh);
}

@media (max-width:1023.98px){
  /* mobile.js builds its own .m-head and mobile.css hides .navwrap, so the
     desktop bar's clearance has to go with it */
  .shop-body .sh-page{padding-top:0}
  .shop-body .sh-page > .blk-cover:first-child{margin-top:0;padding-top:0}
}

/* ── chrome · the nav and footer, in her language ──────────────────────
   Hand-built rather than lifted from main.css, because that navbar is an
   absolutely-positioned row inside the scaled artboard and would not survive
   out here. Same palette, same wordmark file, same hairline. */
.sh-nav{
  position:sticky;top:0;z-index:50;background:var(--ink);
  border-bottom:1px solid var(--line);
}
.sh-nav-in{
  max-width:1440px;margin:0 auto;padding:0 var(--shop-pad);
  height:78px;display:flex;align-items:center;justify-content:space-between;gap:20px;
}
.sh-logo{
  display:block;width:118px;aspect-ratio:1898 / 385;flex:none;
  background-color:var(--lilac-logo);
  -webkit-mask:var(--img-logo-nav) center/contain no-repeat;
          mask:var(--img-logo-nav) center/contain no-repeat;
}
.sh-links{display:flex;align-items:center;gap:clamp(14px,2.4vw,34px)}
.sh-links a{
  font:400 calc(15px * var(--fs))/1 var(--ff-sans);color:var(--lilac);opacity:.85;
  transition:opacity .16s ease;
}
.sh-links a:hover,.sh-links a[aria-current="page"]{opacity:1}
.sh-links a[aria-current="page"]{text-decoration:underline;text-underline-offset:6px}

.sh-burger{display:none;width:40px;height:40px;flex-direction:column;
  justify-content:center;gap:5px;padding:0 8px;background:none;border:0;cursor:pointer}
.sh-burger span{display:block;height:1.5px;background:var(--lilac);
  transition:transform .25s ease,opacity .25s ease}
.sh-burger[aria-expanded="true"] span:nth-child(1){transform:translateY(6.5px) rotate(45deg)}
.sh-burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.sh-burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-6.5px) rotate(-45deg)}

.sh-foot{
  border-top:1px solid var(--line);background:var(--ink);
  padding:46px var(--shop-pad) 38px;text-align:center;
}
.sh-foot .sh-logo{width:230px;margin:0 auto 26px;background-color:var(--lilac);
  -webkit-mask-image:var(--img-logo-footer);mask-image:var(--img-logo-footer);
  aspect-ratio:1898 / 385}
.sh-foot-links{display:flex;flex-wrap:wrap;gap:18px 28px;justify-content:center;
  font:400 calc(14px * var(--fs))/1 var(--ff-sans);color:var(--lilac);opacity:.85}
.sh-copy{margin-top:26px;font:400 calc(13px * var(--fs))/1 var(--ff-sans);color:rgba(255,255,255,.45)}

/* ═══════════════════════════════════════════════════════════════════════
   THE BLOCKS
   Every block is <section class="blk blk-TYPE"> with inline custom properties
   written by the renderer. Layout lives here; the per-block CHOICES (font,
   size, colour, alignment, spacing) arrive as CSS variables, so one rule set
   serves every instance and the saved document stays small, declarative and
   inspectable — no generated stylesheet, no !important war.
   ═══════════════════════════════════════════════════════════════════════ */
.sh-page{min-height:40vh}

.blk{
  padding:var(--blk-pt,34px) var(--shop-pad) var(--blk-pb,34px);
  background:var(--blk-bg,transparent);
}
.blk-in{
  max-width:var(--blk-max,1100px);margin:0 auto;width:100%;
  text-align:var(--blk-align,left);
}

/* ── the cover ─────────────────────────────────────────────────────────
   Her hero band, made adjustable. Every other page opens with one photograph
   at 15% over a solid ground with the title centred on it — that ratio is why
   the type stays readable over any picture, and why the photo is its own
   layer here rather than a background on the section: the opacity has to
   land on the picture and not on the words.                              */
.blk-cover{
  position:relative;overflow:hidden;padding:0;
  min-height:var(--blk-h,440px);
  background:var(--blk-ground,var(--ink));
  display:grid;place-items:center;
}
.blk-cover > i{
  position:absolute;inset:0;display:block;
  background-position:var(--blk-pos,center);
  background-size:cover;background-repeat:no-repeat;
  opacity:var(--blk-op,.15);
}
.blk-cover .blk-in{position:relative;z-index:1;padding:40px var(--shop-pad)}
.blk-cover-in{display:flex;flex-direction:column;gap:14px;
  align-items:var(--blk-ai,center)}
.blk-cover[style*="--blk-align:left"] .blk-cover-in{--blk-ai:flex-start}
.blk-cover[style*="--blk-align:right"] .blk-cover-in{--blk-ai:flex-end}
.blk-kicker{
  font:500 calc(11px * var(--fs))/1 var(--ff-sans);letter-spacing:.28em;text-transform:uppercase;
  color:var(--lilac);opacity:.9;
}
.blk-cover-t{
  font-family:var(--blk-ff,var(--ff-display));
  font-size:calc((var(--blk-fs,72px)) * var(--fs));
  font-weight:var(--blk-fw,400);
  line-height:var(--blk-lh,1.08);
  letter-spacing:var(--blk-ls,0);
  color:var(--blk-color,var(--white));
}
.blk-cover-s{
  max-width:56ch;font:300 calc(17px * var(--fs))/1.6 var(--ff-sans);
  color:rgba(255,255,255,.78);
}

/* text-ish blocks — one rule, driven entirely by variables */
.blk-heading .blk-in,
.blk-text .blk-in{
  font-family:var(--blk-ff,var(--ff-display));
  font-size:calc((var(--blk-fs,40px)) * var(--fs));
  font-weight:var(--blk-fw,400);
  line-height:var(--blk-lh,1.25);
  letter-spacing:var(--blk-ls,0);
  color:var(--blk-color,var(--white));
}
.blk-text .blk-in{white-space:pre-wrap}   /* her line breaks survive verbatim */

/* picture / motion — figure so a caption is native, not bolted on */
.blk-media figure{margin:0}
.blk-media img,.blk-media video{
  width:100%;height:var(--blk-h,auto);
  object-fit:var(--blk-fit,cover);
  border-radius:var(--blk-radius,0);
  margin-inline:auto;
  max-width:var(--blk-mw,100%);
}
.blk-media figcaption{
  margin-top:10px;font:400 calc(13px * var(--fs))/1.5 var(--ff-sans);
  color:rgba(255,255,255,.55);text-align:var(--blk-align,left);
}

/* the rule — her 1px lilac hairline, thickness and width made adjustable */
.blk-divider hr{
  border:0;height:var(--blk-th,1px);background:var(--blk-color,var(--lilac));
  width:var(--blk-w,100%);opacity:var(--blk-op,.5);
  margin-inline:var(--blk-mi,0);
}

.blk-spacer{padding:0;height:var(--blk-h,48px)}

/* ══ THE BUTTON · four designs FIDA picks between ══════════════════════
   Two are her own, lifted off the artboard. Two were designed for the shop
   and are not on the artboard anywhere.

     Pill      .btn/.btn-lilac  — the 40px capsule, her signature control:
                                  16 of the artboard's 33 button instances
     Hairline  .pill-outline    — the 15px capsule with a .5px lilac stroke
     Plate     new              — a catalogue entry: her serif, a marginal
                                  rule, a leader that draws out
     Sweep     new              — her hairline lilac used as a SURFACE with
                                  a spine, ink flooding across it

   ── ONE RULE EVERY DESIGN OBEYS ────────────────────────────────────────
   No position, transform, filter, backdrop-filter, perspective, contain or
   will-change on .sh-btn in ANY state. On a product card an ::after is
   stretched from the card to make the whole thing clickable, and it finds
   its containing block by walking up to the nearest positioned ancestor.
   Any of those properties makes the BUTTON that ancestor, and the click
   target silently collapses from the whole card down to the button — the
   exact bug we already fixed once. Motion here is background-size only.

   ── AND ONE THAT IS EASY TO MISS ───────────────────────────────────────
   The reduced-motion block at the foot of this file says `.sh-btn{
   transition:none}`, which is (0,1,0) and LOSES to `.sh-btn.is-x` at
   (0,2,0). So a design that declares its own transition must also declare
   its own reduced-motion block, or it keeps animating for someone who
   asked it not to. Pill and Hairline declare no transition and inherit the
   base's, which the blanket does still switch off.                      */
.blk-button .blk-in{display:flex;justify-content:var(--blk-jc,flex-start)}
.sh-btn{
  display:inline-flex;align-items:center;gap:10px;
  padding:13px 30px;border-radius:3px;
  font:600 calc(15px * var(--fs))/1 var(--ff-sans);cursor:pointer;
  transition:opacity .16s ease;
}
.sh-btn:hover{opacity:.85}

/* ── Pill · hers ──────────────────────────────────────────────────────
   main.css:255-256. Always radius 40, always a flat fill, and on a black
   page the lilac colourway is the readable one — .btn-black would be a
   black capsule on black. */
.sh-btn.is-pill{
  background:var(--lilac);color:var(--ink);
  border-radius:40px;padding:14px 34px;
}

/* ── Hairline · hers ──────────────────────────────────────────────────
   main.css:258,265. The only non-40px capsule she draws, and the only
   half-pixel lilac stroke. Drawn as an inset shadow rather than a border
   so it costs no layout and cannot shift anything on hover. */
.sh-btn.is-hairline{
  background:transparent;color:var(--lilac);
  border-radius:15px;
  box-shadow:inset 0 0 0 .5px var(--lilac);
}

/* ── Plate · a catalogue entry ────────────────────────────────────────
   Her display serif held to a 1px lilac rule on the left margin, with her
   own arrow trailing the words. On hover the ground washes in from that
   rule and the arrow travels.

   THE LABEL NEVER CHANGES COLOUR. A flood that also flipped the text would
   put lilac-on-lilac on screen for the length of the wipe — illegible
   exactly while it moves. So the ground is --line, lilac at 18%, and the
   words stay lilac throughout.

   Setting a button in her serif is precedented rather than invented:
   main.css:180 already sets .f-p16m at 500 16px var(--ff-display). */
.sh-btn.is-plate{
  gap:12px;
  padding:13px 20px 13px 17px;
  border-radius:0;                    /* a rule, not a chip */
  background:
    linear-gradient(var(--lilac),var(--lilac)) left top / 1px 100% no-repeat,
    linear-gradient(var(--line),var(--line))   left top / 0    100% no-repeat;
  color:var(--lilac);
  font:500 calc(16px * var(--fs))/1.4 var(--ff-display);
  letter-spacing:.005em;
  transition:background-size .42s cubic-bezier(.22,.61,.36,1);
}
/* HER ARROW, not a dash. The first draft trailed the words with a drawn
   rule; FIDA looked at it and asked for a proper flèche. She already owns
   one — assets/img/arrow-explore.svg, Figma "Arrow 1", exported from its
   real strokeGeometry with the chevron head — and it is what the ten
   "Explore Project" links on HOME and PORTFOLIO already use. Masking it
   with currentColor is exactly how main.css:250 draws it, so it recolours
   with the label instead of being a second colour to keep in step.

   14.5 x 7.364 is its absoluteRenderBounds, NOT its bounding box: the box
   is 14 x 0 because a stroked line has no height, and using it would hide
   the arrow completely. See the note at main.css:241.

   --arrow is declared in main.css, which shop.html loads but admin-shop.html
   does NOT — so the picker in the builder would have shown an empty gap
   where the arrow should be. The literal url is the fallback, which makes
   this rule work in both without adding a stylesheet to the admin page.

   order:1 puts this ::before AFTER the words. ::before is the only free
   pseudo-element: ::after is the card's stretched hit area. The transform
   below is on the PSEUDO, never on .sh-btn — a transform on the button
   itself would capture that hit area and collapse it onto the button. */
.sh-btn.is-plate::before{
  content:'';order:1;flex:none;
  width:14.5px;height:7.364px;
  background-color:currentColor;
  -webkit-mask:var(--arrow,url('../assets/img/arrow-explore.svg')) left center/contain no-repeat;
          mask:var(--arrow,url('../assets/img/arrow-explore.svg')) left center/contain no-repeat;
  transition:transform .42s cubic-bezier(.22,.61,.36,1);
}
.sh-btn.is-plate:hover,
.sh-btn.is-plate:focus-visible,
.sh-card.is-link:hover .sh-btn.is-plate{
  opacity:1;                          /* cancels the blanket hover dim */
  background-size:1px 100%, 100% 100%;
}
/* the arrow travels, the way it wants to on a link that leads somewhere */
.sh-btn.is-plate:hover::before,
.sh-btn.is-plate:focus-visible::before,
.sh-card.is-link:hover .sh-btn.is-plate::before{transform:translateX(5px)}
.sh-btn.is-plate:focus-visible{outline:2px solid var(--lilac);outline-offset:4px}
@media (prefers-reduced-motion:reduce){
  .sh-btn.is-plate,.sh-btn.is-plate::before{transition:none}
}

/* ── Sweep · the page floods in ───────────────────────────────────────
   Her hairline lilac used as a SURFACE instead of a stroke — --line is
   literally the value that draws every rule on this page — with a 2px
   lilac spine down the left edge. On hover ink sweeps across from that
   spine and the plate becomes a hole cut in the page, the spine and the
   label left on black.

   The first-listed background layer paints ON TOP, which is what lets the
   spine survive the flood. Only background-size animates. */
.sh-btn.is-sweep{
  background-color:var(--line);
  background-image:linear-gradient(var(--lilac),var(--lilac)),   /* the spine */
                   linear-gradient(var(--ink),var(--ink));       /* the flood */
  background-repeat:no-repeat;
  background-position:left center;
  background-size:2px 100%, 0% 100%;
  color:var(--lilac);
  transition:background-size .42s cubic-bezier(.22,.61,.36,1);
}
.sh-btn.is-sweep:hover,
.sh-btn.is-sweep:focus-visible,
.sh-card.is-link:hover .sh-btn.is-sweep{
  opacity:1;
  background-size:2px 100%, 100% 100%;
}
.sh-btn.is-sweep:focus-visible{outline:2px solid var(--lilac);outline-offset:4px}
@media (prefers-reduced-motion:reduce){
  .sh-btn.is-sweep{transition:none}
}

/* ── Star · hers, the "Let's Talk" button on HOME ─────────────────────
   index.html:191 — a 40px capsule with no fill, her star ornament inside it
   beside the label, and the star ANIMATES on hover: main.css:763 scales it
   .577 -> .797 -> .577 over .36s. That movement is the whole character of
   the button and it is why she asked for this one by name.

   Two things had to be carried rather than referenced. --spark and the
   spark-zoom keyframes both live in main.css, which shop.html loads and
   admin-shop.html does NOT — so the star would have been an empty gap in the
   builder while working on the live page. The mask carries the literal path
   as a fallback and the animation is declared here under its own name.

   Her version is a black stroke on white. On the shop's dark ground that
   would be invisible, so it takes the lilac colourway — the same adaptation
   Pill makes, and the same one .pill-outline already makes on her own black
   WHAT I CREATE band. */
.sh-btn.is-star{
  background:transparent;color:var(--lilac);
  border-radius:40px;padding:13px 28px;gap:11px;
  box-shadow:inset 0 0 0 1px var(--lilac);
  letter-spacing:.18px;                    /* her .lsp */
}
.sh-btn.is-star::before{
  content:'';flex:none;width:26px;height:26px;margin:0 -5.5px;
  background-color:currentColor;
  -webkit-mask:var(--spark,url('../assets/img/star-ornament.svg')) center/contain no-repeat;
          mask:var(--spark,url('../assets/img/star-ornament.svg')) center/contain no-repeat;
  transform:scale(.577);                   /* 26 x .577 = her 15px */
}
@keyframes sh-spark{
  0%,100% { transform:scale(.577) }
  50%     { transform:scale(.797) }
}
.sh-btn.is-star:hover::before,
.sh-btn.is-star:focus-visible::before,
.sh-card.is-link:hover .sh-btn.is-star::before{
  animation:sh-spark .36s ease-in-out;
}
.sh-btn.is-star:hover,
.sh-card.is-link:hover .sh-btn.is-star{ opacity:1 }
.sh-btn.is-star:focus-visible{outline:2px solid var(--lilac);outline-offset:4px}
@media (prefers-reduced-motion:reduce){
  .sh-btn.is-star::before{animation:none !important}
}

/* ── White · hers, the SUBMIT button on CONTACT ───────────────────────
   contact.css:238 — white, 3px radius, and set in Romelu Vomelu italic at
   15px/16.55. Black text on white, which is what she asked for, and the only
   button on the site that uses that face. The italic is the point: it is
   what stops a white rectangle reading as a default browser button. */
.sh-btn.is-white2{
  background:var(--white);color:var(--ink);
  border-radius:3px;padding:13px 26px;
  font:italic 400 calc(15px * var(--fs))/16.55px var(--ff-name);
}
.sh-card .sh-btn.is-white2{padding:11px 20px;font-size:calc(14px * var(--fs))}

/* ── the three names that came before ─────────────────────────────────
   The renderer has no whitelist — whatever string is in the saved JSON
   becomes a class — so a page built before the four designs existed keeps
   whatever it was given. Deleting these would not raise an error; it would
   quietly render an unstyled button on work FIDA has already made.

   Nothing in the site emits these any more — the dead-link page in shop.html
   was the last one and now asks for is-pill. They are here purely for saved
   pages, and can go once none of them uses one. */
.sh-btn.is-lilac{background:var(--lilac);color:var(--ink)}
.sh-btn.is-white{background:var(--white);color:var(--ink)}
.sh-btn.is-outline{background:transparent;color:var(--lilac);box-shadow:inset 0 0 0 1px var(--lilac)}

/* ── the product · what a shop page is actually for ──────────────────── */
.blk-products .sh-grid{
  display:grid;gap:clamp(18px,2.6vw,34px);
  grid-template-columns:repeat(var(--blk-cols,3),minmax(0,1fr));
}
.sh-card{display:flex;flex-direction:column;gap:12px;text-align:left}

/* ── a product that leads somewhere is clickable ANYWHERE ─────────────
   The button alone was not enough: people click the photograph, and when
   nothing happens the product reads as broken. The card's own anchor is
   stretched over it, so the whole thing is one target — photo, name, price
   and all — while the button keeps its text for anyone reading the page
   aloud. position:relative on the card is what the stretch is measured
   against, so it must stay. */
.sh-card.is-link{position:relative;cursor:pointer}
.sh-card .sh-btn.is-stretched::after{
  content:'';position:absolute;inset:0;z-index:1;
  /* SQUARE, deliberately. This used to be border-radius:inherit, which was
     harmless while every button was 3px — but it inherits from the BUTTON,
     and Pill is a 40px capsule, so the hit area was being drawn as a
     40px-rounded rectangle over a square card and each corner lost a bite
     roughly 12px deep. The card looks rectangular, so it must be clickable
     rectangular. Nothing is painted here, so the radius only ever affected
     hit-testing; the focus ring is drawn on .sh-card, not on this. */
  border-radius:0;
}
/* the photograph answers the pointer, so the card does not look inert */
.sh-card.is-link .sh-card-img{transition:transform .35s cubic-bezier(.22,.61,.36,1),
                                         opacity .25s ease}
.sh-card.is-link:hover .sh-card-img{transform:scale(1.03);opacity:.92}
.sh-card.is-link:hover .sh-btn{opacity:.85}
/* keyboard users get the same outline the rest of the site uses, drawn on
   the CARD rather than on the invisible stretched area */
.sh-card.is-link:focus-within{outline:2px solid var(--lilac);outline-offset:6px}
.sh-card .sh-btn.is-stretched:focus-visible{outline:none}

@media (prefers-reduced-motion:reduce){
  .sh-card.is-link .sh-card-img{transition:none}
  .sh-card.is-link:hover .sh-card-img{transform:none}
}
.sh-card-img{
  width:100%;aspect-ratio:var(--blk-ar,1 / 1);object-fit:cover;
  border-radius:var(--blk-radius,6px);background:#242121;
}
.sh-card-name{font:400 calc(21px * var(--fs))/1.25 var(--ff-display);color:var(--white)}
.sh-card-price{font:600 calc(15px * var(--fs))/1 var(--ff-sans);color:var(--lilac)}
.sh-card-note{font:300 calc(14px * var(--fs))/1.55 var(--ff-sans);color:rgba(255,255,255,.6)}
.sh-card .sh-btn{align-self:flex-start;margin-top:4px;padding:10px 22px;font-size:calc(14px * var(--fs))}
/* `.sh-card .sh-btn` is (0,2,0) — the SAME weight as `.sh-btn.is-plate`, and
   it comes later, so on a product card it silently took Plate's asymmetric
   padding and its serif size away. Restated at (0,3,0) to win the tie back.
   The other three designs want the card's smaller sizing and say nothing. */
.sh-card .sh-btn.is-plate{padding:11px 18px 11px 15px;font-size:calc(15px * var(--fs));margin-top:6px}
/* Pill carries the most padding of the four, and 34px reads as oversized
   under a card photo where the button is one element among four. */
.sh-card .sh-btn.is-pill{padding:11px 26px}

/* ── the gallery ─────────────────────────────────────────────────────── */
.blk-gallery .sh-grid{
  display:grid;gap:var(--blk-gap,14px);
  grid-template-columns:repeat(var(--blk-cols,3),minmax(0,1fr));
}
.blk-gallery img{width:100%;aspect-ratio:var(--blk-ar,1 / 1);object-fit:cover;
  border-radius:var(--blk-radius,4px)}

/* ── phone ───────────────────────────────────────────────────────────── */
@media (max-width:820px){
  .sh-nav-in{height:64px}
  .sh-burger{display:flex}
  .sh-links{
    position:fixed;inset:64px 0 auto;flex-direction:column;align-items:stretch;
    gap:0;background:var(--ink);border-bottom:1px solid var(--line);
    padding:10px var(--shop-pad) 24px;
    transform:translateY(-120%);transition:transform .3s ease;
  }
  .sh-links.open{transform:translateY(0)}
  .sh-links a{padding:14px 0;font-size:17px}

  /* Her columns collapse rather than shrink: three 300px cards squeezed into
     a 375px screen is unreadable, and a product photo is the thing being
     sold. Two across for a gallery, one for a product. */
  .blk-products .sh-grid{grid-template-columns:1fr}
  .blk-gallery .sh-grid{grid-template-columns:repeat(min(var(--blk-cols,3),2),minmax(0,1fr))}
  .blk{padding-top:calc(var(--blk-pt,34px) * .7);padding-bottom:calc(var(--blk-pb,34px) * .7)}
  /* the cover keeps its own padding — it is a band, not a content block */
  .blk-cover{padding:0;min-height:max(300px, calc(var(--blk-h,440px) * .74))}
  .blk-cover-t{font-size:max(30px, calc(var(--blk-fs,72px) * .52))}
  .blk-cover-s{font-size:15px}
  /* type scales down proportionally, floored so nothing becomes unreadable */
  .blk-heading .blk-in{font-size:max(22px, calc(var(--blk-fs,40px) * .66))}
  .blk-text .blk-in{font-size:max(14px, calc(var(--blk-fs,17px) * .92))}
}

@media (prefers-reduced-motion:reduce){
  .sh-links,.sh-burger span,.sh-btn{transition:none}
}
