/* Human Crafted — shop styles.
   Buy block, "$" mark, cart drawer, cart / checkout / confirmation pages.

   Split out of main.css deliberately: this file is only linked (and only
   copied into the build) when `shop_enabled: true` in _config.yml. Leaving
   these rules in main.css would ship .buy-block/.cart-drawer selectors to
   every visitor while the shop is meant to be invisible.

   Uses the same design tokens as main.css — no new colors. */

/* --- Back link (shop pages only; elsewhere the breadcrumb wordmark does this) */
.back-link {
  display: inline-block;
  margin-bottom: 2rem;
  color: var(--muted-foreground);
  text-decoration: none;
  font-size: 0.875rem;
}

.back-link:hover {
  color: var(--foreground);
  text-decoration: underline;
  text-decoration-style: wavy;
}

/* --- Cart button in the nav ---------------------------------------------- */
.cart-link {
  position: relative;
  background: none;
  border: none;
  padding: 0.25rem;
  cursor: pointer;
  color: var(--foreground);
  display: inline-flex;
  align-items: center;
  transition: opacity 150ms ease, transform 150ms ease;
}

.cart-link:hover { transform: translateY(-1px); }

/* An empty cart is noise on a page that isn't the shop — hide it there. */
.cart-link.is-empty { display: none; }
body.shop-page .cart-link.is-empty { display: inline-flex; opacity: 0.55; }
body.shop-page .cart-link.is-empty:hover { opacity: 1; }

.cart-badge {
  position: absolute;
  top: -2px;
  right: -4px;
  min-width: 1.125rem;
  height: 1.125rem;
  padding: 0 0.25rem;
  border-radius: 999px;
  background: var(--accent);
  color: #2A2824;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1.125rem;
  text-align: center;
}

.cart-link.is-empty .cart-badge { display: none; }

/* --- Cart drawer ---------------------------------------------------------- */
.cart-drawer {
  position: fixed;
  inset: 0;
  /* Above the floating co/lab pill (z-index 1001 in main.css), which sits in
     the same corner as the drawer's checkout button. */
  z-index: 1100;
  visibility: hidden;
  pointer-events: none;
}

.cart-drawer.is-open { visibility: visible; pointer-events: auto; }

.cart-drawer-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  opacity: 0;
  transition: opacity 250ms ease;
}

.cart-drawer.is-open .cart-drawer-backdrop { opacity: 1; }

.cart-drawer-panel {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(24rem, 100%);
  background: var(--background);
  /* Borderless, lifted off the page by a soft shadow — same treatment as the
     quick-links panel. */
  box-shadow: -12px 0 40px rgba(0, 0, 0, 0.14);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 250ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.cart-drawer.is-open .cart-drawer-panel { transform: translateX(0); }

@media (prefers-reduced-motion: reduce) {
  .cart-drawer-panel,
  .cart-drawer-backdrop { transition: none; }
}

.cart-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.5rem 1.5rem 0.75rem;
}

.cart-drawer-head h2 { margin: 0; font-size: 1.125rem; }

.cart-drawer-close {
  background: none;
  border: none;
  color: var(--foreground);
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  padding: 0.25rem;
  transition: transform 150ms ease;
}

.cart-drawer-close:hover { transform: translateX(1px); }

.cart-drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 1rem 1.5rem;
}

.cart-drawer-foot {
  padding: 0.75rem 1.5rem 1.5rem;
}

/* On phones the floating co/lab pill lands on top of Add to cart and Check
   out. Shop pages (a product for sale, the cart, the thanks page — see the
   body class in default.html) go without it there; co/lab stays a nav item
   on wider screens and reachable from every other page. */
@media (max-width: 768px) {
  body.shop-page .colab-fab { display: none; }
}

/* --- Cart lines (shared by drawer and cart page) -------------------------- */
.cart-line {
  display: flex;
  gap: 0.875rem;
  padding: 0.75rem 0;
  align-items: flex-start;
}

.cart-line-image {
  width: 5rem;
  height: 5rem;
  flex: 0 0 auto;
  border-radius: 0.5rem;
  overflow: hidden;
  /* No tile: the line drawing floats on the paper, as it does on the
     homepage grid. The box keeps its size so rows still line up. */
  background: transparent;
}

.cart-line--lg .cart-line-image { width: 6.5rem; height: 6.5rem; }

/* The drawer lives outside .page-content, so main.css's dark-mode SVG invert
   never reaches its thumbnails. Same filter, same reason. */
