/* ============================================================
   The Pig Pen — stylesheet
   Direction "Scrapbook Picnic": paper ground, inked outlines,
   stitched patches, pastel cloth and hand-drawn energy.
   ============================================================ */

:root {
  --paper: #fbf6ec;
  --ink: #1b1815;
  --red: #e7a0a2;
  --red-dark: #934e59;
  --blue: #9dbce5;
  --pink: #e7b5d1;
  --yellow: #efd892;
  --mint: #b9d9c5;
  --lilac: #cbb9df;
  --tint: #f0eadf;
  --white: #fffdf8;

  --ink-72: rgba(27, 24, 21, 0.72);
  --ink-60: rgba(27, 24, 21, 0.6);
  --ink-45: rgba(27, 24, 21, 0.45);
  --ink-25: rgba(27, 24, 21, 0.25);
  --ink-12: rgba(27, 24, 21, 0.12);

  --rule: 1.5px solid var(--ink);
  --rule-soft: 1.5px solid var(--ink-25);
  --shell: 1180px;
  --pad: clamp(18px, 4vw, 40px);

  --display: "Bricolage Grotesque", "Trebuchet MS", system-ui, sans-serif;
  --body: Karla, system-ui, -apple-system, sans-serif;
  --mono: "Courier Prime", ui-monospace, Menlo, Consolas, monospace;
  --serif: "Instrument Serif", Georgia, serif;
}

*, *::before, *::after { box-sizing: border-box; }
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background-color: var(--paper);
  background-image: radial-gradient(rgba(27, 24, 21, 0.055) 0.55px, transparent 0.7px);
  background-size: 6px 6px;
  color: var(--ink);
  font: 400 16px/1.55 var(--body);
  overflow-wrap: break-word;
}

img { max-width: 100%; display: block; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 0.98;
  margin: 0;
  text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }

a { color: var(--red-dark); text-decoration-thickness: 1.5px; text-underline-offset: 3px; }
a:hover { color: var(--red-dark); }

:focus-visible {
  outline: 3px solid var(--blue);
  outline-offset: 2px;
  border-radius: 2px;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  padding: 12px 18px; background: var(--ink); color: var(--paper);
  font: 700 14px var(--body); text-decoration: none;
}
.skip:focus { left: 8px; top: 8px; color: var(--paper); }

.shell { max-width: var(--shell); margin: 0 auto; padding-inline: var(--pad); }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---------- Typography helpers ---------- */

.eyebrow {
  font: 700 11px var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--red-dark);
  margin: 0 0 14px;
}
.eyebrow--ink { color: var(--ink-60); }
.eyebrow--pink { color: var(--pink); }

.meta { font: 400 12px var(--mono); color: var(--ink-60); }
.lede { font: 400 clamp(16px, 1.9vw, 18px)/1.55 var(--body); color: var(--ink-72); max-width: 46ch; }
.quote { font: italic 400 clamp(20px, 2.6vw, 26px)/1.25 var(--serif); margin: 0; }
/* Quote marks live in CSS so the text stays clean in the admin. */
.quote::before { content: "\201C"; }
.quote::after { content: "\201D"; }

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 14px 24px;
  border: 2px solid var(--ink);
  border-radius: 999px 920px 999px 880px;
  background: var(--paper);
  color: var(--ink);
  font: 700 15px var(--body);
  text-decoration: none;
  cursor: pointer;
  box-shadow: 3px 3px 0 rgba(27, 24, 21, 0.22);
  transition: transform 0.12s ease, background 0.15s ease, color 0.15s ease, box-shadow 0.12s ease;
}
.btn:hover { transform: translate(-1px, -2px) rotate(-1deg); box-shadow: 4px 5px 0 rgba(27, 24, 21, 0.2); color: var(--ink); }
.btn:active { transform: translate(1px, 1px) rotate(0); box-shadow: 1px 1px 0 rgba(27, 24, 21, 0.2); }
.btn--primary { background: var(--red); border-color: var(--ink); color: var(--ink); }
.btn--primary:hover { background: #f0b2b3; border-color: var(--ink); color: var(--ink); }
.btn--ink { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.btn--ink:hover { color: var(--paper); }
.btn--paper { background: var(--paper); border-color: var(--paper); color: var(--ink); }
.btn--sm { padding: 9px 16px; font-size: 13px; }
.btn--block { display: flex; width: 100%; }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; transform: none; }

.link-mono {
  font: 400 12px var(--mono);
  color: var(--ink);
  border-bottom: 1.5px solid var(--ink);
  text-decoration: none;
  padding-bottom: 1px;
}
.link-mono:hover { color: var(--red-dark); border-color: var(--red-dark); }

/* ---------- Header ---------- */

.site-header {
  position: sticky; top: 0; z-index: 40;
  background: rgba(251, 246, 236, 0.96);
  border-bottom: 2px solid var(--ink);
  backdrop-filter: blur(8px);
}
.site-header::after {
  content: "";
  position: absolute; left: 0; bottom: -2px;
  width: var(--page-progress, 0%); height: 2px;
  background: repeating-linear-gradient(90deg, var(--red) 0 9px, transparent 9px 13px);
  pointer-events: none;
}
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px; padding-block: 17px;
}
.brand { display: flex; align-items: center; gap: 13px; text-decoration: none; color: var(--ink); }
.brand__mark {
  width: 52px; height: 52px; flex: none;
  border: 2px solid var(--ink); border-radius: 49% 44% 52% 46%;
  display: grid; place-items: center;
  font-size: 0; color: var(--ink); text-align: center;
  transform: rotate(-7deg);
  background-color: #fde7df;
  background-image:
    repeating-linear-gradient(0deg, rgba(231,160,162,.2) 0 6px, transparent 6px 12px),
    repeating-linear-gradient(90deg, rgba(231,160,162,.2) 0 6px, transparent 6px 12px);
  box-shadow: 3px 3px 0 var(--yellow), inset 0 0 0 4px #fde7df, inset 0 0 0 5.5px var(--red-dark);
}
.brand__mark::before { content: "P·P"; font: 700 10px/1 var(--mono); letter-spacing: -0.06em; }
.brand__wordmark { display: flex; flex-direction: column; align-items: flex-start; line-height: 1; }
.brand__name {
  font: 800 clamp(20px, 2.4vw, 23px)/1 var(--display);
  letter-spacing: -0.04em; white-space: nowrap;
}
.brand__byline {
  margin-top: 4px;
  font: italic 400 clamp(16px, 1.8vw, 19px)/.95 var(--serif);
  letter-spacing: 0.015em; color: var(--red-dark); white-space: nowrap;
  transform: rotate(-1.5deg); transform-origin: left center;
}
@media (max-width: 520px) {
  .site-header__inner { gap: 10px; padding-block: 12px; }
  .brand { gap: 8px; }
  .brand__mark { width: 42px; height: 42px; }
  .brand__name { font-size: 18px; }
  .brand__byline { font-size: 15px; margin-top: 3px; }
}

