/* The shop (index.html): an exhibition catalogue for a booth of fan-made goods, built for a phone first.
   Paper and ink, a serif for what is displayed large and the app's sans for everything read small. Pages
   and sections are numbered like a booth's list (CSS counters), products carry their code, and an order
   number is a ticket stub to show at the booth.
   Saffron (--buy, --buy-ink text, --buy-deep pressed) is the colour of shopping: everything that buys or checks
   out (Add to cart, Check out, Send order, the cart once it holds something, Reserve online) and the order a
   visitor holds while it waits. The + of a card is frosted until hovered or in the cart. What buys nothing
   (Done, Keep shopping, Back) is a soft neutral pill; blue, the staff pages' colour, never shows here.
   The paper-and-ink colours come from base.css (--paper is the page). Buttons over pictures are frosted
   (see-through); the frost gets stronger on hover.
   Motion: things rise into view as they are scrolled to (where the browser ties animations to scrolling),
   dialogs rise and sheets slide up, a slide's dot fills while it waits, a picture flies into the cart, and a
   page turns: the line marking it slides there, the page shown lifts away and the new one's pieces rise in
   one after another (shop.js, turnPage); sideways on a phone, where the pages are tabs side by side. All of it
   stops for prefers-reduced-motion. */
:root{
  --paper:var(--bg);
  --buy:#F2C230;--buy-ink:#1C1606;--buy-deep:#E3AE14;
  --frost:rgba(255,253,249,.55);--frost-strong:rgba(255,253,249,.88);--frost-ink:#16140F;
  --frost-plain:rgba(22,20,15,.05);--frost-plain-strong:rgba(22,20,15,.09);
  --lift:0 1px 2px rgba(22,20,15,.08),0 10px 24px -10px rgba(22,20,15,.28);
  --float:0 2px 6px rgba(22,20,15,.06),0 28px 64px -20px rgba(22,20,15,.38);
  --ease:cubic-bezier(.2,.7,.2,1);--ease-out:cubic-bezier(.16,1,.3,1);
  /* The gap between columns of products and of tiles, so their columns line up; the side margin of the compact layout. */
  --gutter:clamp(14px,2.2vw,28px);--pad:clamp(16px,4vw,32px);
  /* Display type: the Latin serifs computers have, then a CJK serif for the reader's language (or its
     sans where no serif is installed: Windows' CJK serifs are not made for large sizes). */
  --cjk-serif:"Songti TC","Noto Serif TC","Noto Serif CJK TC","Source Han Serif TC","Microsoft JhengHei",serif;
  --font-display:"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",Georgia,var(--cjk-serif);
}
:root:lang(zh-CN){--cjk-serif:"Songti SC","Noto Serif SC","Noto Serif CJK SC","Source Han Serif SC","Microsoft YaHei",serif}
:root:lang(ja){--cjk-serif:"Hiragino Mincho ProN","Yu Mincho",YuMincho,"Noto Serif JP","Noto Serif CJK JP",serif}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --frost:rgba(27,25,22,.5);--frost-strong:rgba(27,25,22,.85);--frost-ink:#F1ECE3;
  --frost-plain:rgba(241,236,227,.06);--frost-plain-strong:rgba(241,236,227,.11);
  --lift:0 1px 2px rgba(0,0,0,.3),0 10px 24px -10px rgba(0,0,0,.6);
  --float:0 2px 6px rgba(0,0,0,.3),0 28px 64px -20px rgba(0,0,0,.8)}}
:root[data-theme="dark"]{
  --frost:rgba(27,25,22,.5);--frost-strong:rgba(27,25,22,.85);--frost-ink:#F1ECE3;
  --frost-plain:rgba(241,236,227,.06);--frost-plain-strong:rgba(241,236,227,.11);
  --lift:0 1px 2px rgba(0,0,0,.3),0 10px 24px -10px rgba(0,0,0,.6);
  --float:0 2px 6px rgba(0,0,0,.3),0 28px 64px -20px rgba(0,0,0,.8)}

body.shop{background:var(--paper);color:var(--ink);font-feature-settings:"kern";text-rendering:optimizeLegibility;-webkit-tap-highlight-color:transparent}
body.shop ::selection{background:var(--buy);color:var(--buy-ink)}
body.shop :focus-visible{outline:2px solid var(--focus);outline-offset:3px}
.shop .boot{padding-top:30vh;font:400 22px/1.2 var(--font-display);letter-spacing:.01em}
/* While the shop loads: the voxel of base.css's .mark, breathing. */
.shop .boot::before{content:"";display:block;width:30px;height:34px;margin:0 auto 20px;clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%);
  background:conic-gradient(from -60deg at 50% 50%,var(--voxel-lit) 0 120deg,var(--voxel-shade) 0 240deg,var(--voxel-face) 0);animation:drift 2.4s ease-in-out infinite}

/* Frosted glass: the blur that goes with a --frost background. */
.round,.sreserve,.cartfab,.bbtn{-webkit-backdrop-filter:blur(14px) saturate(1.4);backdrop-filter:blur(14px) saturate(1.4)}
/* Small capitals: codes, step numbers, labels over sections. */
.scode,.pcode,.howto h2,.sectitle::before,.langfield > span,.myorders h3{font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;font-variant-numeric:tabular-nums lining-nums}

/* ---------- buttons of the shop: pills, no outline ---------- */
.shop .btn{border:0;border-radius:var(--radius-pill);background:var(--frost-plain-strong);color:var(--ink);min-height:48px;padding:10px 22px;font-weight:600;letter-spacing:.01em;
  transition:background .25s var(--ease),transform .2s var(--ease-out),box-shadow .3s var(--ease),opacity .2s}
.shop .btn:active{transform:scale(.97)}
.shop .btn.sm{min-height:38px;padding:6px 16px}
.shop .btn.ghost{background:transparent}
.shop .btn.wide{display:flex;width:100%}
/* Saffron: what buys or checks out (2026-10-31), one button: Add to cart, Check out, Send order, Reserve online. In
   capitals, lifted with a sheen crossing it under the mouse, a shade deeper pressed; `.wide` fills its row (Add to cart
   with the price of the quantity at its end, `.buyprice`). */
.shop .btn.buy{position:relative;overflow:hidden;gap:10px;padding:10px 26px;background:var(--buy);color:var(--buy-ink);
  font-size:14px;font-weight:700;letter-spacing:.08em;text-transform:uppercase}