[data-theme="dark"] .cart-line-image img[src$=".svg"] {
  filter: invert(91%) sepia(17%) saturate(166%) hue-rotate(1deg) brightness(94%) contrast(88%);
}
.cart-line-image img { width: 100%; height: 100%; object-fit: cover; display: block; }

.cart-line-body { flex: 1; min-width: 0; }

.cart-line-title {
  color: var(--foreground);
  text-decoration: none;
  font-size: 0.9375rem;
  display: block;
}

.cart-line-title:hover { text-decoration: underline; text-decoration-style: wavy; }

.cart-line-variant {
  margin: 0.125rem 0 0.5rem;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
}

.cart-line-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.cart-line-price { font-size: 0.9375rem; }
.cart-line-qty-fixed { font-size: 0.8125rem; color: var(--muted-foreground); }

.cart-line-remove {
  background: none;
  border: none;
  color: var(--muted-foreground);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.25rem;
}

.cart-line-remove:hover { color: var(--foreground); }

.cart-empty,
.cart-loading {
  color: var(--muted-foreground);
  padding: 2rem 0;
  text-align: center;
}

.cart-subtotal {
  display: flex;
  justify-content: space-between;
  font-size: 1.0625rem;
  margin-bottom: 0.25rem;
}

.cart-fineprint {
  font-size: 0.75rem;
  color: var(--muted-foreground);
  margin: 0 0 1rem;
}

.cart-checkout-btn { width: 100%; justify-content: center; }

/* --- Cart page ------------------------------------------------------------ */
.cart-grid {
  display: grid;
  grid-template-columns: 1fr 18rem;
  gap: 3rem;
  align-items: start;
  margin-bottom: 4rem;
}

.cart-summary {
  position: sticky;
  top: 8rem;
}

.cart-summary h2 {
  margin: 0 0 1rem;
  font-size: 1rem;
}

.summary-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.375rem 0;
  font-size: 0.875rem;
}

.summary-row span:last-child { text-align: right; white-space: nowrap; }

.summary-row--total {
  margin-top: 0.75rem;
  font-size: 1.0625rem;
  font-weight: 500;
}

.cart-summary .btn {
  width: 100%;
  justify-content: center;
  margin-top: 1.25rem;
}

.cart-keep {
  display: block;
  text-align: center;
  margin-top: 0.75rem;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
}

.cart-empty-state {
  text-align: center;
  padding: 4rem 0;
}

.cart-empty-state p { color: var(--muted-foreground); margin-bottom: 1.5rem; }

.cart-notices {
  list-style: none;
  padding: 1rem 1.25rem;
  margin: 0 0 2rem;
  border-radius: 0.5rem;
  background: var(--surface);
  font-size: 0.875rem;
}

.cart-notices li + li { margin-top: 0.5rem; }
.cart-error { color: var(--muted-foreground); padding: 2rem 0; }

/* --- Cart page: ship-to region -------------------------------------------
   Picked before checkout because Stripe's hosted page shows every shipping
   option to everyone — the region decides the one rate it gets offered. */
.cart-region {
  margin: 0.75rem 0 0.25rem;
}

.cart-region label {
  display: block;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  margin-bottom: 0.25rem;
}

