/* Essex Street MFG. CO. — minimal.
   One mast, one sentence, a wall of plates, a size ruler that adds.
   No hero, no header bar, no drawer, no toast. */

@font-face{font-family:'Big Shoulders';src:url('/fonts/big-shoulders.woff2?v=64') format('woff2');font-weight:400 900;font-style:normal;font-display:swap}
@font-face{font-family:'Switzer';src:url('/fonts/switzer-400.woff2?v=64') format('woff2');font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:'Switzer';src:url('/fonts/switzer-500.woff2?v=64') format('woff2');font-weight:500;font-style:normal;font-display:swap}
@font-face{font-family:'Switzer';src:url('/fonts/switzer-600.woff2?v=64') format('woff2');font-weight:600;font-style:normal;font-display:swap}

:root{
  /* surfaces */
  --white:#fff; --ink:#141311; --muted:#6B6B6B;
  --paper:#EDEBE5; --ink-press:#2A2825;              /* product mat: the garment's own mount, never the page */
  --text-2:rgb(20 19 17 / .62); /* 5.19:1 — footer colophon that still has to be read */
  --line:rgb(20 19 17 / .22); --line-strong:rgb(20 19 17 / .5); --hair:rgb(20 19 17 / .12);
  --alert:#C4382A;
  --display:'Big Shoulders','Arial Narrow',Impact,sans-serif;
  --text:'Switzer',ui-sans-serif,system-ui,-apple-system,'Helvetica Neue',sans-serif;
  /* geometry: 4px base */
  --pad:16px; --gutter:16px; --mat:8px;
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px;
  --space-5:24px; --space-6:32px; --space-7:40px; --space-8:56px; --space-10:96px;
  /* type roles. Four sizes carry the shop: 14 micro, 16 body and every
     price you are asked to pay, 24 every total, and the display ladder for
     plates and titles. Nothing goes below 14. */
  --type-mark:800 24px/24px var(--display);
  /* The wordmark is a lockup, not a string: the street name in the condensed
     face, the manufacturer rider in the text face beside it. 24px on one line
     from 640 up, 20px stacked below that, so a full cart can never collide
     with it (see .mark below). */
  --type-lockup:800 20px/20px var(--display); --track-lockup:.06em;
  /* The wordmark is drawn as SVG (see .brand-mark): the serif is part of the
     mark, not of the type system, so it gets its own stack and width. */
  --brand-serif:Georgia,'Times New Roman',serif;
  --brand-w:240px;
  /* product gallery geometry */
  --thumb:76px;
  --plate-cap:calc(100svh - 296px);
  --type-rider:500 14px/20px var(--text);
  --type-imprint:800 14px/20px var(--display);
  --type-card:600 18px/22px var(--display);
  --type-h1:800 44px/44px var(--display);
  --type-h1-item:800 40px/40px var(--display);
  --type-micro:400 14px/20px var(--text);
  --type-label:500 14px/20px var(--text);
  --type-body:400 16px/24px var(--text);
  --type-price:500 14px/22px var(--text);
  --type-money:500 16px/24px var(--text);
  --type-figure:600 24px/24px var(--text);
  --row:40px;
  --tap:44px; --max:1520px; --measure:640px; --panel-w:clamp(400px,34vw,520px);
  --ease:cubic-bezier(.2,.8,.1,1);
}
@media(min-width:640px){:root{--pad:24px;--gutter:24px;--mat:10px;--type-lockup:800 24px/24px var(--display);--track-lockup:.12em}}
@media(min-width:1024px){:root{--pad:40px;--mat:12px}}
@media(min-width:1440px){:root{--pad:56px}}

*,*::before,*::after{box-sizing:border-box}
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%;caret-color:var(--ink)}
body{margin:0;background:var(--white);color:var(--ink);font:var(--type-body);
  font-variant-numeric:tabular-nums;-webkit-font-smoothing:antialiased;overflow-wrap:break-word;
  min-height:100vh;min-height:100svh;display:flex;flex-direction:column}
main{flex:1 0 auto}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;margin:0;padding:0;cursor:pointer;text-align:left}
h1,h2,p{margin:0}
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
::selection{background:var(--ink);color:var(--white)}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:8px;top:-64px;z-index:60;background:var(--ink);color:var(--white);padding:12px 18px;font-size:13px;transition:top .18s}
.skip:focus{top:8px}
.frame{width:100%;max-width:var(--max);margin-inline:auto;padding-inline:var(--pad)}