.nav { display: flex; align-items: center; gap: 12px; }
.nav a {
  font: 600 14px var(--body);
  color: var(--ink);
  text-decoration: none;
  padding-bottom: 2px;
  border-bottom: 2px solid transparent;
}
.nav a:hover { border-color: var(--ink-25); }
.nav a[aria-current="page"] { border-color: var(--red); }
.nav a[href="shop.html"] {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 40px; padding: 0 18px;
  border: 0; border-radius: 999px;
  background: var(--red); color: var(--ink); font-weight: 700;
  box-shadow: 2px 2px 0 var(--ink);
  transition: transform .12s ease, background .15s ease;
}
.nav a[href="shop.html"]:hover { background: #f0b2b3; color: var(--ink); transform: translate(-1px,-1px) rotate(-1deg); }
.nav a[href="shop.html"][aria-current="page"] { background: var(--yellow); color: var(--ink); }
.nav a.nav__bag {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 40px; padding: 0 18px;
  border: 0; border-radius: 999px;
  box-shadow: inset 0 0 0 2px var(--ink);
  line-height: 1; white-space: nowrap;
}
.nav a.nav__bag:hover { background: var(--white); color: var(--ink); box-shadow: inset 0 0 0 2px var(--red); }
.nav a.nav__bag[aria-current="page"] { box-shadow: inset 0 0 0 2px var(--red); }
.nav__bag[data-full="true"] { background: var(--ink); color: var(--paper); }
.nav__bag[data-bump="true"] { animation: pp-bag-bump 0.42s ease-out; }
@keyframes pp-bag-bump {
  0%, 100% { transform: rotate(0) scale(1); }
  35% { transform: rotate(-3deg) scale(1.1); }
  70% { transform: rotate(2deg) scale(0.98); }
}

.nav-toggle {
  display: none; align-items: center; gap: 8px;
  padding: 7px 13px; border: 1.5px solid var(--ink); border-radius: 999px;
  background: none; font: 700 12px var(--body); color: var(--ink); cursor: pointer;
}

@media (max-width: 820px) {
  .nav-toggle { display: inline-flex; }
  .nav {
    display: none;
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper);
    border-bottom: 2px solid var(--ink);
    padding: 6px var(--pad) 18px;
  }
  .nav[data-open="true"] { display: flex; }
  .nav a {
    padding: 13px 0; font-size: 16px;
    border-bottom: 1px solid var(--ink-12);
  }
  .nav a[aria-current="page"] { color: var(--red-dark); border-color: var(--ink-12); }
  .nav a[href="shop.html"] { margin: 8px 0 2px; }
  .nav a.nav__bag { margin-top: 10px; padding: 13px; text-align: center; border: 0; box-shadow: inset 0 0 0 2px var(--ink); }
}

/* ---------- The shop ribbons ----------
   Pinned to the edge of the page on every screen, because they are the
   way into the shop now. Rolled up, a ribbon shows its short name
   written down the roll; hover or keyboard focus unrolls it to the full
   "Pig Pen —" name, the roll spinning thinner as the band comes off it
   and a swallowtail notch opening at the loose end. The shop you are
   already standing in stays unrolled the whole time.

   Only the sections that declare a ribbon get one, so the rail is a
   flex column rather than three slots — a fourth is a content change.

   Below the shell width there is nowhere at the side for a 230px ribbon
   to hang without lying across the page, so the same markup becomes a
   row of ribbon ends along the bottom instead. --rail-side and
   --rail-bottom hold the page itself out from under them; both live on
   <html>, which pages.js marks with data-ribbons once the ribbons
   exist, so a page that never drew any keeps every pixel it had.
   ---------------------------------------------------------------- */

html[data-ribbons] { --rail-side: 152px; --rail-bottom: 0px; }
/* An unrolled ribbon is two and a half times the width of a rolled one,
   and on a shop page one of them is unrolled for good. */
html[data-ribbons][data-ribbon-open] { --rail-side: 430px; }

/* Past this width the shell's own gutter is already wider than the
   ribbons, so almost nothing needs reserving and the page stays centred. */
@media (min-width: 1560px) {
  html[data-ribbons] { --rail-side: 0px; }
  html[data-ribbons][data-ribbon-open] { --rail-side: 206px; }
}

body { padding-inline-start: var(--rail-side, 0px); padding-bottom: var(--rail-bottom, 0px); }

.ribbons {
  position: fixed; z-index: 35;          /* under the sticky header (40) and the toast (60) */
  left: 0; top: 50%; transform: translateY(-50%);
  --rib-h: 104px;                         /* how wide the ribbon itself is */
  --rib-stub: 16px;                       /* the end pinned to the page */
  --rib-tab: 78px;                        /* what's showing while it's rolled */
  --rib-roll: 38px;
}
.ribbons__list {
  display: flex; flex-direction: column; gap: 19px;
  margin: 0; padding: 0; list-style: none;
}

.ribbon {
  /* An unknown tone still looks intentional rather than unstyled. */
  --face: var(--ink); --fold: #000; --patch: #fff2d9; --letters: var(--ink);
  /* pages.js measures the label into --open-w. The fallback keeps an
     unknown hand-written ribbon useful even before JavaScript finishes. */
  --open-w: 380px;
  font: 900 18px/1 var(--display);
  letter-spacing: 0.045em;
  text-transform: uppercase;
}
.ribbon--red  { --face: #e7a0a2; --fold: #b96570; --patch: #ffe8da; }
.ribbon--blue { --face: #9dbce5; --fold: #6f91c0; --patch: #e9f2ff; }
.ribbon--pink { --face: #e7b5d1; --fold: #b97d9e; --patch: #fae8f1; }
.ribbon--red, .ribbon--blue, .ribbon--pink { --letters: var(--ink); }

.ribbon__link {
  position: relative;
  display: flex; align-items: stretch;
  height: var(--rib-h);
  color: var(--letters);
  text-decoration: none;
  /* drop-shadow rather than box-shadow so the notch throws one too. */
  filter: drop-shadow(4px 5px 0 rgba(27, 24, 21, 0.18));
  transition: filter 0.24s ease, transform 0.24s ease;
}
.ribbon__link:hover, .ribbon.is-open .ribbon__link { color: var(--letters); }
.ribbon__link:hover,
.ribbon__link:focus-visible,
.ribbon.is-open .ribbon__link { filter: drop-shadow(6px 7px 0 rgba(27, 24, 21, 0.22)); transform: rotate(-1deg); }

/* The pinned end — a scrap of the tone's own gingham, stitched down. */
.ribbon__stub {
  position: relative; flex: none; width: var(--rib-stub);
  background-color: var(--fold);
  background-image:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, 0.2) 0 5px, transparent 5px 10px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0 5px, transparent 5px 10px);
}
.ribbon__stub::before {
  content: ""; position: absolute; inset: 4px 3px;
  border: 1.5px dashed rgba(27,24,21,.58); border-radius: 7px 3px 5px 4px;
}
.ribbon__stub::after {
  content: ""; position: absolute; top: 6px; bottom: 6px; left: 50%;
  border-left: 1.5px dashed rgba(255, 255, 255, 0.62);
}

/* The band. Grosgrain ribs across the weave, plus a light-to-dark wash
   down it so the ribbon reads as curved cloth and not a filled box. */
.ribbon__band {
  position: relative; flex: none; overflow: hidden;
  width: var(--rib-tab);
  background-color: var(--face);
  background-image:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.15) 0 1.5px, transparent 1.5px 5px),
    linear-gradient(180deg, rgba(255, 255, 255, 0.26) 0, transparent 34%,
      transparent 64%, rgba(27, 24, 21, 0.24) 100%);
  /* Same five points as the open state so the notch can be animated. */
  clip-path: polygon(0 0, 100% 0, 100% 50%, 100% 100%, 0 100%);
  transition: width 0.46s cubic-bezier(0.19, 0.86, 0.24, 1),
              clip-path 0.46s cubic-bezier(0.19, 0.86, 0.24, 1);
}
.ribbon--red .ribbon__band,
.ribbon--red .ribbon__tab {
  background-image:
    radial-gradient(rgba(255,255,255,.3) 1.4px, transparent 1.8px),
    linear-gradient(180deg, rgba(255,255,255,.25), transparent 38%, rgba(27,24,21,.16));
  background-size: 10px 10px, auto;
}
.ribbon--blue .ribbon__band,
.ribbon--blue .ribbon__tab {
  background-image:
    repeating-linear-gradient(-35deg, rgba(255,255,255,.25) 0 2px, transparent 2px 8px),
    linear-gradient(180deg, rgba(255,255,255,.25), transparent 38%, rgba(27,24,21,.16));
}
.ribbon--pink .ribbon__band,
.ribbon--pink .ribbon__tab {
  background-image:
    repeating-linear-gradient(0deg, rgba(255,255,255,.22) 0 5px, transparent 5px 10px),
    repeating-linear-gradient(90deg, rgba(255,255,255,.22) 0 5px, transparent 5px 10px),
    linear-gradient(180deg, rgba(255,255,255,.25), transparent 38%, rgba(27,24,21,.16));
}
.ribbon__name {
  position: absolute; z-index: 1; left: 32px; top: 50%; transform: translateY(-50%) rotate(-0.8deg);
  white-space: nowrap;
  padding: 12px 17px 13px;
  background: var(--patch);
  border: 2px solid var(--ink);
  border-radius: 8px 4px 9px 5px;
  box-shadow: 4px 4px 0 rgba(27,24,21,.18);
}
.ribbon__name::before {
  content: ""; position: absolute; inset: 5px;
  border: 1.5px dashed rgba(27,24,21,.56);
  border-radius: 5px 2px 6px 3px; pointer-events: none;
}