.shop .btn.buy::after{content:"";position:absolute;inset:0;background:linear-gradient(100deg,transparent 30%,rgba(255,255,255,.45) 50%,transparent 70%);transform:translateX(-100%);pointer-events:none}
.shop .btn.buy:active{background:var(--buy-deep);transform:scale(.98)}
.buyprice{margin-left:auto;font-variant-numeric:tabular-nums;letter-spacing:0;font-size:16px}
/* Hover looks only where there is a mouse: a tap leaves :hover on (2026-10-25). */
@media (hover:hover){
  .shop .btn:hover{background:color-mix(in srgb,var(--ink) 14%,transparent)}
  .shop .btn.ghost:hover{background:var(--frost-plain-strong)}
  .shop .btn.buy:hover:not(:disabled){background:var(--buy-deep);box-shadow:0 10px 28px -10px color-mix(in srgb,var(--buy) 80%,#000)}
  .shop .btn.buy:hover:not(:disabled)::after{transform:translateX(100%);transition:transform .9s var(--ease)}
}
/* A sheet's actions are one height: the pop-up's quantity and Add to cart (or Reserve online), the cart's Keep
   shopping and Check out, Back and Send order, Done. */
.sheetfoot .btn{min-height:54px}
.sheetfoot .qtypill{height:54px}
/* Round icon buttons (`round`): + on a card, × of a sheet, the arrows of pictures and rows. One shape and size (44px,
   a finger's), frosted and lifted; each says where it sits, its look on a picture or a row, and what it does on hover. */
.round{display:grid;place-items:center;width:44px;height:44px;padding:0;border:0;border-radius:50%;background:var(--frost-strong);color:var(--frost-ink);
  box-shadow:var(--lift);cursor:pointer}
.round .ico{width:20px;height:20px}
/* Quantity: one pill, − number + */
.qtypill{display:flex;align-items:center;justify-content:space-between;height:52px;padding:0 6px;border:0;border-radius:var(--radius-pill);background:var(--frost-plain-strong)}
.qtypill button{width:42px;height:42px;border:0;border-radius:50%;background:transparent;color:var(--ink);cursor:pointer;transition:background .2s,transform .15s var(--ease-out)}
.qtypill button:active{transform:scale(.88)}
@media (hover:hover){.qtypill button:hover:not(:disabled){background:var(--frost-plain-strong)}}
/* A + that can add no more (nothing further in stock) looks switched off. */
.qtypill button:disabled{opacity:.3;cursor:not-allowed;background:transparent}
.qtypill input{width:56px;min-width:0;border:0;background:transparent;color:var(--ink);text-align:center;font-size:17px;font-weight:600;font-variant-numeric:tabular-nums;-moz-appearance:textfield;appearance:textfield}
.qtypill input:focus-visible{outline-offset:0;border-radius:var(--radius-pic)}
.qtypill input::-webkit-inner-spin-button,.qtypill input::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}
.qtypill.sm{height:40px;padding:0 3px}
.qtypill.sm button{width:34px;height:34px}
.qtypill.sm input{width:36px;font-size:15px}
/* Headings break where their lines are balanced; text keeps more than one word on its last line. */
.sectitle,.banner .ov h2,.tcap h3,.shop .modal h2,.shopclosed h1,.shoppage .empty p,.shoplogo{text-wrap:balance}
.shop p,.ttext,.sline,.howsteps li{text-wrap:pretty}

/* ---------- the frame: the side column (name, search, pages) and the page ---------- */
.shopwrap{display:grid;grid-template-columns:236px minmax(0,1fr);gap:clamp(40px,5vw,80px);max-width:1480px;margin:0 auto;padding:0 clamp(28px,3.6vw,56px) 140px}
/* Room on its left for the line that marks the open page, which its scrolling would otherwise cut off. */
.side{position:sticky;top:0;align-self:start;display:flex;flex-direction:column;gap:30px;max-height:100dvh;overflow-y:auto;scrollbar-width:none;padding:48px 8px 32px 28px;margin:0 -8px 0 -28px}
.side::-webkit-scrollbar{display:none}
/* The name with its staff door under it. */
.shophead{display:flex;flex-direction:column;align-items:flex-start;gap:8px}
.shoplogo{font:400 32px/1.02 var(--font-display);letter-spacing:-.015em;color:var(--ink);text-decoration:none;overflow-wrap:anywhere}
.shophead .linkbtn{font-size:13px;min-height:28px;padding:0}
/* Search: a line to write on. */
.shopsearch{flex:none;max-width:none}
.shopsearch input{border:0;border-bottom:1px solid var(--line);border-radius:0;background:transparent;padding:10px 4px 10px 30px;min-height:46px;transition:border-color .25s}
.shopsearch input:hover{border-bottom-color:var(--muted)}
.shopsearch input:focus-visible{outline:0;border-bottom-color:var(--ink);box-shadow:0 1px 0 var(--ink)}
.shopsearch input::placeholder{color:var(--muted);opacity:1}
.shopsearch .ico{left:2px;color:var(--ink)}
/* The pages, numbered; a short line marks the one open. */
.cats{position:relative;counter-reset:page;display:flex;flex-direction:column}
.cats a{position:relative;display:flex;align-items:baseline;gap:14px;padding:8px 0;color:var(--muted);text-decoration:none;font-size:15px;line-height:1.3;transition:color .2s,transform .35s var(--ease-out)}
/* The numbers are decoration: screen readers are told nothing ("/ ''"), where the browser knows how. */
.cats a::before{counter-increment:page;content:counter(page,decimal-leading-zero);content:counter(page,decimal-leading-zero) / "";flex:none;min-width:20px;font-size:11px;font-weight:600;letter-spacing:.06em;font-variant-numeric:tabular-nums;opacity:.75}
/* All products has no number: a small grid of four squares stands in its place, so it does not read as a
   second dash beside the line that marks the open page. */
.cats a.allprods::before{content:"";counter-increment:none;align-self:center;width:10px;height:10px;min-width:0;margin-right:10px;
  background:linear-gradient(currentColor 0 0) 0 0/4px 4px no-repeat,linear-gradient(currentColor 0 0) 100% 0/4px 4px no-repeat,
    linear-gradient(currentColor 0 0) 0 100%/4px 4px no-repeat,linear-gradient(currentColor 0 0) 100% 100%/4px 4px no-repeat}
.cats a:hover{color:var(--ink);transform:translateX(3px)}
.cats a[aria-current="page"]{color:var(--ink);font-weight:600;transform:none}
.cats a[aria-current="page"]::before{opacity:1}
.cats a.allprods{margin-top:8px;padding-top:14px;border-top:1px solid var(--line)}
/* The line marking the open page: one for the list, put by the page by shop.js (placeMark: --mx, --my, its
   length --mw) and sliding from the page open before. Moved and stretched by transform alone. */
.catmark{position:absolute;left:0;top:0;width:1px;height:1.5px;background:var(--ink);pointer-events:none;opacity:0;transform-origin:0 0;
  transform:translate(var(--mx,0),var(--my,0)) scaleX(var(--mw,12));transition:transform .6s var(--ease-out),opacity .3s var(--ease)}
.cats.marked .catmark{opacity:1}
.cats.still .catmark{transition:none}
/* It is a <main>, so app.css centres it with auto side margins and pads it; here it fills its column. At least a
   screen tall, the page taking what is left, so a short page still ends with the shop's name at the foot of the
   screen, and a page that turns can always put its top under the phone's strip of tabs (shop.js, arrive). */
.shopmain{min-width:0;margin:0;padding:48px 0 0;max-width:none;display:flex;flex-direction:column;min-height:100vh;min-height:100dvh}
.shoppage{counter-reset:section;flex:1 0 auto}
.shoppage > * + *{margin-top:clamp(56px,5.6vw,84px)}
/* The first-visit steps are a note above the page, not a section of it. */
.shoppage > .howto + *{margin-top:clamp(28px,3vw,40px)}
.shoppage .empty{padding:80px 0;text-align:center}
/* A banner may open a page at one of its sections (shop.js): it lands with a little room above it. */
.shoppage > [data-section]{scroll-margin-top:28px}
.shoppage .empty p{font:400 26px/1.25 var(--font-display);color:var(--ink);margin:0 0 22px}
/* Nothing found: the shop's voxel over the words, as on the closed and the loading page. */
.shoppage .empty .mark{display:block;width:30px;height:34px;margin:0 auto 22px;opacity:.85}
.shoppage > p.empty{font:400 26px/1.25 var(--font-display);color:var(--muted)}

/* View only: the shop says it takes no orders now, above the page and in the cart (which cannot be sent). */
.viewnote,.cartpaused{margin:0 0 18px;padding:12px 16px;border:1px solid var(--line);border-radius:var(--radius-box);background:var(--surface);font-size:14px;line-height:1.5}
.cartpaused{margin:14px 0 0}

/* Staff see a note that this is the shop (and whether it is open), with their links. */
.staffbar{position:relative;z-index:50;display:flex;flex-wrap:wrap;gap:6px 22px;justify-content:space-between;align-items:center;padding:9px clamp(16px,3.6vw,56px);
  background:var(--ink);color:var(--paper);font-size:13px;font-weight:600;letter-spacing:.01em}
.staffbar > span:first-child{display:flex;align-items:center;gap:10px}
.staffbar > span:first-child::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--buy);flex:none}
.staffbar .links{display:flex;gap:18px}
.staffbar a{color:inherit;text-decoration:none;opacity:.8;transition:opacity .2s}
.staffbar a:hover{opacity:1;text-decoration:underline;text-underline-offset:3px}

/* ---------- banners: one = a wide hero, two or more = tiles, a slideshow takes turns ----------
   Each kind keeps one shape at every width, the shape the showcase editor shows: a hero or a slide 2:1, a tile
   square. A picture made in that shape is then shown whole on every screen (object-fit: cover crops only what
   does not fit the shape), and 2:1 is short enough for a phone's first screen to show a row of products too.
   The words are sized by the banner itself (cqw: a hundredth of its width; its height follows from its shape),
   so they fit it at every width; the vw sizes before them are for browsers without container units. */