/* ---------- mast: 48px in flow, no bar ----------
   Every page: wordmark at the left edge, Cart at the right. Nothing else
   lives up here, so the mark never moves between routes; back links belong
   to the page body, where they sit with the thing they return to. */
.mast{display:flex;align-items:center;justify-content:space-between;
  gap:var(--space-4);padding-top:var(--space-4);padding-bottom:var(--space-5);min-height:72px}
.mark{font:var(--type-lockup);letter-spacing:var(--track-lockup);margin:0}
/* The mark is two words of street name plus a rider; the rider is a size down
   so the lockup still reads as one name, not two labels. */
.mark a,a.mark{display:flex;align-items:baseline;gap:var(--space-2);white-space:nowrap;text-transform:uppercase}
.mark .rider{font:var(--type-rider);letter-spacing:.1em}
/* A 20-24px wordmark still deserves a 44px target. On the wall the anchor sits
   inside the h1; on the other pages the anchor *is* the mark, so both cases
   are named here — one element must not have two tap heights. */
.mark a,a.mark{padding-block:10px;margin-block:-10px}
/* Below 640 the frame is too narrow for one line once the cart is filled, so
   the lockup stacks. The stacked row is 47px (not 24), so the top pad drops one
   step and min-height holds the mast at exactly 72px: the mark must not move
   between breakpoints, and the stacked block must still clear the cart. */
@media(max-width:639px){.mark a,a.mark{flex-direction:column;gap:0;align-items:flex-start}
  .mast{padding-top:var(--space-3)}}
.cart{font:var(--type-label);color:var(--muted);display:flex;align-items:center;gap:var(--space-1);
  padding:0;min-height:var(--tap);min-width:var(--tap);justify-content:flex-end}
.cart:hover{color:var(--ink)}
.cart b{font-weight:500;color:var(--ink)}
.cart[data-empty='true']{color:var(--muted)}
.mark a{color:inherit}
/* The right slot is the cart on every page; the home page adds the search
   field to it. Search exists only where the wall does. */
.mast-tools{display:flex;align-items:center;gap:var(--space-4);min-width:0}

/* The mast wordmark is a drawing, not a string: ESSEX STREET over a rule and
   MFG. CO., so the two words keep their spacing at any width. It replaces the
   text lockup in place and inherits the ink colour. */
.brand-mark{display:inline-flex;align-items:center;color:inherit;text-decoration:none;
  width:var(--brand-w);max-width:100%;padding-block:4px;margin-block:-4px}
.brand-logo{display:block;width:100%;height:auto;overflow:visible}
.brand-title{font-family:var(--brand-serif);font-size:39px;font-weight:700;letter-spacing:-.02em;fill:currentColor}
.brand-rider{font-family:var(--brand-serif);font-size:13px;font-weight:700;letter-spacing:.18em;fill:currentColor}
.brand-rule{stroke:currentColor;stroke-width:1;fill:none}
/* The mark is drawn text inside a viewBox: textLength keeps it inside the box,
   so the 176px phone lockup is the same artwork, not a clipped one. */
@media(max-width:639px){:root{--brand-w:176px}}

/* ---------- wall: uniform mounted plates, no chrome ---------- */
.wall{display:grid;grid-template-columns:minmax(0,1fr);column-gap:var(--gutter);row-gap:var(--row);padding-bottom:var(--space-8)}
@media(min-width:640px){.wall{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:1200px){.wall{grid-template-columns:repeat(3,minmax(0,1fr))}}

.card{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-3);min-width:0;scroll-margin-top:8px}
.card>*{min-width:0}
/* No mount, no frame: the plate is the maker's own white composite and the
   grid is held apart by gutters and row rhythm, not by drawn boxes. The
   composites carry a 1px #F5 edge; crop it so no box is drawn. */
.card .media img,.gallery-main img,.gallery-thumb img{clip-path:inset(1.5px)}
.card .media,.item-media{aspect-ratio:1;min-width:0;background:transparent;padding:0;outline:0}
.item-gallery{display:grid;gap:var(--space-3);min-width:0}
/* The plate is capped by the viewport so its strip of views is always in the
   first screen: the control and the thing it changes must share a screen. */