/* What's showing while it's rolled. aria-hidden, because the link is
   already named by the full name sitting under it. */
.ribbon__tab {
  position: absolute; z-index: 2; top: 0; bottom: 0; left: var(--rib-stub);
  width: var(--rib-tab);
  display: grid; place-items: center;
  padding: 8px 5px;
  writing-mode: vertical-lr;                 /* lr so two words read left to right */
  font: 900 15px/1.05 var(--display); letter-spacing: 0.045em; text-align: center;
  background-color: var(--patch);
  background-image: none;
  border-block: 2px solid var(--ink);
  pointer-events: none;
  /* Fades back in late, once the band has nearly finished re-rolling. */
  transition: opacity 0.16s ease 0.26s;
}
.ribbon__tab::after {
  content: ""; position: absolute; inset: 6px 7px;
  border: 1.5px dashed rgba(27,24,21,.52); border-radius: 7px 3px 6px 4px;
  pointer-events: none;
}
.ribbon--red .ribbon__tab,
.ribbon--blue .ribbon__tab,
.ribbon--pink .ribbon__tab {
  background-color: var(--patch); background-image: none;
}

/* The roll itself: concentric shading, and it gets thinner as the band
   comes off it, which is the part that sells the unrolling. */
.ribbon__roll {
  flex: none; width: var(--rib-roll);
  background-color: var(--fold);
  background-image:
    linear-gradient(90deg, rgba(27, 24, 21, 0.34) 0 2px, transparent 2px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.3) 0 1.5px,
      rgba(27, 24, 21, 0.16) 1.5px 3px, transparent 3px 7px),
    linear-gradient(180deg, rgba(255, 255, 255, 0.3) 0, transparent 30%,
      transparent 70%, rgba(27, 24, 21, 0.3) 100%);
  background-position: 0 0, 0 0, 0 0;
  border-radius: 0 13px 13px 0 / 0 50% 50% 0;
  transition: width 0.46s cubic-bezier(0.19, 0.86, 0.24, 1),
              background-position 0.46s linear,
              opacity 0.16s ease;
}

/* ---- unrolled: hovered, focused, or the shop you're already in ---- */

.ribbon__link:hover .ribbon__band,
.ribbon__link:focus-visible .ribbon__band,
.ribbon.is-open .ribbon__band {
  width: var(--open-w);
  clip-path: polygon(0 0, 100% 0, calc(100% - 15px) 50%, 100% 100%, 0 100%);
}
.ribbon__link:hover .ribbon__tab,
.ribbon__link:focus-visible .ribbon__tab,
.ribbon.is-open .ribbon__tab { opacity: 0; transition: opacity 0.14s ease; }
.ribbon__link:hover .ribbon__roll,
.ribbon__link:focus-visible .ribbon__roll,
.ribbon.is-open .ribbon__roll {
  width: 0; opacity: 0;
  background-position: 0 0, -30px 0, 0 0;
  transition: width 0.46s cubic-bezier(0.19, 0.86, 0.24, 1),
              background-position 0.46s linear,
              opacity 0.14s ease 0.3s;
}

/* The unrolling is the animation; the open ribbon is the information.
   Asked for less motion the ribbon still opens — it just arrives there
   instead of travelling. !important because the rules above re-declare
   `transition` at a higher specificity than any selector this can use. */
@media (prefers-reduced-motion: reduce) {
  .ribbons *, .ribbons *::before, .ribbons *::after { transition: none !important; }
}

/* ---- narrow screens: a row of ribbon ends along the bottom ---- */

@media (max-width: 1179px) {
  html[data-ribbons], html[data-ribbons][data-ribbon-open] {
    --rail-side: 0px; --rail-bottom: 60px;
  }
  .ribbons {
    left: 0; right: 0; top: auto; bottom: 0; transform: none;
    background: var(--paper); border-top: 2px solid var(--ink);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    transition: transform .24s cubic-bezier(.2,.72,.2,1);
  }
  html[data-ribbons-hidden] .ribbons { transform: translateY(105%); }
  html[data-ribbons-hidden] .ribbons:focus-within { transform: none; }
  .ribbons__list { flex-direction: row; align-items: flex-end; gap: 5px; height: 60px; padding-inline: 5px; }
  .ribbon { flex: 1 1 0; min-width: 0; }
  .ribbon__link { height: 48px; filter: none; }
  /* The one you're in hangs further down than the rest. */
  .ribbon.is-open .ribbon__link { height: 58px; transform: none; }
  .ribbon__stub, .ribbon__roll { display: none; }
  /* The full name has nowhere to go at this width, but it is still what
     names the link, so it is hidden the way .sr-only hides things. */
  .ribbon__band, .ribbon__link:hover .ribbon__band, .ribbon.is-open .ribbon__band {
    position: absolute; width: 1px; height: 1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: none; white-space: nowrap;
  }
  .ribbon__tab, .ribbon.is-open .ribbon__tab, .ribbon__link:hover .ribbon__tab {
    position: static; width: auto; flex: 1; opacity: 1;
    writing-mode: horizontal-tb;
    font: 900 13px/1 var(--display); letter-spacing: 0.045em;
    padding: 8px 5px 12px;
    /* A notched end, so three of them read as ribbons and not as tabs. */
    clip-path: polygon(0 0, 100% 0, 100% 68%, 50% 100%, 0 68%);
  }
  .ribbon__tab::after { inset: 5px 6px 11px; border-radius: 4px; }
}

/* ---------- Placeholder / photo frames ---------- */

.frame {
  position: relative;
  border: 2px solid var(--ink);
  background: var(--white);
  overflow: hidden;
  border-radius: 7px 4px 8px 5px;
}
.frame__media {
  position: relative;
  display: grid; place-items: center;
  aspect-ratio: var(--ratio, 3 / 4);
  background-color: var(--tint);
}
.frame__media img { width: 100%; height: 100%; object-fit: cover; }
.frame__note {
  margin: 0; padding: 10px 12px;
  border-top: var(--rule);
  font: 400 11px var(--mono);
}
.frame__tag {
  position: absolute; top: 8px; left: 8px;
  padding: 4px 8px; background: var(--yellow); color: var(--ink);
  border: 1.5px solid var(--ink); border-radius: 5px 3px 5px 2px;
  font: 700 9px var(--mono); letter-spacing: 0.08em;
  transform: rotate(-2deg); box-shadow: 2px 2px 0 rgba(27,24,21,.18);
}
.frame__tag--free { background: var(--blue); }

.ph-label {
  font: 400 10px/1.5 var(--mono);
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-45); text-align: center;
  background: rgba(255, 255, 255, 0.72); padding: 3px 6px;
}

.sw-hatch {
  background-color: var(--tint);
  background-image: repeating-linear-gradient(135deg, rgba(27,24,21,.07) 0 7px, transparent 7px 14px);
}
.sw-dots {
  background-color: #fde9df;
  background-image: radial-gradient(circle, rgba(147,78,89,.45) 0 2.5px, transparent 3px);
  background-size: 18px 18px;
  background-position: 2px 3px;
}
.sw-stripes {
  background-color: #eaf2ff;
  background-image: repeating-linear-gradient(-36deg, rgba(111,145,192,.34) 0 5px, transparent 5px 15px);
}
.sw-confetti {
  background-color: #eef6e9;
  background-image:
    radial-gradient(ellipse at 20% 28%, rgba(231,160,162,.58) 0 3px, transparent 3.5px),
    radial-gradient(ellipse at 72% 68%, rgba(111,145,192,.48) 0 3px, transparent 3.5px),
    radial-gradient(ellipse at 52% 18%, rgba(203,185,223,.6) 0 2.5px, transparent 3px);
  background-size: 34px 38px, 39px 35px, 31px 41px;
}
.sw-gingham-red {
  background-color: #fff;
  background-image:
    repeating-linear-gradient(0deg, rgba(195,58,52,.4) 0 10px, transparent 10px 20px),
    repeating-linear-gradient(90deg, rgba(195,58,52,.4) 0 10px, transparent 10px 20px);
}
.sw-gingham-blue {
  background-color: #fff;
  background-image:
    repeating-linear-gradient(0deg, rgba(46,75,154,.32) 0 10px, transparent 10px 20px),
    repeating-linear-gradient(90deg, rgba(46,75,154,.32) 0 10px, transparent 10px 20px);
}
.sw-plain { background-color: var(--white); }