.cart-region select {
  width: 100%;
  padding: 0.5rem 2.5rem 0.5rem 0.75rem;
  border: none;
  /* Own chevron, inset from the edge — the native one is pinned to the
     border regardless of padding. Ink in light, paper in dark. */
  appearance: none;
  background: var(--surface) var(--cart-chevron) no-repeat right 0.875rem center / 0.75rem 0.75rem;
  color: var(--foreground);
  font-family: inherit;
  font-size: 0.875rem;
  border-radius: 0.5rem;
  --cart-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232A2824' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

[data-theme="dark"] .cart-region select {
  --cart-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ECE3CE' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}

.cart-region select:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 1.5px var(--foreground);
}

.cart-fineprint--center { text-align: center; margin: 0.75rem 0 0; }

.cart-checkout-btn:disabled {
  opacity: 0.6;
  cursor: progress;
}

/* --- Confirmation --------------------------------------------------------- */
/* Body size, same as every other page — the old receipt page bumped this up. */
.thanks-page { max-width: 34rem; margin-bottom: 6rem; }
.thanks-lede { margin-bottom: 1.5rem; }

/* --- Responsive ----------------------------------------------------------- */
@media (max-width: 1024px) {
}

@media (max-width: 900px) {
  .cart-grid {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .cart-summary { position: static; }
}

@media (max-width: 768px) {
  .cart-drawer-panel { width: 100%; }
}

.cart-summary h2 + * { margin-top: 0; }

/* --- "Available to buy" mark on the homepage archive card ----------------
   The only signal that a project is buyable: an ink disc with a paper "$".
   Ink/paper rather than accent — the archive grid stays quiet, and the accent
   is left to mean "active/current" as it does elsewhere.

   Alignment: the disc stays INLINE in the text flow (vertical-align: middle)
   rather than being a flex sibling of the title text. Flex looked identical on
   one-line titles but detached the disc to the right of the whole block as soon
   as a title wrapped — which it does on mobile. Inline keeps it trailing the
   last word wherever that lands. */
/* The pill is positioned against the thumbnail box, which needs to be the
   containing block. The box already clips and rounds (main.css), so the pill
   inherits its corner. */
.project-image { position: relative; }

.for-sale-mark {
  position: absolute;
  right: 0.625rem;
  bottom: 0.625rem;
  /* Ink pill carrying the Made wordmark in paper — the .btn inversion, so it
     flips with the theme. Sized so the mark's strokes stay ≥ ~2px. */
  background: var(--foreground);
  color: var(--background);
  display: inline-flex;
  align-items: center;
  height: 1.625rem;
  padding: 0 0.75rem;
  border-radius: 999px;
  pointer-events: none;
}

/* The wordmark (inline SVG, currentColor) wherever it appears on a pill.
   Explicit width (360:143) so both pills measure the same, and max-* reset
   because the card pill sits inside .project-image, whose `svg { max-width:
   80% }` rule is meant for the illustration and was shrinking the mark. The
   bottom margin lifts the mark ~1.5px in the flex-centred pill: the "d"
   ascender makes the box taller than the word's body, which otherwise sits
   low. */
.for-sale-mark .made-mark,
.tag-filter .made-mark {
  display: block;
  height: 0.875rem;
  width: 2.203rem;
  max-width: none;
  max-height: none;
  margin-bottom: 0.1875rem;
}

/* The card scales its thumbnail on hover; the pill rides along with it, which
   keeps it pinned to the same corner of the same box. Nothing extra needed. */

/* The Made filter in the tag bar is the same pill as the card marks, so the
   filter and the marks read as one device. Resting state is the outline
   (paper pill, ink text, thin ink ring — the ring keeps the silhouette on the
   paper); selecting it fills to the solid ink pill the thumbnails wear. No
   underline on hover, unlike the text filters: the pill lifts instead. Sits
   among plain-text filters, so it's centred on the row rather than stretched. */
.tag-filter[data-filter="made"] {
  align-self: center;
  background: var(--background);
  color: var(--foreground);
  box-shadow: inset 0 0 0 1.5px var(--foreground);
  line-height: 1;
  display: inline-flex;
  align-items: center;
  height: 1.625rem;
  padding: 0 0.75rem;
  border-radius: 999px;
  transition: transform 150ms ease, background-color 150ms ease, color 150ms ease;
}

.tag-filter[data-filter="made"]:hover {
  transform: translateY(-1px);
  font-weight: 700;
  text-decoration: none;
}

.tag-filter[data-filter="made"].active {
  background: var(--foreground);
  color: var(--background);
  box-shadow: none;
  font-weight: 700;
  text-decoration: none;
}

@media (prefers-reduced-motion: reduce) {
  .tag-filter[data-filter="made"]:hover { transform: none; }
}

/* --- Buy block on a project page -----------------------------------------
   No card: the block sits on the paper between the meta line and the body,
   held together by whitespace, the same way the meta line sits. (The 1px
   bordered --surface box was dropped Sept 2026 — see CLAUDE.md.) */
.buy-block {
  margin: 0 0 3.5rem;
  max-width: 30rem;
}

.buy-head {
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  margin-bottom: 1.25rem;
}

.buy-price {
  margin: 0;
  font-size: 1.5rem;
  font-family: 'IBM Plex Sans', sans-serif;
  font-weight: 700;
}

/* Small outlined pill beside the price: "digital download" / "archived". */
.buy-tag {
  font-family: 'IBM Plex Sans', sans-serif;
  font-size: 0.6875rem;
  font-weight: 700;
  line-height: 1;
  color: var(--muted-foreground);
  box-shadow: inset 0 0 0 1.5px var(--border);
  border-radius: 999px;
  padding: 0.3125rem 0.5rem;
}

.buy-soldout { margin: 0; font-size: 0.9375rem; }

.buy-fineprint {
  margin: 1rem 0 0;
  font-size: 0.75rem;
  color: var(--muted-foreground);
}

/* --- Variant picker: pills -------------------------------------------------
   The same control the homepage's Made filter uses: outlined pill at
   rest, solid ink when chosen, a 1px lift on hover. Each pill is the <label>
   around a real radio, so keyboard and screen-reader behaviour is the native
   radio group's; the radio itself is drawn off-screen. */
.product-variants {
  border: none;
  padding: 0;
  margin: 0 0 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.product-label {
  padding: 0;
  color: var(--muted-foreground);
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  margin-bottom: 0.5rem;
  /* A <legend> can't be a flex item; take the full row instead. */
  width: 100%;
  float: left;
}

.variant {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  height: 2rem;
  padding: 0 0.875rem 1px;
  border-radius: 999px;
  background: var(--background);
  color: var(--foreground);
  box-shadow: inset 0 0 0 1.5px var(--foreground);
  font-family: 'IBM Plex Sans', sans-serif;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1;
  cursor: pointer;
  transition: transform 150ms ease, background-color 150ms ease, color 150ms ease;
}

.variant input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
  margin: 0;
  pointer-events: none;
}

.variant:hover { transform: translateY(-1px); }

.variant:has(input:checked) {
  background: var(--foreground);
  color: var(--background);
  box-shadow: none;
}

.variant:has(input:focus-visible) {
  outline: 2px solid var(--foreground);
  outline-offset: 2px;
}

.variant-price { font-weight: 400; }

/* Colour dot, ringed in the pill's current text colour so it survives both
   states: black on the paper pill gets an ink ring, black on the ink pill a
   paper ring, and white/clear the reverse. */
.variant-swatch {
  flex: 0 0 auto;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  background: var(--swatch);
  box-shadow: inset 0 0 0 1px currentColor;
}

/* Sold out: muted ring and text, the name struck through. The "sold out"
   flag stays in the markup for screen readers but isn't drawn — the strike
   says it. */
.variant.is-soldout {
  color: var(--muted-foreground);
  box-shadow: inset 0 0 0 1.5px var(--border);
  cursor: not-allowed;
}

.variant.is-soldout:hover { transform: none; }
.variant.is-soldout .variant-name { text-decoration: line-through; }

.variant-flag {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .variant, .variant:hover { transform: none; transition: none; }
}

.product-stock {
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  margin: 0 0 1rem;
}

.product-stock.is-low { color: var(--foreground); font-weight: 500; }

.product-actions {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
}

.qty-stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--border);
  background: var(--background);
  height: 2.5rem;
  border-radius: 1.875rem;
  overflow: hidden;
}