.gallery-main{aspect-ratio:1;width:min(100%,var(--plate-cap));display:grid;min-width:0}
.gallery-main>*{grid-area:1/1;min-width:0}
.gallery-main picture[hidden]{display:none}
.gallery-main img{width:100%;height:100%;object-fit:contain;object-position:50% 50%}
.gallery-thumbs{display:flex;flex-wrap:wrap;gap:var(--space-4)}
.gallery-thumb{display:grid;gap:var(--space-1);justify-items:start;padding:0;border:0;
  background:transparent;cursor:pointer}
.gallery-thumb img{width:var(--thumb);height:var(--thumb);object-fit:contain;display:block;
  opacity:.66;transition:opacity .12s ease}
.gallery-thumb:hover img{opacity:.88}
.gallery-thumb[aria-pressed='true'] img{opacity:1}
/* The view's name is the control's label, underlined when it is the one shown —
   the same selected-state language as the size ruler. No boxes anywhere. */
.gallery-label{font:500 14px/20px var(--text);letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);padding-bottom:var(--space-1);border-bottom:2px solid transparent}
.gallery-thumb[aria-pressed='true'] .gallery-label{color:var(--ink);border-bottom-color:var(--ink)}
@media(max-width:1023px){:root{--plate-cap:max(220px,calc(100svh - 256px))}}
@media(max-width:639px){:root{--thumb:64px}}
.card .media img,.item-media img{width:100%;height:100%;object-fit:contain;object-position:50% 50%}
.card .card-row{display:flex;justify-content:space-between;align-items:baseline;gap:var(--space-3);min-width:0}
.card .name{font:var(--type-card);letter-spacing:.03em;text-transform:uppercase;
  overflow-wrap:break-word;min-width:0}
.card .price{font:var(--type-price);font-variant-numeric:tabular-nums;color:var(--muted);white-space:nowrap}
@media(min-width:1024px){:root{--type-card:600 20px/24px var(--display);--type-price:500 15px/24px var(--text)}}
@media(min-width:1440px){:root{--type-card:600 22px/26px var(--display);--type-price:500 15px/26px var(--text)}}

/* One listing system: the underline is the hover/focus/press affordance for
   every card, and never exists at rest or once visited.
   Scoped on purpose: an unscoped `a:visited{color:inherit}` is (0,1,1) and
   outranks every single-class colour rule below it — it made the drawer's
   Checkout label ink on ink for anyone who had ever clicked it. */
.card a:visited{color:inherit}
/* Dark blocks carry their own colour, so they must answer :visited too. */
.panel-cta:visited{color:#fff}
.pay-btn:visited{color:var(--white)}
.skip:visited{color:var(--white)}
.card:is(:hover,:focus-visible,:active) .name{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}

/* ---------- foot: a full-bleed band across the bottom ----------
   The rule spans the viewport; the content is distributed edge to edge
   with its own page padding, so it reads as a colophon band, not a card. */
.foot{margin-top:auto;width:100%;border-top:1px solid var(--line);
  color:var(--text-2);font:var(--type-micro)}
/* A baseline grid row + three baseline-aligned zones is unstable: a link's
   padded box makes the columns scatter over half a page. `start` keeps the
   band on one row, and the three zones share its top edge. */
.foot-in{display:grid;grid-template-columns:1fr auto 1fr;align-items:start;
  column-gap:var(--space-4);padding-top:var(--space-5);padding-bottom:var(--space-6)}
@supports(padding:env(safe-area-inset-bottom)){.foot-in{padding-bottom:calc(var(--space-6) + env(safe-area-inset-bottom))}}
.foot p{margin:0;min-width:0}
.foot-brand{justify-self:start;display:flex;flex-wrap:wrap;gap:0 var(--space-2)}
/* One display string in the band: at 14px a two-part lockup would make the
   rider equal the name and the hierarchy would vanish. */
.foot-brand b{font:var(--type-imprint);letter-spacing:.06em;text-transform:uppercase;font-weight:800}
.foot-place{justify-self:center;white-space:nowrap}
.foot-mail{justify-self:end;min-width:0;overflow-wrap:anywhere}
.foot a{color:inherit;text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px;
  display:inline-block;padding:13px 8px;margin:-13px -8px}
.foot a:hover{color:var(--ink)}
@media(max-width:639px){
  /* row-gap one step larger: the mail link carries a 13px tap pad that would
     otherwise reach up into the "New York / 2026" line above it. */
  .foot-in{grid-template-columns:1fr;row-gap:var(--space-4);padding-top:var(--space-4);padding-bottom:var(--space-5)}
  .foot-brand,.foot-place,.foot-mail{justify-self:start}
}

/* ---------- cart panel ----------
   A decision surface, not chrome: it may never be set smaller than the page
   behind it. The title is the wordmark; every total is the figure size. */
.veil{position:fixed;inset:0;z-index:70;background:rgb(20 19 17 / .2);opacity:0;transition:opacity .18s var(--ease)}
.veil.is-on{opacity:1}
/* Full height on purpose: the drawer is a panel of the shop, not a receipt that
   ends under its last row. It keeps the viewport edge-to-edge on the right. */
.panel{position:fixed;z-index:71;top:0;right:0;bottom:0;width:var(--panel-w);background:var(--white);
  border-left:1px solid var(--ink);
  display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,1fr) auto;
  transform:translateX(101%);transition:transform .22s var(--ease)}