/* ---------- Home: the whole page on one screen ----------
   The landing page is a title card now. The ribbons are the way into the
   shop, so there is no catalogue on it to scroll past — brand, headline,
   the free-pattern list, and her walking along the bottom.

   It is built to *fit* one screen rather than to *be* one screen. Nothing
   here has a fixed height, the body's min-height is a minimum, and the
   centring is done with auto margins rather than justify-content: when
   the card is taller than the room it has, auto margins collapse to zero
   and it overflows downwards where you can still scroll to it. Centring
   would have pushed the top of it off the screen for good, and an
   unreachable signup form is worse than a scrollbar.
   ---------------------------------------------------------------- */

.home { display: flex; flex-direction: column; }

.home__card {
  margin-block: auto;                    /* see above — not justify-content */
  /* .shell centres itself with margin-inline:auto, and an auto cross-axis
     margin turns off a flex item's stretch — without this the card sizes
     to the signup's own width and the headline stops lining up with the
     logo above it. */
  width: 100%;
  display: flex; flex-direction: column;
  gap: clamp(12px, 2dvh, 24px);
  padding-block: clamp(22px, 4dvh, 58px);
  position: relative;
}
.home__card .eyebrow { margin: 0; }
/* Capped by the height as well as the width, so a wide-but-short window
   doesn't spend its whole screen on one line of display type. */
.home__card h1 { font-size: clamp(42px, min(7.4vw, 9.2dvh), 76px); line-height: 0.9; max-width: 13ch; position: relative; z-index: 1; }
.home__card .lede { max-width: 50ch; }
.home__card .signup { margin-top: clamp(2px, 1.2dvh, 10px); }

/* Says which way the ribbons are, because a rolled ribbon down the side
   is a small thing to notice on a page this quiet. It only earns its
   line at the shell width and up: below that the ribbons are already a
   row of named tabs across the bottom of the screen, in plain sight and
   needing no arrow drawn to them. */
.home__hint {
  display: flex; align-items: center; gap: 9px;
  font: 700 11px var(--mono); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-60);
}
.home__hint::before { content: "\2190"; font-size: 15px; letter-spacing: 0; color: var(--red); }

/* The waiting-list page's closing line. It sits where .home__hint sits on the
   homepage - same quiet mono voice - but it is a sentence rather than a
   pointer at the ribbons, so it keeps its arrow off and stays on at every
   width. The page is the only one being served while the gate is on, so this
   line is the only thing telling a visitor the shop is bigger than one deck. */
.waitlist__foot {
  font: 400 13px/1.5 var(--mono);
  color: var(--ink-60);
  max-width: 46ch;
}

/* Nearly everyone reaching this page came from a TikTok video, so following
   her is the obvious second action after joining the list. Buttons rather than
   footer text, because on a page with one form the only competing thing is
   worth making tappable. */
.waitlist__follow { display: flex; flex-direction: column; gap: 10px; }
.waitlist__follow-label {
  font: 700 11px var(--mono); letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-60);
}
.waitlist__follow-links { display: flex; flex-wrap: wrap; gap: 10px; }
/* btn--sm is 37px tall, which is fine to click and too small to tap. Nearly
   all of this page's traffic is phones coming from a video, so on a touch
   pointer these go back up to a proper target. */
@media (pointer: coarse) {
  .waitlist__follow-links .btn { min-height: 46px; padding-inline: 22px; font-size: 14px; }
}

/* The card is a two-column grid at this width, everything but the signup in
   column 1. The follow row takes a row of its own, so the signup has to span
   one further to stay the full height of the card beside it. */
@media (min-width: 1180px) {
  .home--waitlist .home__card > .waitlist__follow { grid-column: 1; grid-row: 4; align-self: start; }
  .home--waitlist .home__card > .waitlist__foot { grid-column: 1; grid-row: 5; align-self: start; }
  .home--waitlist .home__card > .signup { grid-row: 1 / 6; }
}

@media (min-width: 1180px) {
  .home__card {
    display: grid;
    grid-template-columns: minmax(0, 1.08fr) minmax(380px, .92fr);
    grid-template-rows: auto auto auto auto;
    column-gap: clamp(34px, 5vw, 72px);
    row-gap: clamp(12px, 2dvh, 22px);
    align-items: center;
  }
  .home__card > .eyebrow,
  .home__card > h1,
  .home__card > .lede,
  .home__card > .home__hint { grid-column: 1; }
  .home__card > .eyebrow { grid-row: 1; align-self: end; }
  .home__card > h1 { grid-row: 2; }
  .home__card > .lede { grid-row: 3; }
  .home__card > .home__hint { grid-row: 4; align-self: start; }
  .home__card > .signup {
    grid-column: 2; grid-row: 1 / 5;
    grid-template-columns: 1fr;
    gap: 20px;
    transform: rotate(1deg);
  }
  .home__card > .signup form { flex-direction: column; min-width: 0; }
}

/* Full width of the content column rather than inside the shell: as the
   last thing above the footer it reads as the floor of the page.

   Its height is what is left of the screen once the header, the footer
   and the card have had theirs, so the strip is the thing that gives as
   the window shortens. CSS can't be asked for "the leftover" here — the
   card's height moves with how its own text wraps, and a flex item won't
   shrink against a <main> that simply grows instead — so this is that
   leftover measured across the range and written down. Floored at the
   height below which she reads as squashed rather than walking, capped
   so the strip never becomes a field. Being wrong by a little at some
   window size costs a short scroll, never a clipped signup. */
.home__walk {
  flex: none;
  height: clamp(96px, calc(80dvh - 520px), 190px);
  /* A flex column so the strip can be told to fill it. */
  display: flex; flex-direction: column;
}
.home__walk .walk { flex: 1 1 auto; min-height: 0; margin-top: 0; border-inline: 0; }
/* She is measured off the strip she is walking in rather than off the
   window, so a short strip gets a smaller figure instead of one whose
   head is cut off by the top edge. Pinning the actor top *and* bottom is
   what gives her a height to be a percentage of; 26px is the clearance
   she already had at the floor, repeated overhead. */
.home__walk .walk__actor { top: 26px; }
.home__walk .walk__inner { height: 100%; }
.home__walk .walk__figure { height: 100%; width: auto; aspect-ratio: 0.66; }

/* Two things give way as the screen runs out, in this order: the words
   inside her, then the strip itself. The headline and the signup are the
   page and they keep their screen at every size. */
@media (max-height: 780px) { .home__walk .walk__figure span { display: none; } }
@media (max-height: 749px) { .home__walk { display: none; } }
/* Below the shell width the ribbons themselves run along the bottom of
   the screen. A second band stacked on top of them is noise rather than
   signature, and the narrower column has made the card taller anyway, so
   the strip is where that height comes back from. */
@media (max-width: 1179px) { .home__walk, .home__hint { display: none; } }

/* ---------- The walk-cycle strip ---------- */

.walk {
  position: relative; height: clamp(150px, 22vw, 196px);
  margin-top: 36px;
  border: 2px solid var(--ink);
  border-radius: 8px 5px 0 0;
  background-color: var(--white);
  background-image:
    repeating-linear-gradient(0deg, rgba(231,160,162,.36) 0 13px, transparent 13px 26px),
    repeating-linear-gradient(90deg, rgba(231,160,162,.36) 0 13px, transparent 13px 26px);
  overflow: hidden;
}
.walk__floor {
  position: absolute; left: 0; right: 0; bottom: 0; height: 34px;
  background: var(--paper); border-top: var(--rule);
}
.walk__actor { position: absolute; bottom: 26px; left: 0; animation: pp-walk 11s linear infinite; }
.walk__inner { position: relative; }
.walk__figure {
  width: 96px; height: clamp(112px, 16vw, 146px);
  border: 2px solid var(--ink);
  background: rgba(247, 243, 234, 0.9);
  display: grid; place-items: center;
  transform-origin: 50% 100%;
  animation: pp-bob 0.62s ease-in-out infinite;
  border-radius: 47% 53% 45% 55% / 42% 44% 56% 58%;
  box-shadow: inset 0 0 0 5px rgba(251,246,236,.9), inset 0 0 0 6.5px rgba(27,24,21,.48), 4px 4px 0 rgba(27,24,21,.15);
}
.walk__figure span {
  font: 400 9px/1.6 var(--mono);
  letter-spacing: 0.06em; text-transform: uppercase; text-align: center;
}
.walk__figure img { width: 100%; height: 100%; object-fit: contain; }
.walk__dust {
  position: absolute; border-radius: 50%;
  background: rgba(27, 24, 21, 0.28);
  animation: pp-dust 1.5s ease-out infinite;
}
.walk__dust:nth-child(1) { bottom: 2px; left: -6px; width: 9px; height: 9px; }
.walk__dust:nth-child(2) { bottom: 8px; left: -16px; width: 13px; height: 13px; animation-delay: 0.5s; }
.walk__dust:nth-child(3) { bottom: 1px; left: -28px; width: 7px; height: 7px; animation-delay: 1s; }