.banner{position:relative;display:block;overflow:hidden;border-radius:var(--radius-banner);background:var(--plate);color:#fff;text-decoration:none;isolation:isolate;container-type:inline-size}
.banner img,.tpic img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;background:var(--pic-plate);transition:transform 1.6s var(--ease-out)}
a.banner:hover img{transform:scale(1.035)}
.banner.noimg{background:linear-gradient(140deg,#1D1A15 10%,#5A4824 60%,#C49A33)}
.banner .ov{position:absolute;inset:0;display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-end;gap:12px;padding:clamp(22px,3.8vw,56px);text-align:left;
  background:linear-gradient(to top,rgba(12,10,6,.62),rgba(12,10,6,.22) 46%,rgba(12,10,6,0) 72%);text-shadow:0 1px 20px rgba(0,0,0,.28)}
.banner .ov h2{margin:0;font-family:var(--font-display);font-weight:400;overflow-wrap:anywhere}
.banner .ov h2{font-size:clamp(28px,4vw,60px);font-size:clamp(22px,5.4cqw,60px);line-height:1;letter-spacing:-.02em;max-width:15ch}
.banner .ov p{margin:0;max-width:42ch;font-size:clamp(13px,1.15vw,17px);font-size:clamp(13px,1.6cqw,17px);line-height:1.45;white-space:pre-line;opacity:.92;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* The call to action: frosted, filled white on hover, its arrow moving on. */
.bbtn{display:inline-flex;align-items:center;gap:10px;margin-top:10px;padding:11px 20px 11px 22px;border-radius:var(--radius-pill);background:rgba(255,255,255,.2);color:#fff;
  font-size:12.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;text-shadow:none;transition:background .35s var(--ease),color .35s var(--ease)}
.bbtn .ico{width:17px;height:17px;transition:transform .45s var(--ease-out)}
a.banner:hover .bbtn{background:#fff;color:#16140F}
a.banner:hover .bbtn .ico{transform:translateX(4px)}
.hero .banner{aspect-ratio:2/1}
.hero .ov{gap:clamp(6px,1.1cqw,12px);padding:clamp(16px,4.6cqw,56px)}
.hero .bbtn{margin-top:clamp(2px,.9cqw,10px);padding:clamp(8px,1cqw,11px) clamp(14px,1.8cqw,20px) clamp(8px,1cqw,11px) clamp(16px,2cqw,22px);font-size:clamp(11px,1.15cqw,12.5px)}
/* A hero's words rise in one after another as the page opens. */
.hero .ov > *{animation:cap-in 1s var(--ease-out) both}
.hero .ov > :nth-child(2){animation-delay:.12s}
.hero .ov > :nth-child(3){animation-delay:.22s}
@keyframes cap-in{from{opacity:0;transform:translateY(22px)}}
.carousel{position:relative;container-type:inline-size}
.ctrack{display:flex;overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;border-radius:var(--radius-banner);overscroll-behavior-x:contain}
.ctrack::-webkit-scrollbar{display:none}
.cslide{flex:0 0 100%;scroll-snap-align:start}
.cslide .banner{border-radius:0}
.carousel .ov{padding-bottom:clamp(40px,8.6cqw,104px)}
/* The slideshow's dots are lines at the bottom left; the one in view fills while it waits (shop.js). */
.carousel .dots{left:clamp(16px,4.6cqw,56px);right:auto;bottom:clamp(6px,2.6cqw,36px);justify-content:flex-start;gap:6px}
.carousel .dot{position:relative;width:44px;height:28px;border:0;border-radius:0;background:transparent;box-shadow:none;transform:none}
.carousel .dot::before,.carousel .dot::after{content:"";position:absolute;left:0;right:0;top:50%;height:2px;margin-top:-1px;border-radius:2px;background:rgba(255,255,255,.34)}
.carousel .dot::after{background:#fff;transform:scaleX(0);transform-origin:left;transition:transform .3s var(--ease)}
.carousel .dot[aria-current="true"]{width:44px;background:transparent;transform:none}
.carousel .dot[aria-current="true"]::after{transform:scaleX(1)}
.carousel .dot.filling::after{transition:none;animation:fill var(--wait,3s) linear both}
@keyframes fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.carousel .snav{top:auto;bottom:clamp(8px,2.4cqw,32px);transform:none;background:rgba(255,255,255,.18);color:#fff;transition:background .3s,color .3s}
.carousel .snav:hover{background:#fff;color:#16140F}
.carousel .snav.prev{left:auto;right:calc(clamp(16px,4.6cqw,56px) + 52px)}
.carousel .snav.next{right:clamp(16px,4.6cqw,56px)}
/* A tile: its square picture with nothing over it, and its words under it on the page, in ink, like a product
   card's. As many as a row of product cards holds fill the row (--n of them: shop.js). */
.tiles{position:relative;container-type:inline-size;--tgap:var(--gutter)}
/* A grid styled like the product grid, with nothing in it and no height: shop.js counts its columns (--cols). */
.tprobe{height:0;visibility:hidden;overflow:hidden}
.ttrack{display:grid;gap:var(--tgap);grid-template-columns:repeat(var(--n,2),minmax(0,1fr))}
.tile{display:flex;flex-direction:column;min-width:0;color:var(--ink);text-decoration:none}
.tpic{position:relative;display:block;aspect-ratio:1/1;border-radius:var(--radius-banner);overflow:hidden;background:var(--plate);isolation:isolate}
.tpic.noimg{background:linear-gradient(140deg,#1D1A15 10%,#5A4824 60%,#C49A33)}
/* With a picture, no plate of its own: the transparent parts of a picture show the page, like a product's. */
.tpic:has(img),.banner:has(img){background:transparent}
a.tile:hover .tpic img{transform:scale(1.035)}
.tcap{display:flex;flex-direction:column;align-items:flex-start;gap:6px;padding-top:16px}
.tcap h3{margin:0;font:400 clamp(20px,1.9vw,28px)/1.1 var(--font-display);letter-spacing:-.01em;overflow-wrap:anywhere}
.ttext{color:var(--muted);font-size:14.5px;line-height:1.45;white-space:pre-line;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* Its call to action: small capitals with an arrow, underlined (and the arrow moving on) on hover. */
.tgo{display:inline-flex;align-items:center;gap:8px;margin-top:4px;font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  text-decoration:underline;text-decoration-color:transparent;text-decoration-thickness:1.5px;text-underline-offset:5px;transition:text-decoration-color .3s var(--ease)}
.tgo .ico{width:16px;height:16px;flex:none;transition:transform .45s var(--ease-out)}
a.tile:hover .tgo{text-decoration-color:currentColor}
a.tile:hover .tgo .ico{transform:translateX(4px)}
/* More tiles than a product row holds: a row that scrolls sideways with half a tile more in view than that row
   (--cols + 1/2), each a little smaller than a product card, the picture cut at its edge showing there is more.
   Room around it for a tile's focus ring. */
.tiles.scroll .ttrack{grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:calc((100% - var(--cols) * var(--tgap)) / (var(--cols) + .5));
  overflow-x:auto;scroll-snap-type:x mandatory;scrollbar-width:none;overscroll-behavior-x:contain;padding:6px;margin:-6px;scroll-padding-inline:6px}
.tiles.scroll .ttrack::-webkit-scrollbar{display:none}
.tiles.scroll .tile{scroll-snap-align:start}
/* Signs that it goes on, on a touch screen too: round arrows in ink at the middle of the pictures over its ends
   (each gone at its own end), and under it a line whose dark part is the part in view, moving as it scrolls. */
.tiles .snav{top:calc((100cqw - var(--cols) * var(--tgap)) / (var(--cols) + .5) / 2);z-index:2;background:var(--ink);color:var(--paper);
  box-shadow:0 8px 22px -8px rgba(0,0,0,.5);transition:opacity .3s var(--ease),transform .3s var(--ease-out)}
.tiles .snav:hover{background:var(--ink);transform:translateY(-50%) scale(1.06)}
.tiles .snav.prev{left:12px}
.tiles .snav.next{right:12px}
.tiles.atstart .snav.prev,.tiles.atend .snav.next{opacity:0;pointer-events:none}
.tbar{position:relative;height:3px;margin-top:22px;border-radius:var(--radius-stamp);background:var(--line);overflow:hidden}
.tbar span{position:absolute;top:0;bottom:0;left:calc(var(--tx,0) * 100%);width:calc(var(--tw,.3) * 100%);border-radius:var(--radius-stamp);background:var(--ink)}
.tiles:not(.scroll) .snav,.tiles:not(.scroll) .tbar{display:none}

/* ---------- product sections: a number, a title in the serif, a hairline ---------- */
.sectitle{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:end;column-gap:20px;margin:0 0 30px;color:var(--ink);
  font:400 clamp(28px,2.7vw,42px)/1.04 var(--font-display);letter-spacing:-.015em;text-transform:none}
.sectitle::before{counter-increment:section;content:counter(section,decimal-leading-zero);content:counter(section,decimal-leading-zero) / "";grid-column:1 / -1;margin-bottom:14px;color:var(--muted);font-family:var(--font-sans);line-height:1}
.sectitle::after{content:"";height:1px;margin-bottom:.32em;background:var(--line);transform-origin:left}
.pgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(208px,1fr));gap:56px var(--gutter)}
.scard{position:relative;display:flex;flex-direction:column;min-width:0}
.scard-media{position:relative}
.scard-img{position:relative;display:block;width:100%;padding:0;border:0;border-radius:var(--radius-pic);background:var(--plate);aspect-ratio:1/1;cursor:pointer;overflow:hidden;isolation:isolate}
.scard-img img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;background:var(--pic-plate);opacity:0;transition:transform 1.2s var(--ease-out),opacity .6s var(--ease)}
/* A picture fades in once it has arrived (shop.js marks it), instead of appearing line by line. Then the frame's
   plate goes: the transparent parts of a picture show the page (app.css, --pic-plate). */
.scard-img img.in{opacity:1}
.scard-img:has(img.in){background:transparent}
/* Under the mouse the picture comes closer. The mouse is on the picture while it is on a button lying on it (the +,
   Reserve online): by the frame, not the picture, or the picture drew back as its button answered. */
.scard-media:hover .scard-img img{transform:scale(1.045)}
/* The second picture takes the first one's place (not on top of it: its transparent parts would show the first). */
.scard-media:hover .scard-img img.alt.ready{opacity:1}
.scard-media:hover .scard-img img:not(.alt):has(~ img.alt.ready){opacity:0}
.scard-text{display:grid;justify-items:start;gap:4px;padding:16px 2px 0;border:0;background:transparent;color:var(--ink);cursor:pointer;text-align:left;font:inherit}
.scode{color:var(--muted)}
.sname{font-weight:600;font-size:15.5px;line-height:1.35;overflow-wrap:anywhere;text-decoration:underline;text-decoration-color:transparent;text-underline-offset:4px;text-decoration-thickness:1px;transition:text-decoration-color .3s}
.scard:hover .sname{text-decoration-color:currentColor}
/* The name and its type in one line: the type smaller and grey after it, kept whole (it moves to the next
   line as one piece when the name leaves no room). */
.sline{line-height:1.35}
.stype{color:var(--muted);font-size:12.5px;font-weight:500;white-space:nowrap}
/* A price: its words quiet, the amount in ink (cart.js, priceEl). */
.sprice,.cprice{color:var(--muted);font-size:14px;font-variant-numeric:tabular-nums lining-nums}
.sprice b,.cprice b{font-weight:600;color:var(--ink)}
.cprice{margin-top:4px}
.noimg{display:block;width:100%;height:100%;background:repeating-linear-gradient(-45deg,var(--plate),var(--plate) 10px,transparent 10px,transparent 20px),var(--surface-2)}
/* The + on every product that can be bought, on the picture's corner: a frosted circle that turns saffron
   on hover (its + turning a quarter) and stays saffron, with the count, once the product is in the cart. */
.plus{position:absolute;right:12px;bottom:12px;
  transition:background .25s var(--ease),color .25s var(--ease),transform .3s var(--ease-out)}
.plus .ico{width:24px;height:24px;transition:transform .45s var(--ease-out)}
.plus:hover{background:var(--buy);color:var(--buy-ink);transform:scale(1.08)}
.plus:hover .ico{transform:rotate(90deg)}
.plus:active{transform:scale(.9)}
.plus.in{background:var(--buy);color:var(--buy-ink)}
.plus.in[data-qty]::after{content:attr(data-qty);position:absolute;top:-5px;right:-5px;min-width:22px;height:22px;padding:0 6px;border-radius:var(--radius-pill);background:var(--ink);color:var(--paper);
  font-size:12px;font-weight:700;display:grid;place-items:center;box-shadow:0 0 0 2px var(--paper);animation:pop .35s var(--ease-out)}
@keyframes pop{from{transform:scale(.4);opacity:0}}
/* Sold out: the picture keeps its colors under a mark stamped across it, and the name is struck through;
   still shown (after what can be bought) and still opens. The mark lets clicks through to the picture. */
.soldmark{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none}
.soldmark span{transform:rotate(-12deg);padding:7px 18px;border:1.5px solid rgba(255,255,255,.9);outline:1.5px solid rgba(255,255,255,.55);outline-offset:3px;border-radius:var(--radius-stamp);
  background:rgba(20,18,14,.55);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);color:#fff;
  font-size:clamp(13px,1.5vw,17px);font-weight:800;letter-spacing:.2em;text-transform:uppercase;white-space:nowrap}
.scard.out .sname,.struck{text-decoration:line-through;text-decoration-color:currentColor;color:var(--muted)}
.soldtag{display:inline-block;margin:2px 0;padding:2px 9px;border-radius:var(--radius-pill);background:var(--ink);color:var(--paper);font:700 11px/1.5 var(--font-sans);letter-spacing:.12em;text-transform:uppercase;text-decoration:none;vertical-align:middle}

/* Things rise into view as they are scrolled to, where the browser can tie an animation to scrolling.
   (Not the slides: they scroll sideways in their own strip.) */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    /* What is looked at rises (cards, banners, tiles, the steps); what is read stays still: a section's title, and
       the foot of the page with the shop's name and its information (the owner, 2026-11-12). */
    .scard,.howto,.hero:not(.carousel),.tiles:not(.scroll) .tile{animation:rise linear both;animation-timeline:view();animation-range:entry 0% entry 70%}
    .pgrid .scard:nth-child(4n+2){animation-range:entry 4% entry 76%}
    .pgrid .scard:nth-child(4n+3){animation-range:entry 8% entry 82%}
    .pgrid .scard:nth-child(4n+4){animation-range:entry 12% entry 88%}
    /* A section's hairline is drawn from its title outwards. */
    .sectitle{view-timeline-name:--section}
    .sectitle::after{animation:draw linear both;animation-timeline:--section;animation-range:entry 40% cover 45%}
  }
}
@keyframes rise{from{opacity:0;transform:translateY(36px)}}
/* A piece coming in sideways as a page turns on a phone (shop.js, enter): its rise is put aside meanwhile, so it
   has one animation at a time. In view the rise is over, so nothing shows. */
.shopmain .turning{animation:none}

/* ---------- the cart button ---------- */
/* It floats over the page: paper while the cart is empty, saffron once it holds something. */
.cartfab{position:fixed;right:max(24px,env(safe-area-inset-right,0px));bottom:calc(24px + env(safe-area-inset-bottom,0px));z-index:40;width:64px;height:64px;border-radius:50%;border:0;
  background:var(--frost-strong);color:var(--ink);display:grid;place-items:center;cursor:pointer;box-shadow:var(--float);
  transition:background .3s var(--ease),color .3s var(--ease),transform .35s var(--ease-out)}
.cartfab:hover{transform:translateY(-3px)}
.cartfab:active{transform:scale(.94)}
.cartfab.full{background:var(--buy);color:var(--buy-ink)}
.cartfab.full:hover,.cartfab.full:active{background:var(--buy-deep)}
.fabcount{position:absolute;top:-3px;right:-3px;min-width:24px;height:24px;padding:0 7px;border-radius:var(--radius-pill);background:var(--ink);color:var(--paper);font-size:12.5px;font-weight:700;display:grid;place-items:center;box-shadow:0 0 0 2px var(--paper);font-variant-numeric:tabular-nums}
.fabcount[hidden]{display:none}
@keyframes fabbump{0%{transform:scale(1)}35%{transform:scale(1.16)}65%{transform:scale(.96)}100%{transform:scale(1)}}
.cartfab.bump{animation:fabbump .5s var(--ease-out)}
.cartfab.bump .fabcount{animation:pop .4s var(--ease-out)}
/* A picture on its way into the cart (shop.js, fly()): three layers the GPU moves (across, down, shrinking),
   given their own layers before the first frame. Nothing about them is animated that would need redrawing. */
.fly{position:fixed;z-index:120;pointer-events:none;will-change:transform}
.flylane{width:100%;height:100%;will-change:transform}
.flyimg{display:block;width:100%;height:100%;object-fit:cover;border-radius:var(--radius-banner);box-shadow:0 6px 18px -6px rgba(22,20,15,.35);will-change:transform,opacity}
/* "Added" notes rising from the cart button. Each grows from nothing (so the older ones slide up smoothly) and shrinks away. */
.cartpops{position:fixed;right:max(24px,env(safe-area-inset-right,0px));bottom:calc(98px + env(safe-area-inset-bottom,0px));z-index:110;display:flex;flex-direction:column;align-items:flex-end;pointer-events:none;max-width:min(80vw,340px)}
.cpop{display:grid;grid-template-rows:0fr;opacity:0;max-width:100%;transition:grid-template-rows .35s var(--ease-out),opacity .3s var(--ease)}
.cpop.in{grid-template-rows:1fr;opacity:1}
.cpopin{min-height:0;overflow:hidden;padding-top:8px;transform:translateY(12px) scale(.94);transform-origin:bottom right;transition:transform .45s var(--ease-out)}
.cpop.in .cpopin{transform:none}
.cpopbtn{pointer-events:auto;display:flex;align-items:center;gap:10px;max-width:100%;min-height:44px;padding:5px 16px 5px 5px;border:0;border-radius:var(--radius-pill);background:var(--ink);color:var(--paper);
  font:inherit;font-size:14px;font-weight:600;box-shadow:var(--float);cursor:pointer}
.cpopimg{flex:none;width:34px;height:34px;border-radius:50%;object-fit:cover;background:var(--pic-plate)}
.cpopbtn > b:first-child{margin-left:11px}
.cpopbtn b{color:var(--buy);font-variant-numeric:tabular-nums}
.cpopname{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* A warning among them (e.g. no more in stock): filled in the warning color, so it is taken neither for an
   "added" note nor for the cart bar under it; free to wrap. */
.cpopbtn.warn{align-items:flex-start;border-radius:var(--radius-modal);padding:11px 16px;background:var(--danger);color:var(--paper);line-height:1.35;text-align:left}
.cpopbtn.warn b{flex:none;margin:0;display:grid;place-items:center;width:20px;height:20px;border-radius:50%;background:var(--paper);color:var(--danger);font-size:13px}
/* A discount the product just added made apply (or grow): the shop's yellow, an ink check, and one sweep of
   light across it as it arrives. */
.cpopbtn.deal{position:relative;overflow:hidden;padding-left:6px;background:var(--buy);color:var(--buy-ink)}
.cpopcheck{flex:none;display:grid;place-items:center;width:32px;height:32px;border-radius:50%;background:var(--buy-ink);color:var(--buy)}
.cpopcheck .ico{width:15px;height:15px;stroke-width:2.6}
.cpopbtn.deal .cpopname{font-variant-numeric:tabular-nums lining-nums}
.cpopbtn.deal.shine::after{content:"";position:absolute;inset:0;background:linear-gradient(105deg,transparent 35%,rgba(255,255,255,.55) 50%,transparent 65%);transform:translateX(-100%);animation:dealshine .9s .15s var(--ease-out) forwards;pointer-events:none}
.cpopbtn.deal.shine .cpopcheck path{animation:dealcheck .4s .1s var(--ease-out) both}
@keyframes dealshine{to{transform:translateX(100%)}}
@keyframes dealcheck{from{stroke-dasharray:24;stroke-dashoffset:24}to{stroke-dasharray:24;stroke-dashoffset:0}}
@media (prefers-reduced-motion:reduce){.cpopbtn.deal.shine::after{display:none}.cpopbtn.deal.shine .cpopcheck path{animation:none}}
/* "Only N left" on a cart line that holds all there is: the same red and "!" as the warning bar. */
.leftnote{display:inline-flex;align-items:center;gap:6px;align-self:flex-start;margin-top:6px;padding:2px 10px 2px 3px;border-radius:var(--radius-pill);background:var(--danger);color:var(--paper);font-size:12.5px;font-weight:600}
.leftnote b{display:grid;place-items:center;width:16px;height:16px;border-radius:50%;background:var(--paper);color:var(--danger);font-size:11px}
@media (prefers-reduced-motion:reduce){
  .cartfab.bump,.cartfab.bump .fabcount,.plus.in[data-qty]::after{animation:none}
  .scard-img img,.plus,.plus .ico,.cpop,.cpopin,.banner img,.bbtn .ico,.tpic img,.tgo .ico,.tiles .snav,.cats a,.catmark,.shop .btn.buy::after,.sreserve,.btn.buy .ico,.sreserve .ico,.reservelink .ico{transition:none}
}

/* ---------- dialogs of the shop: the product pop-up, the cart and the ticket ---------- */
.shop .overlay{background:rgba(16,13,8,.44);-webkit-backdrop-filter:blur(8px) saturate(1.1);backdrop-filter:blur(8px) saturate(1.1)}
/* A dialog is the page's paper (--surface is the paper inside it, so what copies the dialog's colour, such as the
   ticket's notches and the bars stuck to a sheet's bottom, follows), with a hairline edge and its shadow. */
.shop .modal{--surface:var(--paper);background:var(--surface);border-radius:var(--radius-float);box-shadow:0 0 0 1px color-mix(in srgb,var(--ink) 7%,transparent),var(--float)}
.shop .modal h2{font:400 30px/1.08 var(--font-display);letter-spacing:-.015em;margin:0 0 10px}
.shop .modal p{color:var(--muted)}
.modal.sheet{position:relative}
.closex{position:absolute;top:14px;right:14px;z-index:2;
  transition:background .25s,transform .35s var(--ease-out)}
.closex:hover{transform:rotate(90deg)}
.snav:hover{background:var(--frost-strong)}
/* The product pop-up takes the shape of the picture it shows, so nothing is left blank beside it: the picture
   area is as tall as the window allows (at most 680px) and as wide as the picture's own proportions make it
   (--pratio = width / height, set by shop.js for the picture in view; 1 until it is known). The text column
   keeps its width beside it. A very wide picture is held to the room the window leaves and is less tall
   instead. The pop-up never scrolls; the text column does when the details are longer than the picture is tall. */
.modal.pmodal{position:relative;width:fit-content;max-width:calc(100vw - 48px);padding:0;overflow:hidden;--pratio:1;--ptext:420px;
  --ph:min(680px,calc(100dvh - 48px),calc(min(900px,100vw - 48px - var(--ptext)) / var(--pratio)))}
.pmodal-grid{display:grid;grid-template-columns:calc(var(--ph) * var(--pratio)) var(--ptext);height:var(--ph);transition:grid-template-columns .4s var(--ease-out)}
.slider{position:relative;background:var(--plate);height:100%;min-width:0;min-height:0}
.slides{display:flex;height:100%;overflow-x:auto;overflow-y:hidden;scroll-snap-type:x mandatory;scrollbar-width:none;overscroll-behavior-x:contain}
.slides::-webkit-scrollbar{display:none}
.slide{flex:0 0 100%;height:100%;min-height:0;scroll-snap-align:start;display:grid;grid-template:100% / 100%;place-items:center}
/* Whole, whatever its shape: a tall or wide picture is shown smaller, never cut and never scrolled. The picture is
   its own size (not contained in the slide), so the plate behind its transparent parts is only under it. */
.slide img{display:block;max-width:100%;max-height:100%;width:auto;height:auto;background:var(--pic-plate);animation:fadein .6s var(--ease)}
@keyframes fadein{from{opacity:0}}
.pmodal .slider .noimg.big{height:100%}
.snav{position:absolute;top:50%;transform:translateY(-50%);background:var(--frost);box-shadow:none;transition:background .25s}
.snav.prev{left:14px}
.snav.next{right:14px}
.dots{position:absolute;left:0;right:0;bottom:14px;display:flex;justify-content:center;gap:8px}
.dot{width:8px;height:8px;border-radius:var(--radius-pill);border:0;background:rgba(22,20,15,.25);padding:0;cursor:pointer;transition:width .4s var(--ease-out),background .3s}
.dot[aria-current="true"]{width:24px;background:var(--ink)}
.pinfo{display:flex;flex-direction:column;padding:48px 38px 34px;min-height:0;overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--line) transparent}
.shop .pinfo .pcode{margin:0 0 12px;color:var(--muted)}
.shop .pinfo h2{margin:0 44px 12px 0;font-size:clamp(26px,2.4vw,34px);line-height:1.08;display:flex;flex-wrap:wrap;align-items:center;gap:10px}
/* In the pop-up the amount is set in the display serif, like the name over it. */
.shop .pinfo .pprice{display:flex;align-items:baseline;gap:.3em;margin:0 0 28px;font-size:15px;color:var(--muted)}
.pprice b{font:400 28px/1 var(--font-display);letter-spacing:-.01em;color:var(--ink);font-variant-numeric:lining-nums tabular-nums}
.pbuy{display:flex;flex-direction:column;gap:12px;margin-bottom:30px}
.reserve{margin:0 0 28px;padding:14px 16px;border-radius:var(--radius-control);background:var(--surface-2);color:var(--ink)}
.shop .pmodal p.reserve{color:var(--ink)}
.shop .pmodal .reserve p{margin:0;color:var(--ink)}
/* Sold out, with a page to reserve it online (cart.js, reserveLink): a wide saffron pill in the pop-up (it buys, on
   another site), a pill where a card's + would be, a link on a cart line. Another site, so their arrow points on, and
   moves on as a banner's does. */
.reserve .btn{margin-top:12px}
.reservelink{display:inline-flex;align-items:center;align-self:flex-start;gap:6px;margin-top:4px;color:var(--ink);font-size:13px;font-weight:600;text-underline-offset:3px}
/* On a card it takes the place of the +: the same corner, height, frost and shadow, as a pill with words (an
   arrow alone would not say what it does), and saffron on hover as the + is. It does not grow as the + does: words
   that swell shimmer, and the pill left its corner. Like a banner's button it fills and its arrow moves on; like
   everything that buys it is a shade deeper pressed. */
.sreserve{position:absolute;right:12px;bottom:12px;display:inline-flex;align-items:center;gap:6px;max-width:calc(100% - 24px);height:44px;padding:0 14px 0 16px;border-radius:var(--radius-pill);
  background:var(--frost-strong);color:var(--frost-ink);box-shadow:var(--lift);font-size:13px;font-weight:600;text-decoration:none;white-space:nowrap;
  transition:background .25s var(--ease),color .25s var(--ease),transform .2s var(--ease-out)}
.sreserve span{min-width:0;overflow:hidden;text-overflow:ellipsis}
.sreserve:hover{background:var(--buy);color:var(--buy-ink)}
.sreserve:active{background:var(--buy-deep);color:var(--buy-ink);transform:scale(.97)}
.btn.buy .ico,.sreserve .ico,.reservelink .ico{flex:none;width:16px;height:16px;transition:transform .35s var(--ease-out)}
.btn.buy:hover .ico,.sreserve:hover .ico,.reservelink:hover .ico{transform:translateX(3px)}
.pdl{display:grid;grid-template-columns:auto minmax(0,1fr);margin:0 0 20px;font-size:14px;border-top:1px solid var(--line)}
.pdl dt,.pdl dd{padding:11px 0;border-bottom:1px solid var(--line)}
.pdl dt{padding-right:22px;color:var(--muted)}
.pdl dd{margin:0;overflow-wrap:anywhere}
.shop .modal.pmodal p.pdesc2{white-space:pre-line;color:var(--ink);margin:0;font-size:15px;line-height:1.6}

/* ---------- the cart ---------- */
.modal.cartbox{max-width:600px;padding:34px 34px 28px}
.cartlines{list-style:none;margin:0 0 4px;padding:0}
.cartline{display:flex;align-items:center;gap:14px;padding:16px 0;border-bottom:1px solid var(--line);animation:fadein .4s var(--ease)}
.cartline.out .cname{text-decoration:line-through;color:var(--muted)}
.cthumb{width:64px;height:64px;object-fit:cover;border-radius:var(--radius-pic);background:var(--pic-plate);flex:none}
.cinfo{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}
.cinfo .soldtag{align-self:flex-start}
.cname{font-weight:600;overflow-wrap:anywhere;line-height:1.3}
.carttotal{display:flex;justify-content:space-between;align-items:baseline;gap:12px;margin:8px 0;padding-top:14px;font-size:14px;font-weight:600;letter-spacing:.08em;text-transform:uppercase}
.shop .modal .carttotal{color:var(--ink)}
.carttotal strong{font:400 32px/1 var(--font-display);letter-spacing:-.01em;text-transform:none;font-variant-numeric:lining-nums tabular-nums}
.carttotal strong.words{font-size:22px;line-height:1.25;text-align:right}
.cartempty{padding:28px 0 8px}
.shop .modal p.cartempty{font:400 22px/1.3 var(--font-display);color:var(--ink)}
.ordernum{font-family:var(--font-mono);letter-spacing:.3em}
.ordertbl{margin:6px 0 8px}
/* An order's money, set like a receipt (moneySummary in cart.js): the subtotal, the discounts indented under it,
   each given one with an ink check and a dotted leader to what it takes off, the others greyed with what they
   need; a rule; the total, with what it was before the discount in quiet words under it. A discount given since
   the last change draws its check in, and a new total settles into place. */
.receipt{margin-top:18px}
.shop .modal .receipt p.rline{display:grid;grid-template-columns:auto minmax(16px,1fr) auto;align-items:baseline;column-gap:8px;margin:0 0 12px;font-size:14px;color:var(--ink)}
.lead{display:block;height:0;border-bottom:1.5px dotted color-mix(in srgb,var(--ink) 28%,transparent);transform:translateY(-4px)}
.rdiscs{list-style:none;margin:0;padding:0;display:grid;gap:12px}
.rdisc{display:grid;grid-template-columns:16px minmax(0,max-content) minmax(16px,1fr) auto;column-gap:10px;align-items:baseline}
.rmark{display:grid;place-items:center;width:16px;height:16px;border-radius:50%;align-self:start;margin-top:2px;box-sizing:border-box}
.rmark .ico{width:10px;height:10px;stroke-width:3}
.rdisc.on .rmark{background:var(--ink);color:var(--paper)}
.rdisc.off .rmark{border:1.5px solid color-mix(in srgb,var(--ink) 30%,transparent)}
.rname{font-size:14.5px;font-weight:600;line-height:1.4;color:var(--ink);overflow-wrap:anywhere}
.ramt{font-size:14px;font-weight:600;color:var(--ink);text-align:right;font-variant-numeric:tabular-nums lining-nums;white-space:nowrap}
.rline .ramt{font-weight:400}
.rsub{grid-column:2 / -1;display:flex;flex-wrap:wrap;gap:1px 12px;margin-top:1px;font-size:12.5px;line-height:1.45;color:var(--muted)}
.rnote{display:inline-flex;align-items:center;gap:5px}
.rnote .ico{width:12px;height:12px;flex:none}
.rdisc.on .rnote{color:var(--ink);font-weight:600}
.rdisc.off{opacity:.7}
.rdisc.off .rname{font-weight:500;color:var(--muted)}
.carttotal.ruled{margin-top:18px;padding-top:16px;border-top:1px solid var(--line)}
.shop .modal p.before{margin:-2px 0 14px;text-align:right;font-size:12.5px;letter-spacing:.01em;color:var(--muted);font-variant-numeric:tabular-nums lining-nums}
.rdisc.won .rmark{animation:rmark .42s var(--ease-out) both}
.rdisc.won .rmark path{animation:rcheck .38s .14s var(--ease-out) both}
.rdisc.won .ramt{animation:ramt .5s .08s var(--ease-out) both}
.carttotal strong.settle{animation:settle .45s var(--ease-out)}
@keyframes rmark{from{transform:scale(.3);opacity:0}to{transform:none;opacity:1}}
@keyframes rcheck{from{stroke-dasharray:24;stroke-dashoffset:24}to{stroke-dasharray:24;stroke-dashoffset:0}}
@keyframes ramt{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}
@keyframes settle{from{opacity:.2;transform:translateY(7px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.rdisc.won .rmark,.rdisc.won .rmark path,.rdisc.won .ramt,.carttotal strong.settle{animation:none}}
.ordertbl td{padding-left:0}
.ordertbl td:last-child{padding-right:0}
.ordertbl tfoot td{background:transparent;font-size:16px}
/* Where you are: 1 Cart, 2 Check, 3 Order number; a line over each step, drawn in as you reach it. */
.steps{list-style:none;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:0 52px 26px 0;padding:0;font-size:12.5px;font-weight:600;color:var(--muted)}
.steps li{position:relative;display:flex;align-items:center;gap:8px;min-width:0;padding-top:14px;white-space:nowrap;overflow:hidden}
/* The label is cut with "…" where a phone has no room for it (a flex box's own text would be cut bare). */
.steps .stepl{min-width:0;overflow:hidden;text-overflow:ellipsis}
.steps li::after,.steps li.on::before,.steps li.done::before{content:"";position:absolute;left:0;right:0;top:0;height:2px;background:var(--line)}
.steps li.on,.steps li.done{color:var(--ink)}
.steps li.on::before,.steps li.done::before{z-index:1;background:var(--ink);transform-origin:left}
.steps li.on::before{animation:draw .7s var(--ease-out) both}
@keyframes draw{from{transform:scaleX(0)}}
.stepn{flex:none;display:inline-grid;place-items:center;width:22px;height:22px;border-radius:50%;background:var(--frost-plain-strong);color:var(--ink);font-size:12px;font-weight:700;font-variant-numeric:tabular-nums}
.steps li.on .stepn{background:var(--ink);color:var(--paper)}
.steps li.done .stepn{background:transparent;box-shadow:inset 0 0 0 1.5px var(--ink)}
/* The ticket: the number to show at the booth, on a stub with a torn line and two notches. */
.ticket{position:relative;margin:18px 0 24px;padding:30px 24px 0;border-radius:var(--radius-float);background:var(--buy);color:var(--buy-ink);text-align:center;animation:ticket .7s var(--ease-out) both}
@keyframes ticket{from{opacity:0;transform:translateY(18px) rotate(-1.5deg)}}
.ticket::before,.ticket::after{content:"";position:absolute;bottom:70px;width:26px;height:26px;border-radius:50%;background:var(--surface)}
.ticket::before{left:-13px}
.ticket::after{right:-13px}
.ticket .big{margin:0;padding:0 0 26px;border:0;background:transparent;color:inherit;font-size:clamp(48px,11vw,68px);font-weight:600;line-height:1;letter-spacing:.24em;text-indent:.24em}
.shop .modal .ticket p.orderstate{display:flex;justify-content:center;align-items:center;gap:10px;margin:0;padding:0;height:84px;border-top:2px dashed color-mix(in srgb,currentColor 32%,transparent);
  border-radius:0;background:transparent;color:inherit;font-size:14px;font-weight:600;letter-spacing:.04em}
.ticket .orderstate::before{content:"";width:9px;height:9px;border-radius:50%;background:currentColor;box-shadow:0 0 0 0 color-mix(in srgb,currentColor 45%,transparent);animation:pulse 1.8s ease-out infinite}
@keyframes pulse{to{box-shadow:0 0 0 12px transparent}}
.ticket.confirmed{background:var(--onsite);color:var(--paper)}
.ticket.confirmed .orderstate::before{background:currentColor;animation:none}
.ticket.cancelled,.ticket.expired{background:var(--surface-2);color:var(--muted)}
.ticket.cancelled .orderstate::before,.ticket.expired .orderstate::before{background:currentColor;animation:none}
.ordernum.cancelled,.ordernum.expired{text-decoration:line-through;text-decoration-thickness:3px;opacity:.6}
/* Earlier orders of this device. */
.myorders{margin-top:24px;padding-top:16px;border-top:1px solid var(--line);display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.myorders h3{flex-basis:100%;margin:0 0 4px;color:var(--muted)}
.orderchip{gap:8px}
.orderchip strong{font-family:var(--font-mono);letter-spacing:.12em}
.shop .orderchip.waiting{background:color-mix(in srgb,var(--buy) 45%,transparent)}
.shop .orderchip.confirmed{background:color-mix(in srgb,var(--onsite) 16%,transparent)}
.cartbox .sheetfoot{margin-top:20px}

/* ---------- your order on the page: its number stays until hidden, with what staff decided ---------- */
.orderbars{display:flex;flex-direction:column;gap:10px}
.orderbars:not(:empty){margin-bottom:40px}
.orderbar{display:flex;align-items:center;gap:6px;border-radius:var(--radius-box);background:var(--buy);color:var(--buy-ink);padding:5px 6px 5px 5px;animation:barrise .6s var(--ease-out) both}
@keyframes barrise{from{opacity:0;transform:translateY(-10px)}}
.orderbar.confirmed{background:var(--onsite);color:var(--paper)}
.orderbar.cancelled,.orderbar.expired{background:var(--surface-2);color:var(--muted)}
.orderbar-main{flex:1;min-width:0;display:flex;align-items:center;gap:16px;min-height:50px;padding:4px 14px;border:0;border-radius:var(--radius-banner);background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}
.orderbar-main::before{content:"";flex:none;width:9px;height:9px;border-radius:50%;background:currentColor;box-shadow:0 0 0 0 color-mix(in srgb,currentColor 45%,transparent);animation:pulse 1.8s ease-out infinite}
.orderbar.confirmed .orderbar-main::before,.orderbar.cancelled .orderbar-main::before,.orderbar.expired .orderbar-main::before{background:currentColor;animation:none}
.orderbar .iconbtn{color:inherit}
.orderbar .iconbtn:hover{background:color-mix(in srgb,currentColor 14%,transparent)}
.onum2{font-family:var(--font-mono);font-size:22px;font-weight:600;letter-spacing:.2em}
.orderstate{display:inline-block;margin:0 0 12px;padding:3px 12px;border-radius:var(--radius-pill);font-weight:700;font-size:14px;background:var(--hl);color:var(--hl-ink)}

/* ---------- how ordering works: three steps for a first visit ---------- */
.howto{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:22px 40px;padding:28px 30px;border-radius:var(--radius-box);background:var(--surface);box-shadow:inset 0 0 0 1px var(--line)}
.howto h2{grid-column:1 / -1;margin:0;color:var(--muted)}
.howsteps{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px 30px}
.howsteps li{display:grid;grid-template-columns:auto minmax(0,1fr);gap:14px;align-items:start;font-size:15px;line-height:1.45}
.howsteps .stepn{width:auto;height:auto;margin-top:-4px;background:transparent;color:var(--ink);font:400 38px/1 var(--font-display);font-variant-numeric:lining-nums}

/* ---------- the page's end ---------- */
.shopfoot{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:18px 28px;margin-top:clamp(96px,10vw,160px);padding-top:26px;border-top:1px solid var(--line);font-size:14px}
.footmark{flex:1 1 100%;margin:0;font:400 clamp(48px,9vw,148px)/.9 var(--font-display);letter-spacing:-.035em;color:color-mix(in srgb,var(--ink) 12%,transparent);overflow-wrap:anywhere;user-select:none}
/* What the shop says about itself, under its name (the showcase's information): up to four blocks side by side,
   each a heading in small capitals over its text, as a catalogue's colophon. */
.shopinfo{flex:1 1 100%;display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,210px),1fr));gap:28px clamp(28px,4vw,60px);margin:clamp(14px,2vw,26px) 0 10px}
.infoblk{min-width:0}
.infoblk h2{margin:0 0 12px;color:var(--muted);font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;line-height:1.4}
.infoblk p{margin:0;max-width:44ch;color:var(--ink);font-size:15px;line-height:1.65;white-space:pre-line;overflow-wrap:anywhere}
.infoblk a{color:inherit;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 35%,transparent);text-decoration-thickness:1px;text-underline-offset:4px;
  transition:text-decoration-color .25s var(--ease),text-decoration-thickness .25s var(--ease)}
.infoblk a:hover{text-decoration-color:currentColor;text-decoration-thickness:1.5px}
/* A block of upcoming events (shop.js, eventsBlock): each its days over its name and city, like a catalogue's
   list of dates; the one running now marked in ink. A note may follow. */
.infoevents{display:flex;flex-direction:column;gap:14px;margin:0;padding:0;list-style:none}
.infoevents li{display:flex;flex-wrap:wrap;align-items:center;gap:3px 8px}
.infoevents time{font-size:12px;font-weight:700;letter-spacing:.06em;color:var(--muted);font-variant-numeric:tabular-nums lining-nums}
.evnow{padding:1px 8px;border-radius:var(--radius-pill);background:var(--ink);color:var(--paper);font-size:11px;font-weight:700;letter-spacing:.1em;text-transform:uppercase}
.evname{flex:1 1 100%;font-size:15px;line-height:1.45;color:var(--ink);overflow-wrap:anywhere}
.evcity{color:var(--muted)}
.infoevents + p{margin-top:16px}
.linkbtn{border:0;background:transparent;padding:10px 0;min-height:44px;display:inline-flex;align-items:center;color:var(--muted);font:inherit;text-decoration:underline;text-decoration-color:color-mix(in srgb,currentColor 40%,transparent);text-underline-offset:4px;cursor:pointer;transition:color .2s,text-decoration-color .2s}
.linkbtn:hover{color:var(--ink);text-decoration-color:currentColor}
.langfield{display:inline-flex;align-items:center;gap:10px;color:var(--muted)}
.side .langfield{flex-direction:column;align-items:flex-start;gap:8px}
.langsel{font-size:14px;min-height:40px;padding:4px 30px 4px 14px;border-radius:var(--radius-pill);border:1px solid var(--line);background-color:transparent;background-position:calc(100% - 18px) 55%,calc(100% - 12px) 55%;color:var(--ink);max-width:100%;cursor:pointer}
/* Under the pages on a wide screen; at the end of the page on a phone, where the pages are a strip of tabs. */
.footlang{display:none}

/* ---------- closed ---------- */
.shopclosed{min-height:100dvh;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;text-align:center;padding:32px 24px;
  background:radial-gradient(circle at 50% 36%,color-mix(in srgb,var(--buy) 16%,transparent),transparent min(42vw,360px))}
.shopclosed .mark{width:46px;height:52px;margin-bottom:12px;animation:drift 6s ease-in-out infinite}
@keyframes drift{50%{transform:translateY(-8px) rotate(6deg)}}
.shopclosed h1{margin:0;max-width:15ch;font:400 clamp(34px,5.6vw,64px)/1.02 var(--font-display);letter-spacing:-.02em}
.shopclosed p{margin:0;color:var(--muted);font-size:17px}
.shopclosed p.small{margin-top:10px;font-size:14px}
.shopclosed a{color:var(--ink);text-underline-offset:4px}
.shopclosed .langfield{margin-top:18px}
@media (prefers-reduced-motion:reduce){.shop .boot::before,.shopclosed .mark,.ticket,.orderbar,.cartline,.slide img,.steps li.on::before,.ticket .orderstate::before,.orderbar-main::before,.hero .ov > *{animation:none}}

/* The cart button's words show only when it is the phone's bottom bar. */
.fablabel,.fabtotal{display:none}

@media (min-width:1500px){.pgrid{grid-template-columns:repeat(auto-fill,minmax(236px,1fr))}}
@media (max-width:1100px) and (min-width:901px){
  .shopwrap{grid-template-columns:200px minmax(0,1fr)}
  .shoplogo{font-size:28px}
  .howsteps{grid-template-columns:1fr}
}
@media (hover:none){
  .carousel .snav{display:none}
  .tiles .snav:hover{transform:translateY(-50%)}
  /* A tap leaves :hover on until the next tap elsewhere: no hover looks on a touch screen. Pressing
     (:active) gives the feedback there instead. */
  .scard-media:hover .scard-img img,a.banner:hover img,a.tile:hover .tpic img{transform:none}
  a.tile:hover .tgo{text-decoration-color:transparent}
  a.tile:hover .tgo .ico{transform:none}
  .scard:hover .sname{text-decoration-color:transparent}
  .plus:not(.in):hover{background:var(--frost-strong);color:var(--frost-ink)}
  .plus:hover,.cartfab:hover,.closex:hover{transform:none}
  .plus:hover .ico,a.banner:hover .bbtn .ico{transform:none}
  .sreserve:hover{background:var(--frost-strong);color:var(--frost-ink)}
  a.banner:hover .bbtn{background:rgba(255,255,255,.2);color:#fff}
  .scard-img{transition:transform .2s var(--ease-out)}
  .scard-img:active{transform:scale(.97)}
  a.banner,a.tile .tpic{transition:transform .2s var(--ease-out)}
  a.banner:active{transform:scale(.985)}
  a.tile:active .tpic{transform:scale(.97)}
}

@media (max-width:900px){
  /* A page turns sideways here (shop.js, turnPage), and nothing of it passes the screen's edge, so nothing here cuts
     it off: overflow on the page or on a box around it stopped the cards' rise on scrolling in Safari on iOS. */
  .shopwrap{grid-template-columns:1fr;gap:0;padding:0 var(--pad) 132px}
  .side{display:contents}
  /* A short top: the name, the search, the tabs; the first screen is for the shop's banner and products. */
  .shophead{flex-direction:row;align-items:baseline;justify-content:space-between;gap:4px 14px;padding:14px 0 10px}
  .shoplogo{font-size:26px}
  .shophead .linkbtn{font-size:13px}
  .shopsearch{margin:0 0 8px}
  .shopsearch input{border:0;border-radius:var(--radius-pill);background:var(--surface-2);padding:9px 16px 9px 42px;min-height:44px}
  .shopsearch input:focus-visible{box-shadow:0 0 0 2px var(--ink)}
  .shopsearch .ico{left:16px}
  /* The pages stay at hand while scrolling: a strip of tabs stuck to the top, frosted over what passes under it. */
  .cats{position:sticky;top:0;z-index:30;flex-direction:row;overflow-x:auto;gap:2px;margin:0 calc(-1 * var(--pad));padding:0 calc(var(--pad) - 6px);scrollbar-width:none;
    background:color-mix(in srgb,var(--paper) 86%,transparent);-webkit-backdrop-filter:blur(16px) saturate(1.3);backdrop-filter:blur(16px) saturate(1.3);border-bottom:1px solid var(--line)}
  .cats::-webkit-scrollbar{display:none}
  /* An end with more tabs past it fades out (shop.js, edges), instead of cutting a tab's name off at the edge. */
  .cats{--fl:0px;--fr:0px;-webkit-mask-image:linear-gradient(to right,transparent,#000 var(--fl),#000 calc(100% - var(--fr)),transparent);
    mask-image:linear-gradient(to right,transparent,#000 var(--fl),#000 calc(100% - var(--fr)),transparent)}
  .cats.moreleft{--fl:28px}
  .cats.moreright{--fr:44px}
  .cats a{white-space:nowrap;min-height:46px;display:flex;align-items:center;padding:0 10px;font-size:14.5px}
  .cats a:hover{transform:none}
  .cats a::before{display:none}
  .cats a.allprods{margin-top:0;padding-top:0;border-top:0}
  .catmark{height:2px}
  .shopmain{padding-top:16px}
  /* Sections are a column with even gaps, so the first-visit steps can come after the first section of
     products (order): on a phone the first screen shows the banner and a row of products. */
  .shoppage{display:flex;flex-direction:column;gap:44px}
  .shoppage > * + *,.shoppage > .howto + *{margin-top:0}
  .shoppage > .howto{order:1}
  .shoppage > .psection ~ :not(.howto){order:2}
  /* Under the strip of tabs stuck to the top. */
  .shoppage > [data-section]{scroll-margin-top:64px}
  /* A section's number, title and hairline in one line. */
  .sectitle{grid-template-columns:auto auto minmax(0,1fr);align-items:baseline;column-gap:10px;margin-bottom:16px;font-size:24px}
  .sectitle::before{grid-column:auto;margin:0}
  .sectitle::after{align-self:center;margin:0}
  .pgrid{grid-template-columns:repeat(2,minmax(0,1fr));gap:34px var(--gutter)}
  .scard-text{padding-top:12px}
  .sname{font-size:14.5px}
  /* Two tiles fill the row, as two product cards do; three or more are a row to swipe, two and a half in view,
     across the screen's edge. (Not risen into view: they move in their own strip.) */
  .tiles.scroll .ttrack{margin:-6px calc(-1 * var(--pad));padding:6px var(--pad);scroll-padding-inline:var(--pad)}
  .tiles.scroll .tile{animation:none}
  .tiles .snav.prev{left:6px}
  .tiles .snav.next{right:6px}
  .tbar{margin-top:16px}
  .tcap{padding-top:10px;gap:3px}
  .tcap h3{font-size:17px;line-height:1.15}
  .ttext{font-size:12.5px;line-height:1.4}
  .tgo{font-size:11px;letter-spacing:.1em;gap:6px}
  .tgo .ico{width:14px;height:14px}
  .banner .ov h2{font-size:clamp(22px,7.4cqw,32px);max-width:18ch}
  .banner .ov p{font-size:13px;-webkit-line-clamp:1}
  .hero .bbtn{padding:7px 12px 7px 14px;font-size:11px;letter-spacing:.09em}
  .hero .bbtn .ico{width:15px;height:15px}
  .carousel .ov{padding-bottom:34px}
  .carousel .dots{bottom:3px}
  .carousel .dot{width:30px}
  .carousel .dot[aria-current="true"]{width:30px}
  .howto{grid-template-columns:1fr;gap:14px;padding:18px}
  .howsteps{grid-template-columns:1fr;gap:10px}
  .howsteps li{font-size:14.5px;gap:12px}
  .howsteps .stepn{font-size:26px;min-width:20px}
  .howto .btn{justify-self:start}
  /* No zoom when a field takes the focus (iOS zooms into text under 16px). */
  .qtypill.sm input,.langsel{font-size:16px}
  .plus{right:8px;bottom:8px}
  .sreserve{right:8px;bottom:8px;max-width:calc(100% - 16px);height:40px;padding:0 10px 0 12px;gap:4px;font-size:12px}
  .sreserve .ico{width:14px;height:14px}
  .shopfoot{margin-top:84px}
  .shopinfo{gap:24px;margin-top:8px}
  .infoblk h2{margin-bottom:8px}
  .infoblk p,.evname{font-size:14.5px}
  .orderbars:not(:empty){margin-bottom:16px}
  /* Above the bottom bar, starting at its cart icon. */
  .cartpops{left:var(--pad);right:auto;align-items:flex-start;bottom:calc(84px + env(safe-area-inset-bottom,0px))}
  .cpopin{transform-origin:bottom left}
  .sidelang{display:none}
  .footlang{display:inline-flex}

  /* The cart button becomes a bar across the bottom once the cart holds something: View cart, count, total. */
  .cartfab{right:var(--pad);bottom:calc(16px + env(safe-area-inset-bottom,0px));width:58px;height:58px}
  .cartfab.full{left:max(12px,50% - 300px);right:max(12px,50% - 300px);bottom:calc(12px + env(safe-area-inset-bottom,0px));width:auto;height:60px;border-radius:var(--radius-pill);
    display:flex;align-items:center;gap:12px;padding:0 22px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;font-size:14.5px;animation:barin .5s var(--ease-out)}
  @keyframes barin{from{transform:translateY(130%)}}
  .cartfab.full:hover{transform:none}
  .cartfab.full .fablabel{display:block;flex:1;text-align:left}
  .cartfab.full .fabtotal{display:block;font-variant-numeric:tabular-nums;letter-spacing:0;font-size:16px}
  .cartfab.full .fabcount{position:static;order:3;box-shadow:none}
  .cartfab.full .fabtotal{order:4}
  body.shop #toasts{bottom:calc(88px + env(safe-area-inset-bottom,0px))}

  /* Sheets fill the screen and slide up; their main button stays at the bottom, under the thumb. */
  .overlay:has(.sheet){padding:0;place-items:stretch;-webkit-backdrop-filter:none;backdrop-filter:none}
  .modal.sheet{max-width:none;width:100%;height:100dvh;max-height:none;border-radius:0;overflow-y:auto;display:flex;flex-direction:column}
  .overlay .modal.sheet{animation:sheet-in .5s var(--ease-out)}
  .overlay.closing:has(.sheet){animation-duration:.26s}
  .overlay.closing .modal.sheet{animation:sheet-out .26s ease-in forwards}
  @keyframes sheet-in{from{transform:translateY(100%)}}
  @keyframes sheet-out{to{transform:translateY(100%)}}
  .modal.sheet .closex{position:fixed;top:calc(10px + env(safe-area-inset-top,0px));right:10px;z-index:5}
  .shop .modal.cartbox.sheet{padding:22px 18px 0}
  .shop .modal h2{font-size:27px}
  .cartbox .sheetbody{flex:1}
  .cartbox .sheetfoot,.pmodal .pbuy,.pmodal .reserve{position:sticky;bottom:0;z-index:3;background:var(--surface);margin:0;padding:12px 0 calc(12px + env(safe-area-inset-bottom,0px));box-shadow:0 -1px 0 var(--line)}
  .cartbox .sheetfoot{margin-top:18px;flex-wrap:nowrap}
  .cartbox .sheetfoot .btn{flex:1}
  .sheetfoot .btn.buy{padding:0 18px;letter-spacing:.05em}
  .steps{margin-right:50px}
  .cartline{gap:10px}
  .cthumb{width:52px;height:52px}
  .carttotal strong{font-size:28px}
  .carttotal strong.words{font-size:20px}
  /* The product sheet itself does not scroll: the picture keeps the top part of the screen, whole, and the
     details scroll under it, above the buying controls. */
  .modal.pmodal.sheet{overflow:hidden}
  .pmodal-grid{grid-template-columns:1fr;grid-template-rows:auto minmax(0,1fr);flex:1;height:auto;min-height:0}
  .slider{height:min(100vw,52dvh)}
  .pinfo{display:flex;flex-direction:column;padding:22px 18px 0}
  .shop .pinfo h2{margin-right:0;font-size:27px}
  .shop .pinfo .pcode{margin-bottom:8px}
  .shop .pinfo .pprice{margin-bottom:18px}
  /* Details first, the buying controls last and always on screen. */
  .pmodal .pbuy,.pmodal .reserve{order:99;max-width:none;margin-top:auto}
  .pmodal .reserve{border-radius:0;margin:auto -18px 0;padding:16px 18px calc(16px + env(safe-area-inset-bottom,0px))}
  .pmodal .pbuy{flex-direction:row}
  .pmodal .pbuy .qtypill{flex:none;width:132px}
  .pmodal .pbuy .qtypill input{width:40px}
  .pmodal .pbuy .btn.buy{flex:1;min-width:0;gap:8px}
  .ticket .big{font-size:clamp(46px,15vw,64px)}
}
/* A phone held sideways has no room to stack the product sheet: its picture stands beside its details, as tall as
   the screen, and the details scroll over the buying controls at their foot. */
@media (max-width:900px) and (orientation:landscape) and (max-height:520px){
  .pmodal-grid{grid-template-columns:minmax(0,min(44vw,100dvh)) minmax(0,1fr);grid-template-rows:minmax(0,1fr)}
  .slider{height:auto}
  .pinfo{padding-top:16px}
  .shop .pinfo .pcode,.shop .pinfo h2{margin-right:50px}
}
/* A tablet held upright: three products a row (after the compact layout's two). */
@media (min-width:600px) and (max-width:900px){.pgrid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:900px) and (prefers-reduced-motion:reduce){.overlay .modal.sheet,.overlay.closing .modal.sheet,.cartfab.full{animation:none}}

/* Icons (icons.js) in the round and pill buttons: centred by the grid, sized to the button. */
.qtypill button,.iconbtn{display:grid;place-items:center;padding:0}
.qtypill button .ico{width:20px;height:20px}
.qtypill.sm button .ico,.iconbtn .ico{width:18px;height:18px}
.shop .iconbtn{width:40px;min-height:40px;padding:0}