.panel.is-on{transform:none}
.panel-top{display:flex;justify-content:space-between;align-items:center;
  padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--line);
  font:var(--type-label);color:var(--muted)}
.panel-top>span{font:var(--type-mark);letter-spacing:.06em;text-transform:uppercase;color:var(--ink)}
.panel-top button{font:var(--type-label);color:var(--muted);padding:10px;margin:-10px;
  min-height:var(--tap);min-width:var(--tap);display:inline-flex;align-items:center;justify-content:center}
.panel-top button:hover{color:var(--ink)}
.panel-items{overflow:auto;min-height:0;padding:0 var(--space-5) var(--space-2);
  scrollbar-gutter:stable}
/* A cart line, in the order a shopper reads it: what it is, which size, how
   many, what it costs, and the one destructive action tucked at the end. */
.row-item{display:grid;grid-template-columns:96px minmax(0,1fr) auto;
  gap:var(--space-4);align-items:start;padding:var(--space-4) 0;border-bottom:1px solid var(--line)}
.row-item:last-child{border-bottom:0}
.row-item img,.row-plate{width:96px;height:96px;object-fit:cover;clip-path:inset(3%);display:block}
.row-main{display:grid;gap:2px;min-width:0;padding-top:2px}
.row-item .nm{display:block;font:600 16px/20px var(--display);letter-spacing:.03em;text-transform:uppercase}
.row-item .mt{display:block;font:var(--type-micro);color:var(--muted)}
.row-side{display:grid;gap:var(--space-2);justify-items:end;padding-top:2px}
.row-item .am{font:500 16px/20px var(--text);font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.qty{display:flex;align-items:center;gap:6px;margin-top:var(--space-2);justify-self:start}
.qty button{width:44px;height:44px;border:1px solid var(--line-strong);
  display:grid;place-items:center;font:400 15px/1 var(--text);color:var(--ink)}
.qty button:hover{border-color:var(--ink)}
.qty span{min-width:20px;text-align:center;font:500 14px/1 var(--text)}
/* The destructive action is a quiet word, not a second button. */
.row-remove{font:400 14px/20px var(--text);color:var(--muted);text-decoration:underline;min-height:44px;padding:10px 0;
  text-underline-offset:3px;padding:6px 0;min-height:32px}
.row-remove:hover{color:var(--ink);text-decoration-thickness:2px}
.panel-empty{padding:var(--space-7) 0;font:var(--type-body);color:var(--muted)}
.panel-empty a{color:var(--ink);text-decoration:underline;text-underline-offset:3px}
.panel-foot{border-top:1px solid var(--line);padding:var(--space-4) var(--space-5);
  display:flex;align-items:baseline;gap:var(--space-3)}
.panel-foot .sum{display:flex;align-items:baseline;gap:var(--space-2);margin-right:auto}
.panel-foot span{font:var(--type-micro);color:var(--muted)}
.panel-foot b{font:var(--type-figure)}
@supports(padding:env(safe-area-inset-bottom)){
  .panel-foot{padding-bottom:calc(var(--space-4) + env(safe-area-inset-bottom))}
}
.panel-cta{background:var(--ink);color:#fff;
  min-height:52px;min-width:0;padding:0 var(--space-4);text-align:center;
  display:flex;align-items:center;justify-content:center;font:600 16px/1 var(--text)}
@media(min-width:640px){.panel-cta{min-width:160px;padding:0 var(--space-5)}}
.panel-cta:hover{background:var(--ink-press)}
.panel-cta[aria-disabled='true']{background:transparent;color:var(--muted);
  box-shadow:inset 0 0 0 1px var(--line);pointer-events:none}
/* A drawer that stops 10px short of a phone's edge is a bug, not an inset. */
@media(max-width:639px){.panel{width:100%;border-left:0}
  .panel-foot{flex-wrap:wrap;row-gap:var(--space-3)}
  .panel-cta{width:100%;min-width:0}}
html[data-bag-lock]{overflow:hidden}
/* ---------- shirt page ---------- */
/* `.item` used to match both <main> and the data div inside it, so every
   padding applied twice. Scope it to the page shell. */
/* The plate wants the page, not a 520px column beside 460px of void. From
   1024 the buy block sits beside it, which keeps the size ruler and the add
   button high on the screen without shrinking the artwork. Only the stacked
   phone/tablet layout has to trade plate size for a visible buy button, so
   only that layout asks the viewport how tall it is. */
.frame.item{padding-top:var(--space-2);padding-bottom:var(--space-7);margin-inline:auto;max-width:var(--max)}
@media(max-width:1023px){
  /* Capping .item shrank the buy column to 76px on short screens; cap the
     gallery instead and keep a hard floor. */
  .frame.item .item{max-width:none;margin-inline:0}
  .frame.item .item>.item-gallery{width:100%;max-width:min(760px,max(300px,100svh - 440px));margin-inline:auto}
}
@media(min-width:1024px){
  /* The pair reads as one object: cap it instead of letting the two columns
     sprawl to the frame edge, and keep the gutter modest. */
  /* Columns follow the plate, not a ratio: a 1.2fr column left the image
     narrower than its cell and opened a gap before the buy block. */
  .frame.item .item{display:grid;grid-template-columns:minmax(0,var(--plate-cap)) minmax(320px,1fr);
    column-gap:var(--space-6);align-items:start;
    max-width:calc(var(--plate-cap) + var(--space-6) + 440px);margin-inline:auto}
  .frame.item .item-buy{padding-top:0}
}
@media(min-width:1440px){.frame.item .item{max-width:calc(var(--plate-cap) + var(--space-6) + 480px)}}
/* The product column is capped and centred on wide screens, so the back link
   must ride the same column instead of hugging the frame edge. */
@media(min-width:1024px){
  .frame.item .back{display:block;max-width:calc(var(--plate-cap) + var(--space-6) + 440px);margin-inline:auto}
}
@media(min-width:1440px){
  .frame.item .back{max-width:calc(var(--plate-cap) + var(--space-6) + 480px)}
}

.item-buy{display:grid;gap:var(--space-2);padding-top:var(--space-5)}
.item-buy h1{font:var(--type-h1-item);text-transform:uppercase;letter-spacing:.004em}
.item-buy .price{font:var(--type-money);color:var(--ink)}
.item-buy .sizes{display:flex;height:52px;margin-top:var(--space-1);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.item-buy .s{position:relative;flex:1 1 0;min-width:0;display:flex;align-items:center;justify-content:center;
  text-align:center;padding-inline:var(--space-2);font:500 16px/1 var(--text)}
.item-buy .s:hover{background:rgb(20 19 17 / .05)}
.item-buy .s[aria-checked='true']{background:transparent;color:var(--ink);font-weight:600;
  text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:6px}
.add{margin-top:var(--space-3);width:100%;height:56px;background:var(--ink);color:var(--white);
  font:600 16px/1 var(--text);display:flex;align-items:center;justify-content:center;transition:background .12s}
.add:hover:not(:disabled){background:var(--ink-press)}
/* An inactive control should look deliberately inactive, not greyed out of
   existence: the ink block is reserved for a live action. */
.add:disabled{background:transparent;color:var(--text-2);box-shadow:inset 0 0 0 1px var(--line);cursor:default}
/* The standing spec: the facts every shirt shares, so the column never depends
   on a product description being written. */
.item-spec{margin:var(--space-5) 0 0;border-top:1px solid var(--line)}
.item-spec div{display:flex;align-items:baseline;justify-content:space-between;gap:var(--space-4);
  padding:var(--space-3) 0;border-bottom:1px solid var(--hair)}
.item-spec dt{font:500 14px/20px var(--text);letter-spacing:.06em;text-transform:uppercase;color:var(--muted)}
.item-spec dd{font:var(--type-micro);color:var(--ink);text-align:right;margin:0}

/* ---------- checkout: one column, no furniture ---------- */
.checkout{padding-top:8px;padding-bottom:120px}
/* One left edge under the mast. The reading column hangs from the frame edge
   instead of centring itself, so it starts under the mark on every route; the
   cap adds the frame's own padding so the text still measures 640px. */
.page,.info,.checkout{max-width:var(--max);margin-inline:auto}
/* The frame is centred on wide screens; the reading columns stay at the
   measure so they hang from the same left edge as the mast and the wall. */
.page>*,.info>*,.checkout>*{max-width:var(--measure)}
.back{display:inline-block;font:var(--type-label);color:var(--muted);padding:10px 0;min-height:44px;margin-bottom:var(--space-2)}
.back:hover{color:var(--ink)}
.lines{display:grid;border-top:1px solid var(--line)}
.line{display:grid;grid-template-columns:96px minmax(0,1fr) auto;gap:var(--space-4);align-items:start;padding:var(--space-4) 0;border-bottom:1px solid var(--line)}
.line img{width:96px;height:96px;object-fit:cover;clip-path:inset(3%)}
.line b{display:block;font:500 18px/24px var(--text)}
.line small{display:block;font:var(--type-micro);color:var(--muted)}
.line .amt{font:var(--type-money);text-align:right;white-space:nowrap}

.money{padding:16px 0;display:grid;gap:6px;border-bottom:1px solid var(--line)}
.money div{display:flex;justify-content:space-between;gap:12px;font:var(--type-money);color:var(--muted)}
.money div b{font-weight:500;color:var(--ink)}
.money .total{font:var(--type-label);color:var(--ink);padding-top:var(--space-2);align-items:baseline}
.money .total strong{font:var(--type-figure)}

.form{display:grid;gap:14px;padding-top:18px}
.f{display:grid;gap:2px;min-width:0}
.f>span{font:var(--type-label);color:var(--muted)}
.f input,.f select{width:100%;background:transparent;border:0;border-bottom:1px solid var(--line-strong);border-radius:0;
  padding:7px 0 9px;font:var(--type-body);transition:border-color .12s}
.f input:focus,.f select:focus{border-bottom-color:var(--ink)}
.f input:focus-visible,.f select:focus-visible{outline:2px solid var(--ink);outline-offset:2px}
.f select{appearance:none;background-image:linear-gradient(45deg,transparent 49%,var(--ink) 50%),linear-gradient(-45deg,transparent 49%,var(--ink) 50%);
  background-position:calc(100% - 12px) 52%,calc(100% - 7px) 52%;background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.f.is-bad input,.f.is-bad select{border-bottom-color:var(--alert)}
.f-error{font:var(--type-micro);color:var(--alert)}
.form-msg{font:var(--type-micro);color:var(--alert)}
.form-msg:empty{display:none}
.row{display:grid;gap:14px;grid-template-columns:1fr 1fr}
.promise{font:400 14px/22px var(--text);color:var(--muted);padding-top:var(--space-1)}

.paybar{position:fixed;left:0;right:0;bottom:0;z-index:40;background:var(--white);border-top:1px solid var(--ink);
  display:flex;align-items:center;gap:var(--space-3);padding:var(--space-3) var(--pad);min-height:72px}
@supports(padding:env(safe-area-inset-bottom)){.paybar{padding-bottom:calc(8px + env(safe-area-inset-bottom))}}
.paybar .sum{margin-right:auto;font:var(--type-label)}
.paybar .sum strong{font:var(--type-figure)}
.pay-btn{background:var(--ink);color:var(--white);height:52px;padding:0 var(--space-5);display:flex;align-items:center;
  justify-content:center;font:600 16px/1 var(--text);white-space:nowrap;transition:background .12s}
.pay-btn:hover:not(:disabled){background:var(--ink-press)}
.pay-btn:disabled{background:rgb(20 19 17 / .35);cursor:not-allowed}
@media(min-width:720px){.pay-btn{min-width:300px;justify-content:center}}

/* ---------- return / receipt / info ---------- */
.page{padding-top:8px;padding-bottom:var(--space-10)}
.page h1{font:var(--type-h1);text-transform:uppercase;letter-spacing:.004em;padding-top:8px;padding-bottom:16px}
.page p{color:var(--muted);padding-bottom:var(--space-3)}
.page p b{color:var(--ink);font-weight:500}
.rec-line{display:flex;justify-content:space-between;gap:12px;padding:10px 0;border-bottom:1px solid var(--line);font:var(--type-micro)}
.rec-line b{font-weight:500}
.rec-total{display:flex;justify-content:space-between;align-items:baseline;padding-top:var(--space-3);font:var(--type-label)}
.rec-total strong{font:var(--type-figure)}
.info{padding-top:8px;padding-bottom:var(--space-10)}
.info h1{font:var(--type-h1);text-transform:uppercase;letter-spacing:.004em;padding-bottom:20px}
.info dl{display:grid;gap:18px;margin:0;border-top:1px solid var(--line);padding-top:20px}
.info dt{font:600 14px/20px var(--text);color:var(--muted);text-transform:uppercase;letter-spacing:.04em;padding-bottom:3px}
.info dd{margin:0;font:var(--type-body);color:var(--ink)}
.info dd a{border-bottom:1px solid var(--line);padding-bottom:1px}
.info dd span{color:var(--muted)}

/* Empty collection and page-level links, in the same voice as everything else. */
.note{grid-column:1/-1;font:var(--type-body);color:var(--muted);padding:var(--space-5) 0 var(--space-6)}
.page a{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}
.page a:hover{color:var(--ink)}
.muted{color:var(--muted)}
.item-desc{max-width:38rem;padding-top:var(--space-4)}
.item-desc p{font:var(--type-body);color:var(--muted);padding-bottom:var(--space-3)}
.item-desc p:last-child{padding-bottom:0}

/* ---------- find: a field in the mast ----------
   Minimal by design: the wordmark and Cart already own the header, so search
   is one quiet 14px field between them — no icon, no box, no heading, no
   count. Just a hairline that inks on focus, sitting where the Search word
   sits on the pages that do not carry the wall. On the wall it filters in
   place; on any other page Enter takes the query to /?q=. */
.mast-find{display:flex;align-items:center;min-width:0}
.mast-find input{width:clamp(130px,16vw,200px);height:var(--tap);background:transparent;border:0;border-radius:0;
  border-bottom:1px solid var(--line-strong);padding:0;line-height:var(--tap);
  font:var(--type-label);color:var(--ink);caret-color:var(--ink)}
.mast-find input::placeholder{color:var(--muted);opacity:1}
.mast-find input:focus{outline:0;border-bottom-color:var(--ink)}
/* Below 640 the field cannot share a row with a stacked lockup and a filled
   cart, so it takes the header's second row at full width; Cart stays
   top-right. These rules live after the mast definitions on purpose: the
   display:contents override has to win on source order. */
@media(max-width:639px){
  .mast{flex-wrap:wrap}
  .mast-tools{display:contents}
  .mast-find{order:3;flex:1 0 100%;margin-top:var(--space-1)}
  .mast-find input{width:100%;font:var(--type-body)}
  .cart{order:2;margin-left:auto}
}
/* A settling query can shorten the wall enough to add or remove the page
   scrollbar. Hold the gutter only while a query is active, so the rest of the
   shop (including the full-bleed footer) is untouched. */
html[data-find]{scrollbar-gutter:stable}

/* The only authored motion on the storefront: a plate arriving in the
   gallery. Reduced motion is already flattened globally above. */
@keyframes plate-in{from{opacity:.65}to{opacity:1}}
.gallery-main picture:not([hidden]) img{animation:plate-in .18s var(--ease)}
.gallery-thumb img{opacity:1}

@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
}

/* Phones: the buy button must be reachable without scrolling past a full
   plate. Tighten the gallery cap and the title just enough (measured at 360
   and 390) without changing the design language. */
@media(max-width:639px){
  .frame.item .item>.item-gallery{max-width:min(760px,max(240px,100svh - 540px))}
  .item-buy h1{font:800 36px/36px var(--display)}
  .item-buy .add{margin-top:var(--space-2)}
}