@keyframes pp-walk { from { transform: translateX(-120px); } to { transform: translateX(100vw); } }
@keyframes pp-bob {
  0%, 100% { transform: translateY(0) rotate(-2.5deg); }
  50% { transform: translateY(-9px) rotate(2.5deg); }
}
@keyframes pp-dust {
  from { opacity: 0.65; transform: translate(0, 0) scale(0.5); }
  to { opacity: 0; transform: translate(-52px, -18px) scale(1.6); }
}

@media (prefers-reduced-motion: reduce) {
  .walk__actor { animation: none; left: 50%; transform: translateX(-50%); }
  .walk__figure, .walk__dust { animation: none; }
  .walk__dust { opacity: 0.3; }
  .btn:hover { transform: none; }
  .nav__bag[data-bump="true"] { animation: none; }
  * { scroll-behavior: auto !important; }
}

/* ---------- Sections ---------- */

.section { padding-block: clamp(38px, 6vw, 56px); }
.section--tight { padding-block: clamp(26px, 4vw, 38px); }
.section__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 20px;
}
.section__head h2 { font-size: clamp(26px, 4vw, 34px); }

.page-head { padding-top: clamp(28px, 5vw, 40px); }
.page-head h1 { font-size: clamp(34px, 5.6vw, 52px); }
.page-head h1::after,
.about-grid h1::after {
  content: ""; display: block; width: clamp(72px, 12vw, 132px); height: 9px;
  margin-top: 10px; border-top: 3px dashed var(--red-dark); border-radius: 50%;
  transform: rotate(-2deg);
}
.breadcrumb { padding-block: 14px; font: 400 12px var(--mono); color: var(--ink-60); }
.breadcrumb a { color: inherit; }

/* ---------- Product grid ---------- */