.qty-btn {
  width: 2.25rem;
  height: 100%;
  background: none;
  border: none;
  color: var(--foreground);
  font-size: 1.125rem;
  cursor: pointer;
  line-height: 1;
}

.qty-btn:hover:not(:disabled) { background: var(--surface); }
.qty-btn:disabled { opacity: 0.3; cursor: not-allowed; }

.qty-input {
  width: 2.5rem;
  border: none;
  background: none;
  text-align: center;
  color: var(--foreground);
  font-family: inherit;
  font-size: 0.9375rem;
  -moz-appearance: textfield;
}

.qty-input::-webkit-outer-spin-button,
.qty-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.qty-stepper--sm { height: 1.875rem; }
.qty-stepper--sm .qty-btn { width: 1.75rem; font-size: 0.9375rem; }
.qty-value { min-width: 1.5rem; text-align: center; font-size: 0.875rem; }

/* --- Archived product ----------------------------------------------------
   Sold once, not again. The price and options still show — they're part of
   the record — but nothing is interactive: muted price, muted outlined pills
   that don't respond, and a dead "Archived" button. */
.buy-block.is-archived .buy-price { color: var(--muted-foreground); }

.buy-tag--archived {
  box-shadow: inset 0 0 0 1.5px var(--foreground);
  color: var(--foreground);
}

/* Static pills, not labels: no radio, no pointer, nothing focusable. */
.variant.is-disabled {
  cursor: default;
  color: var(--muted-foreground);
  box-shadow: inset 0 0 0 1.5px var(--border);
}

.variant.is-disabled:hover { transform: none; }

.buy-block.is-archived .product-label {
  text-transform: none;
  letter-spacing: 0;
}

.btn:disabled,
.btn[disabled] {
  background: var(--muted);
  color: var(--background) !important;
  cursor: not-allowed;
  opacity: 0.65;
}

.btn:disabled:hover,
.btn[disabled]:hover {
  background: var(--muted);
  color: var(--background) !important;
}