.grid { display: grid; gap: clamp(18px, 2.2vw, 26px); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid--4[data-count="1"] { grid-template-columns: minmax(260px, 360px); }
.grid--4[data-count="2"] { grid-template-columns: repeat(2, minmax(260px, 360px)); }
@media (max-width: 900px) { .grid--3, .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) {
  .grid--3 { grid-template-columns: 1fr; }
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .grid--4 .card__body { padding: 10px; }
  .grid--4 .card__title { font-size: 14px; line-height: 1.05; }
  .grid--4 .card__meta { font-size: 10px; line-height: 1.45; }
}

.card {
  --card-rotate: 0deg;
  position: relative;
  display: flex; flex-direction: column;
  border: 2px solid var(--ink); background: var(--white);
  color: var(--ink); text-decoration: none;
  border-radius: 7px 4px 8px 5px;
  overflow: hidden;
  box-shadow: 2px 3px 0 rgba(27,24,21,.12);
  transform: rotate(var(--card-rotate));
  transform-style: preserve-3d;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.card:nth-child(odd) { --card-rotate: -0.35deg; }
.card:nth-child(even) { --card-rotate: 0.35deg; }
.card:hover {
  transform: perspective(800px) translateY(-5px)
    rotateX(var(--tilt-y, 0deg)) rotateY(var(--tilt-x, 0deg)) rotate(var(--card-rotate));
  box-shadow: 6px 7px 0 var(--ink); color: var(--ink);
}
.card--tactile::before {
  content: ""; position: absolute; z-index: 3; inset: 0; pointer-events: none;
  background: radial-gradient(circle at var(--glint-x, 50%) var(--glint-y, 50%),
    rgba(255,255,255,.72), rgba(255,255,255,.2) 19%, transparent 42%);
  opacity: 0; transition: opacity .18s ease;
}
.card--tactile:hover::before { opacity: .48; }
.card__body { padding: 12px; border-top: var(--rule); display: flex; flex-direction: column; gap: 5px; flex: 1; }
.card__body { background: linear-gradient(145deg, rgba(255,255,255,.92), rgba(247,243,234,.72)); }
.card__title {
  font-family: var(--display); font-weight: 600; font-size: 16px; letter-spacing: -0.02em;
}
.card__meta { font: 400 12px var(--mono); color: var(--ink-60); }

[data-shop-hub] .card:nth-child(1) .card__body { background: #fde8df; }
[data-shop-hub] .card:nth-child(2) .card__body { background: #e9f2ff; }
[data-shop-hub] .card:nth-child(3) .card__body { background: #eef6e9; }
[data-shop-hub] .card:nth-child(4) .card__body { background: #fae8f1; }

.card--promo {
  background: var(--blue); color: var(--ink);
  justify-content: space-between; border-color: var(--ink);
}
.card--promo:hover { color: var(--ink); }
.card--promo__top { padding: 16px; }
.card--promo h3 { font-size: 22px; line-height: 1; letter-spacing: -0.03em; }
.card--promo__foot {
  margin: 0; padding: 11px; border-top: var(--rule);
  background: var(--paper); color: var(--ink); font: 400 11px var(--mono);
}

/* ---------- Filters ---------- */

.filters { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 22px 0 24px; }
.chip {
  min-height: 38px; padding: 7px 15px; border: 1.5px solid var(--ink-25); border-radius: 999px;
  background: none; font: 500 12px var(--body); color: var(--ink); cursor: pointer;
}
.chip:hover { border-color: var(--ink); }
.chip[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); font-weight: 700; }
.filters__note { margin-left: auto; font: 400 12px var(--mono); }
@media (max-width: 700px) { .filters__note { margin-left: 0; width: 100%; } }

.sort { display: flex; align-items: center; gap: 8px; font: 400 12px var(--mono); }
.sort select {
  font: 400 12px var(--mono); color: var(--ink);
  padding: 6px 8px; border: 1.5px solid var(--ink-25); background: var(--white); border-radius: 0;
}
.surprise {
  min-height: 34px; padding: 6px 12px;
  border: 1.5px dashed var(--red-dark); background: transparent; color: var(--red-dark);
  font: 700 11px var(--mono); cursor: pointer;
}
.surprise:hover { background: rgba(195, 58, 52, 0.08); }

/* ---------- Product detail ---------- */

.product { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 30px; padding-bottom: 44px; }
@media (max-width: 900px) { .product { grid-template-columns: 1fr; } }
@media (max-width: 700px) {
  .product--waitlist > :last-child { order: -1; }
  .product--waitlist .gallery { margin-top: 8px; }
}

.gallery { display: flex; flex-direction: column; gap: 10px; }
.gallery__thumbs { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.gallery__thumb {
  padding: 0; border: 1.5px solid var(--ink-25); background: none; cursor: pointer;
  aspect-ratio: 1 / 1; overflow: hidden;
}
.gallery__thumb[aria-pressed="true"] { border: var(--rule); box-shadow: inset 0 0 0 2px var(--white); }
.gallery__thumb > span { display: block; width: 100%; height: 100%; }

.product h1 { font-size: clamp(30px, 4.6vw, 44px); }
.product__price { font-family: var(--display); font-weight: 600; font-size: 22px; margin-top: 8px; }
.product__group { margin-top: 22px; }
.product__group > h2 { font: 700 12px var(--body); letter-spacing: 0.02em; margin-bottom: 8px; font-family: var(--body); }

.swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.swatch-btn {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 14px; border: 1.5px solid var(--ink-25); background: var(--white);
  font: 500 12px var(--body); color: var(--ink); cursor: pointer;
}
.swatch-btn[aria-pressed="true"] { border: var(--rule); }
.swatch-btn i { width: 16px; height: 16px; border: 1px solid var(--ink-25); display: block; }

.sizes { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.size-btn {
  width: 44px; height: 38px; display: grid; place-items: center;
  border: 1.5px solid var(--ink-25); background: var(--white);
  font: 500 13px var(--body); color: var(--ink); cursor: pointer;
}
.size-btn[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: var(--paper); }

.spec { display: grid; gap: 7px; margin-top: 20px; padding: 0; list-style: none; font: 400 12px/1.5 var(--mono); color: var(--ink-60); }
.spec li { padding-left: 14px; position: relative; }
.spec li::before { content: "·"; position: absolute; left: 3px; }

.panel {
  position: relative; border: 2px solid var(--ink); background: var(--white);
  border-radius: 8px 4px 9px 5px; box-shadow: 4px 4px 0 rgba(27,24,21,.11);
}
.panel::after {
  content: ""; position: absolute; inset: 6px; pointer-events: none;
  border: 1.5px dashed rgba(147,78,89,.35); border-radius: 5px 2px 6px 3px;
}
.product--waitlist .panel {
  box-shadow: 5px 5px 0 rgba(195, 58, 52, 0.16);
}
.panel__body { padding: 16px; }
.panel__foot {
  margin: 0; padding: 10px 16px; border-top: 1.5px solid var(--ink-12);
  font: 400 11px var(--mono); color: var(--ink-60);
}
.panel h2, .panel h3 { font-family: var(--display); font-weight: 600; font-size: 17px; letter-spacing: -0.02em; }

/* ---------- Forms ---------- */

.field { display: flex; flex-direction: column; gap: 6px; }
.field > label { font: 700 12px var(--body); }
.input, .textarea, select.input {
  width: 100%; padding: 11px 12px;
  border: 1.5px solid var(--ink-45); border-radius: 6px 3px 7px 4px;
  background: var(--white); color: var(--ink);
  font: 400 14px var(--body);
}
.input:focus, .textarea:focus { border-color: var(--ink); }
.textarea { min-height: 110px; resize: vertical; }
.form-row { display: flex; gap: 8px; }
.form-row .input { flex: 1; }
.form-grid { display: grid; gap: 14px; }
.form-grid--2 { grid-template-columns: 1fr 1fr; }
@media (max-width: 620px) { .form-grid--2 { grid-template-columns: 1fr; } .form-row { flex-direction: column; } }

.form-note { font: 400 13px/1.5 var(--body); color: var(--ink-60); }
.form-error { font: 500 12px var(--body); color: var(--red-dark); }
.form-status {
  margin-top: 12px; padding: 11px 14px;
  border: 1.5px solid var(--ink); background: var(--white);
  font: 500 13px var(--body);
}
.form-status[data-tone="ok"] { border-color: #416991; color: #31567d; }
.form-status[data-tone="bad"] { border-color: var(--red-dark); color: var(--red-dark); }
.form-status:empty { display: none; }
.hp-field {
  position: absolute !important; width: 1px !important; height: 1px !important;
  overflow: hidden !important; clip: rect(0 0 0 0) !important;
  white-space: nowrap !important;
}

/* ---------- Made-to-order band ---------- */

.band { display: grid; grid-template-columns: 1fr 1fr; background: var(--ink); color: var(--paper); }
.band { border-block: 2px solid var(--ink); }
.band__copy { padding: clamp(28px, 4vw, 38px) var(--pad); }
.band__copy h2 { font-size: clamp(24px, 3.6vw, 32px); line-height: 1.02; }
.band__copy p { color: rgba(247, 243, 234, 0.75); max-width: 38ch; margin: 14px 0 22px; }
.band__media { aspect-ratio: 16 / 10; display: grid; place-items: center;
  background-color: var(--lilac);
  background-image:
    radial-gradient(circle, rgba(27,24,21,.17) 0 2px, transparent 2.5px),
    repeating-linear-gradient(135deg, rgba(255,255,255,.2) 0 7px, transparent 7px 14px);
  background-size: 20px 20px, auto;
}
.band__media span { padding: 8px 11px; border: 1.5px dashed var(--ink); background: var(--paper); font: 700 10px var(--mono); text-transform: uppercase; color: var(--ink); transform: rotate(-2deg); }
@media (max-width: 820px) { .band { grid-template-columns: 1fr; } }

/* ---------- Numbered blocks (about) ---------- */

.about-grid {
  padding-top: clamp(32px, 5vw, 48px);
  display: grid; grid-template-columns: 1fr 1fr; gap: 36px; align-items: start;
}
.about-grid h1 { font-size: clamp(36px, 6vw, 56px); line-height: 0.95; }
.about-grid__story > p { margin-top: 16px; font: 400 16px/1.6 var(--body); color: var(--ink-72); }
.about-grid__story > p:first-of-type { margin-top: 20px; font-size: clamp(16px, 2vw, 17px); color: rgba(27,24,21,.8); }
.about-quote {
  margin-top: 26px; padding: 18px; border: var(--rule); background-color: var(--white);
  background-image:
    repeating-linear-gradient(0deg, rgba(46,75,154,.14) 0 12px, transparent 12px 24px),
    repeating-linear-gradient(90deg, rgba(46,75,154,.14) 0 12px, transparent 12px 24px);
}
.about-quote { border-radius: 7px 3px 8px 4px; box-shadow: 4px 4px 0 var(--yellow); transform: rotate(-.5deg); }
.about-grid__art { display: flex; flex-direction: column; gap: 12px; }
.mess-maker {
  position: relative; width: 100%; aspect-ratio: 1 / 1; overflow: hidden;
  border: 1.5px dashed var(--red-dark); background: var(--white); color: var(--red-dark); cursor: pointer;
}
.mess-maker__words {
  position: absolute; z-index: 2; inset: 50% auto auto 50%; transform: translate(-50%, -50%) rotate(-2deg);
  padding: 12px 16px; background: rgba(247,243,234,.9); border: 1px solid var(--red);
  font: 700 11px/1.7 var(--mono); letter-spacing: .04em; text-transform: uppercase; text-align: center;
  box-shadow: 4px 4px 0 rgba(195,58,52,.15); white-space: nowrap;
}
.mess-maker__hint {
  position: absolute; z-index: 3; right: 12px; bottom: 10px;
  font: 400 10px var(--mono); color: var(--ink-60);
}
.mess-maker__scraps i {
  position: absolute; left: var(--x); top: var(--y); width: var(--w); aspect-ratio: var(--ratio, 1.3);
  border: 1px solid var(--ink); transform: rotate(var(--r));
  transition: left .42s cubic-bezier(.2,.8,.2,1), top .42s cubic-bezier(.2,.8,.2,1), transform .42s ease;
}
.mess-maker__scraps i:nth-child(1) { --x:8%; --y:12%; --w:28%; --r:-12deg; background:var(--pink); }
.mess-maker__scraps i:nth-child(2) { --x:61%; --y:9%; --w:24%; --r:9deg; background:var(--blue); }
.mess-maker__scraps i:nth-child(3) { --x:12%; --y:64%; --w:31%; --r:7deg; background:var(--paper); background-image:repeating-linear-gradient(135deg,rgba(27,24,21,.12) 0 6px,transparent 6px 12px); }
.mess-maker__scraps i:nth-child(4) { --x:63%; --y:66%; --w:27%; --r:-8deg; background:var(--white); background-image:repeating-linear-gradient(0deg,rgba(195,58,52,.38) 0 8px,transparent 8px 16px),repeating-linear-gradient(90deg,rgba(195,58,52,.38) 0 8px,transparent 8px 16px); }
.mess-maker__scraps i:nth-child(5) { --x:39%; --y:27%; --w:19%; --r:18deg; background:#e8d7a8; }
.mess-maker:hover .mess-maker__words { box-shadow: 6px 6px 0 rgba(195,58,52,.22); }
@media (max-width: 820px) { .about-grid { grid-template-columns: 1fr; } }

.pillars {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-top: 2px solid var(--ink); border-bottom: 2px solid var(--ink);
  margin-top: 44px;
}
.pillars > div { padding: 26px var(--pad); border-right: 1.5px solid rgba(27,24,21,.2); }
.pillars > div:nth-child(1) { background: #fde8df; }
.pillars > div:nth-child(2) { background: #eaf2ff; }
.pillars > div:nth-child(3) { background: #eef6e9; }
.pillars > div:last-child { border-right: 0; }
.pillars h3 { font-weight: 600; font-size: 19px; letter-spacing: -0.02em; }
.pillars p { margin-top: 7px; font-size: 13px; line-height: 1.5; color: rgba(27,24,21,.65); }
@media (max-width: 820px) {
  .pillars { grid-template-columns: 1fr; }
  .pillars > div { border-right: 0; border-bottom: 1.5px solid rgba(27,24,21,.2); }
  .pillars > div:last-child { border-bottom: 0; }
}

/* ---------- Cart ---------- */

.cart-layout { display: grid; grid-template-columns: 1.6fr 1fr; gap: 30px; align-items: start; padding-bottom: 48px; }
@media (max-width: 900px) { .cart-layout { grid-template-columns: 1fr; } }

.line {
  display: grid; grid-template-columns: 84px 1fr auto; gap: 16px;
  padding: 16px 0; border-bottom: 1.5px solid var(--ink-12); align-items: start;
}
.line:first-child { border-top: 1.5px solid var(--ink-12); }
.line__thumb { border: 1.5px solid var(--ink-25); aspect-ratio: 3 / 4; overflow: hidden; }
.line__thumb > span, .line__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; }
.line__title { font-family: var(--display); font-weight: 600; font-size: 17px; letter-spacing: -0.02em; }
.line__opts { font: 400 12px var(--mono); color: var(--ink-60); margin-top: 4px; }
.line__price { font-family: var(--display); font-weight: 600; font-size: 16px; text-align: right; white-space: nowrap; }
.line__tools { display: flex; align-items: center; gap: 10px; margin-top: 10px; }

.qty { display: inline-flex; align-items: center; border: 1.5px solid var(--ink-25); }
.qty button {
  width: 30px; height: 30px; border: 0; background: none; cursor: pointer;
  font: 700 15px var(--body); color: var(--ink); line-height: 1;
}
.qty button:hover { background: var(--tint); }
.qty span { min-width: 28px; text-align: center; font: 500 13px var(--body); }

.link-quiet {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: 400 12px var(--mono); color: var(--ink-60);
  text-decoration: underline; text-underline-offset: 3px;
}
.link-quiet:hover { color: var(--red-dark); }

.totals { display: grid; gap: 9px; font: 400 14px var(--body); }
.totals__row { display: flex; justify-content: space-between; gap: 12px; }
.totals__row--save { color: var(--red-dark); font-weight: 700; }
.totals__row--grand {
  padding-top: 11px; margin-top: 3px; border-top: var(--rule);
  font-family: var(--display); font-weight: 800; font-size: 21px; letter-spacing: -0.02em;
}

.nudge {
  padding: 11px 14px; border: 1.5px dashed var(--red-dark);
  font: 400 12px/1.5 var(--mono); color: var(--red-dark); margin-bottom: 16px;
}

.empty { padding: 48px 0 60px; text-align: center; }
.empty h1 { font-size: clamp(28px, 4.4vw, 40px); margin-bottom: 12px; }
.empty > .eyebrow {
  display: inline-block; padding: 6px 10px; background: var(--yellow); color: var(--ink);
  border: 1.5px solid var(--ink); border-radius: 5px 2px 6px 3px;
  box-shadow: 2px 2px 0 var(--ink); transform: rotate(-1deg);
}

/* ---------- Craft motion and worktable play ----------
   These are atmospheric layers, not another interface. The entrance motion
   makes sections feel like paper being placed down; the notions only occupy
   real outer margins; and empty pages get one optional loose-thread toy. */

.craft-motion .craft-reveal:not(.is-in) { opacity: 0; translate: 0 18px; }
.craft-motion .craft-reveal.is-in {
  animation: craft-piece-in .58s cubic-bezier(.2,.78,.2,1) var(--reveal-delay, 0ms) both;
}
@keyframes craft-piece-in {
  from { opacity: 0; translate: 0 18px; }
  68% { opacity: 1; translate: 0 -2px; }
  to { opacity: 1; translate: 0 0; }
}

.studio-notions { display: none; }
@media (min-width: 1560px) {
  .studio-notions {
    display: block;
    --notion-edge: max(24px, calc((100vw - var(--shell)) / 2 - 110px));
    --notion-x: 0px; --notion-y: 0px;
  }
  .notion {
    position: fixed; z-index: 2; pointer-events: none;
    opacity: .72;
    transition: transform .42s cubic-bezier(.2,.7,.2,1);
  }
  .notion--thread {
    right: calc(var(--notion-edge) - 2px); top: 16%; width: 118px; height: 300px;
    transform: translate(calc(var(--notion-x) * -.45), calc(var(--notion-y) * -.45)) rotate(2deg);
  }
  .notion--thread svg { width: 100%; height: 100%; overflow: visible; }
  .notion--thread path {
    fill: none; stroke: rgba(147,78,89,.5); stroke-width: 2.2;
    stroke-linecap: round; stroke-dasharray: .018 .025;
  }
  .notion--button {
    right: calc(var(--notion-edge) + 35px); top: 38%; width: 43px; aspect-ratio: 1;
    border: 2px solid rgba(27,24,21,.7); border-radius: 49% 52% 47% 53%;
    background-color: var(--yellow);
    background-image:
      radial-gradient(circle at 39% 39%, var(--paper) 0 2.5px, var(--ink) 2.8px 4px, transparent 4.2px),
      radial-gradient(circle at 61% 39%, var(--paper) 0 2.5px, var(--ink) 2.8px 4px, transparent 4.2px),
      radial-gradient(circle at 39% 61%, var(--paper) 0 2.5px, var(--ink) 2.8px 4px, transparent 4.2px),
      radial-gradient(circle at 61% 61%, var(--paper) 0 2.5px, var(--ink) 2.8px 4px, transparent 4.2px);
    box-shadow: 3px 4px 0 rgba(27,24,21,.13), inset 0 0 0 5px rgba(255,255,255,.25);
    transform: translate(var(--notion-x), var(--notion-y)) rotate(-11deg);
  }
  .notion--spool {
    right: calc(var(--notion-edge) + 22px); top: 61%; width: 52px; height: 70px;
    border-inline: 8px solid #c99b6d;
    background: repeating-linear-gradient(0deg, var(--blue) 0 4px, #799bc9 4px 6px);
    filter: drop-shadow(3px 4px 0 rgba(27,24,21,.13));
    transform: translate(calc(var(--notion-x) * -.7), calc(var(--notion-y) * -.7)) rotate(8deg);
  }
  .notion--spool::before, .notion--spool::after {
    content: ""; position: absolute; left: -13px; width: 62px; height: 10px;
    border: 2px solid rgba(27,24,21,.65); border-radius: 50%; background: #e1bd8d;
  }
  .notion--spool::before { top: -4px; }
  .notion--spool::after { bottom: -4px; }
  .notion--scrap {
    right: var(--notion-edge); top: 81%; width: 82px; height: 58px;
    border: 1.5px solid rgba(27,24,21,.65); background-color: #fde7df;
    background-image: radial-gradient(rgba(147,78,89,.34) 1.5px, transparent 1.8px);
    background-size: 10px 10px;
    clip-path: polygon(4% 3%, 98% 0, 93% 94%, 2% 100%);
    transform: translate(calc(var(--notion-x) * .6), calc(var(--notion-y) * .6)) rotate(-8deg);
  }
  .notion--scrap::after {
    content: ""; position: absolute; inset: 6px; border: 1.5px dashed rgba(27,24,21,.5);
  }
  .notion--scrap i {
    position: absolute; z-index: 1; inset: 0; display: grid; place-items: center;
    font: normal 700 8px var(--mono); letter-spacing: .14em; text-transform: uppercase;
  }
  .studio-notions--1 .notion--button { background-color: var(--mint); transform: translate(var(--notion-x), var(--notion-y)) rotate(13deg); }
  .studio-notions--1 .notion--scrap { background-color: #e9f2ff; transform: translate(calc(var(--notion-x) * .6), calc(var(--notion-y) * .6)) rotate(7deg); }
  .studio-notions--2 .notion--button { background-color: var(--lilac); }
  .studio-notions--2 .notion--spool { background: repeating-linear-gradient(0deg, var(--red) 0 4px, #c67982 4px 6px); transform: translate(calc(var(--notion-x) * -.7), calc(var(--notion-y) * -.7)) rotate(-8deg); }
}

.thread-pull {
  position: relative; display: block; width: min(540px, 100%); height: 112px;
  margin: 38px auto 0; padding: 0; border: 0; background: transparent;
  color: var(--ink); cursor: pointer;
}
.thread-pull__spool {
  position: absolute; z-index: 2; left: 4px; top: 27px; width: 46px; height: 56px;
  border-inline: 7px solid #c99b6d;
  background: repeating-linear-gradient(0deg, var(--red) 0 4px, #c67982 4px 6px);
  filter: drop-shadow(3px 4px 0 rgba(27,24,21,.15));
  transition: transform .9s cubic-bezier(.2,.75,.2,1);
}
.thread-pull__spool::before, .thread-pull__spool::after {
  content: ""; position: absolute; left: -11px; width: 54px; height: 9px;
  border: 1.5px solid var(--ink); border-radius: 50%; background: #e1bd8d;
}
.thread-pull__spool::before { top: -3px; }
.thread-pull__spool::after { bottom: -3px; }
.thread-pull__trail { position: absolute; z-index: 0; inset: 10px 0 0 22px; width: calc(100% - 22px); height: 86px; overflow: visible; }
.thread-pull__trail path {
  fill: none; stroke: var(--red-dark); stroke-width: 3; stroke-linecap: round;
  stroke-dasharray: 1; stroke-dashoffset: .68;
  transition: stroke-dashoffset 1.05s cubic-bezier(.2,.72,.2,1);
}
.thread-pull__label {
  position: absolute; z-index: 3; right: 8%; top: 43px;
  padding: 7px 10px 6px; border: 1.5px solid var(--ink); background: var(--yellow);
  box-shadow: 2px 2px 0 rgba(27,24,21,.16); transform: rotate(-2deg);
  font: 700 10px var(--mono); letter-spacing: .08em; text-transform: uppercase;
}
.thread-pull:hover .thread-pull__trail path { stroke-dashoffset: .58; }
.thread-pull[aria-pressed="true"] .thread-pull__trail path { stroke-dashoffset: 0; }
.thread-pull[aria-pressed="true"] .thread-pull__spool { transform: rotate(355deg); }
.thread-pull[aria-pressed="true"] .thread-pull__label { background: var(--mint); transform: rotate(2deg); }

@media (max-width: 520px) {
  .thread-pull { height: 96px; margin-top: 26px; }
  .thread-pull__label { right: 2%; top: 38px; font-size: 8px; }
  .thread-pull__spool { transform: scale(.88); transform-origin: left center; }
  .thread-pull[aria-pressed="true"] .thread-pull__spool { transform: scale(.88) rotate(355deg); }
}

@media (prefers-reduced-motion: reduce) {
  .craft-motion .craft-reveal:not(.is-in) { opacity: 1; translate: none; }
  .craft-motion .craft-reveal.is-in { animation: none; }
  .notion, .thread-pull__trail path, .thread-pull__spool { transition: none !important; }
  .card--tactile::before { display: none; }
  .ribbons { transition: none !important; }
}

/* ---------- FAQ ---------- */

.faq { border-top: 1.5px solid var(--ink-12); }
.faq details { border-bottom: 1.5px solid var(--ink-12); }
.faq summary {
  padding: 16px 0; cursor: pointer; list-style: none;
  font-family: var(--display); font-weight: 600; font-size: 17px; letter-spacing: -0.02em;
  display: flex; justify-content: space-between; gap: 16px; align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; font: 400 20px var(--mono); color: var(--red-dark); }
.faq details[open] summary::after { content: "–"; }
.faq details > p, .faq details > ul { padding: 0 0 16px; max-width: 68ch; color: var(--ink-72); font-size: 15px; }

/* ---------- Table ---------- */

.table-wrap { overflow-x: auto; border: var(--rule); background: var(--white); }
table.chart { border-collapse: collapse; width: 100%; min-width: 460px; font: 400 13px var(--body); }
table.chart th, table.chart td { padding: 10px 14px; text-align: left; border-bottom: 1px solid var(--ink-12); }
table.chart th { font: 700 11px var(--mono); letter-spacing: 0.1em; text-transform: uppercase; background: var(--tint); }
table.chart tr:last-child td { border-bottom: 0; }

/* ---------- Dialog ---------- */

dialog.modal {
  border: 2px solid var(--ink); background: var(--paper); color: var(--ink);
  padding: 0; max-width: 640px; width: calc(100% - 32px);
}
dialog.modal::backdrop { background: rgba(27, 24, 21, 0.55); }
.modal__head {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 16px 20px; border-bottom: var(--rule);
}
.modal__head h2 { font-size: 20px; }
.modal__body { padding: 20px; }

/* ---------- Newsletter ---------- */

.signup {
  display: grid; grid-template-columns: 1fr auto; gap: 24px; align-items: center;
  position: relative;
  padding: clamp(26px, 4vw, 38px); border: 2px solid var(--ink); background: var(--white);
  background-image:
    repeating-linear-gradient(0deg, rgba(46,75,154,.1) 0 12px, transparent 12px 24px),
    repeating-linear-gradient(90deg, rgba(46,75,154,.1) 0 12px, transparent 12px 24px);
}
.signup { border-radius: 12px 5px 13px 7px; box-shadow: 7px 7px 0 rgba(111,145,192,.2); }
.signup::after {
  content: ""; position: absolute; inset: 7px; pointer-events: none;
  border: 1.5px dashed rgba(27,24,21,.38); border-radius: 8px 3px 9px 4px;
}
.signup > * { position: relative; z-index: 1; }
.signup h2 { font-size: clamp(22px, 3.2vw, 28px); }
.signup form { display: flex; gap: 8px; min-width: min(360px, 100%); }
/* Stacked, the 24px gutter between the pitch and the form reads as a gap
   rather than as a column, and on the home page — which is trying to be
   one screen — it is the loosest thing on it. */
@media (max-width: 780px) {
  .signup { grid-template-columns: 1fr; gap: 16px; padding: 20px; }
  .signup form { flex-direction: column; }
}

/* ---------- Footer ---------- */

.site-footer {
  border-top: 2px solid var(--ink); margin-top: auto;
  background-color: #f5ede0;
  background-image: radial-gradient(rgba(27,24,21,.055) .6px, transparent .8px);
  background-size: 7px 7px;
}
.site-footer__inner {
  display: flex; flex-wrap: wrap; gap: 16px 32px; justify-content: space-between;
  padding-block: 22px; font: 400 12px var(--mono); color: var(--ink-60);
}
.site-footer a { color: var(--ink-60); text-decoration: none; }
.site-footer a:hover { color: var(--red-dark); }
.site-footer__links { display: flex; flex-wrap: wrap; gap: 18px; }

/* On a phone eight links wrap to four rows and the footer ends up taller
   than the headline above it. Tightening the rows costs nothing anywhere
   and gives the home page back most of a screenful. */
@media (max-width: 700px) {
  .site-footer__inner { padding-block: 16px; gap: 10px 22px; }
  .site-footer__links { gap: 10px 16px; }
}

/* dvh, not vh: on a phone the toolbars come and go, and a page built to
   fit one screen has to fit the screen that is actually there. The vh
   line stays underneath it for anything that has never heard of dvh. */
body { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; }
main { flex: 1; }

/* ---------- Toast ---------- */

.toast {
  /* Above the ribbons (35) and the header (40), and on a narrow screen
     sitting clear of the row of ribbon ends rather than on top of it. */
  position: fixed; right: 16px; bottom: calc(16px + var(--rail-bottom, 0px)); z-index: 60;
  max-width: 320px; padding: 13px 16px;
  border: 2px solid var(--ink); background: var(--ink); color: var(--paper);
  font: 500 13px var(--body);
  transform: translateY(12px); opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
  pointer-events: none;
}
.toast[data-show="true"] { opacity: 1; transform: translateY(0); }
