/* ==========================================================================
   BUYMYSICKSHIT — PLATE
   ==========================================================================
   THESIS: the page is an etching plate.

   The product is acid-etched steel: metal chemically removed so THE DESIGN IS
   THE HOLE. v1/v2 rendered that idea as flat filled rectangles, which argues
   the opposite. This layer makes the page enact the process instead:

     - The headline is CUT FROM METAL. Real brushed-steel photography clipped
       through the letterforms. The words are the hole. That is the one thing
       someone remembers.
     - Plate furniture: registration marks, plate numbers, edge rules. The
       page is dressed as a specimen sheet, not a landing page.
     - The A-Z becomes a WALL, full-bleed, oversized. It is the most
       distinctive asset in the catalogue and it was buried at 64px.
     - Grid is broken on purpose: the hero object bleeds off the right edge,
       section numerals sit oversized behind content, bands alternate weight.

   TYPE — deliberately NOT the inherited Anton. Anton is the default "bold
   condensed" pick and reads as generic. Replaced with:
     display : Big Shoulders Display 800 — industrial, flat sharp terminals,
               drawn like a stencil cut rather than a poster face.
     chrome  : Martian Mono — wide technical mono, instrument-panel register.
               Every label, spec, price and plate number is set in it.
     body    : Archivo (kept) — neutral, lets the display carry the character.
   The neutral RAMP is unchanged; the teaztown palette still governs colour.
   ========================================================================== */

:root {
  --font-display: "Big Shoulders Display", "Arial Narrow", Impact, sans-serif;
  --font-chrome:  "Martian Mono", ui-monospace, "Cascadia Mono", monospace;
  --font-body:    "Archivo", system-ui, -apple-system, sans-serif;

  --plate-edge: #2B2A27;
  --mark:       #4E514F;
  --size-micro: 11px;            /* mono runs small; it has width to spare */
}

h1, h2, h3, h4 { font-weight: 800; }

/* Mono needs tighter tracking than a proportional face at label sizes. */
.micro, .card__sku, .card__price, .step__n, .spec th, .ship-bar__text,
.site-nav a, .cart-btn, .btn, .disclose__k, .site-footer__base, .site-footer a {
  font-family: var(--font-chrome);
  letter-spacing: -0.02em;
}

/* ==========================================================================
   PLATE FURNITURE — registration marks + plate numbers.
   Pure CSS, no extra DOM, no images, no runtime cost.
   ========================================================================== */
.band { position: relative; }

/* Corner registration marks — the crop marks on a printing plate. */
.band::before,
.band::after {
  content: "";
  position: absolute;
  width: 14px; height: 14px;
  pointer-events: none;
  opacity: .55;
}
.band::before {
  top: 18px; left: 18px;
  border-top: 1px solid var(--mark);
  border-left: 1px solid var(--mark);
}
.band::after {
  bottom: 18px; right: 18px;
  border-bottom: 1px solid var(--mark);
  border-right: 1px solid var(--mark);
}

/* Oversized ghosted plate numeral behind each section head. */
.band__head { position: relative; }
.band__head[data-plate]::before {
  content: attr(data-plate);
  position: absolute;
  right: 0; top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-display);
  font-size: clamp(80px, 13vw, 180px);
  line-height: 1;
  color: var(--bone);
  opacity: .045;
  pointer-events: none;
  z-index: 0;
}
.band__head > * { position: relative; z-index: 1; }

/* ==========================================================================
   THE HEADLINE IS CUT FROM METAL.
   Real brushed-steel photography clipped through the letterforms — the type
   is a window onto the plate, not ink sitting on it. This is the argument of
   the whole product expressed as a single visual move.
   ========================================================================== */
.hero { padding-block: 0 var(--section-pad); }

.hero__title {
  font-family: var(--font-display);
  font-size: clamp(64px, 15.5vw, 210px);
  line-height: 0.82;
  margin: 0 0 var(--stack-m);
  max-width: none;
  text-transform: uppercase;

  background-image:
    linear-gradient(180deg, rgba(255,255,255,.30), rgba(255,255,255,0) 62%),
    url("/assets/img/atmos/brushed-stainless-steel-texture-1.jpg");
  background-size: cover, 118% auto;
  background-position: center, center 42%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;

  /* A cut edge catches light on one side and shadow on the other. */
  filter: drop-shadow(0 1px 0 rgba(0,0,0,.85))
          drop-shadow(0 -1px 0 rgba(255,255,255,.10));
}

/* Fallback: if background-clip:text is unsupported the text must still be
   readable rather than invisible. */
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero__title { color: var(--bone); -webkit-text-fill-color: var(--bone);
                 background: none; filter: none; }
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.32fr) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 64px);
  align-items: end;
  padding-top: clamp(40px, 7vw, 96px);
}

/* The object bleeds off the right edge of the viewport. Grid-breaking is the
   point: a centred box inside a centred box reads as a template. */
.hero__figure {
  border: 0; background: none;
  margin-right: calc(var(--shell-pad) * -1 - 4vw);
  position: relative;
}
.hero__figure img {
  aspect-ratio: auto;
  width: 100%;
  filter: contrast(1.06) brightness(.96);
}
/* Cut edge along the object's left side. */
.hero__figure::before {
  content: "";
  position: absolute; inset: 0 auto 0 -1px; width: 1px;
  background: linear-gradient(180deg, transparent, var(--mark) 22%, var(--mark) 78%, transparent);
}


@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; align-items: start; }
  .hero__figure { margin-right: calc(var(--shell-pad) * -1); order: -1; }
  .hero__title { font-size: clamp(52px, 17vw, 96px); }
}

/* ==========================================================================
   THE LETTER WALL.
   26 SKUs from one design family — the most distinctive thing in the
   catalogue. It was a 64px chip rail buried mid-page. Now it is full-bleed
   and oversized, and it reads as a specimen sheet of the whole alphabet.
   ========================================================================== */
.letters--wall {
  display: grid;
  grid-template-columns: repeat(13, minmax(0, 1fr));
  gap: 1px;
  background: var(--plate-edge);
  border-block: 1px solid var(--plate-edge);
  width: 100vw;
  margin-left: calc(50% - 50vw);
}
.letters--wall .letter {
  aspect-ratio: 1 / 1;
  min-height: 0;
  font-family: var(--font-display);
  font-size: clamp(20px, 3.6vw, 54px);
  font-weight: 800;
  color: var(--steel);
  background: var(--ink);
  position: relative;
  overflow: hidden;
}
/* Hovering cuts the letter out of steel — the same move as the headline, so
   the interaction teaches the product rather than just highlighting. */
.letters--wall .letter::after {
  content: attr(data-l);
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background-image: url("/assets/img/atmos/brushed-stainless-steel-texture-1.jpg");
  background-size: 320% auto;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  opacity: 0;
  transition: opacity 180ms var(--fluid);
}
.letters--wall .letter:hover { color: transparent; background: var(--ink-raised); }
.letters--wall .letter:hover::after { opacity: 1; }
.letters--wall .letter:disabled { opacity: .18; }
.letters--wall .letter:disabled:hover { background: var(--ink); }

@media (max-width: 720px) {
  .letters--wall { grid-template-columns: repeat(7, minmax(0, 1fr)); }
}

/* ==========================================================================
   BAND RHYTHM — v2 was six near-identical dark bands. Alternate the weight so
   the page has a pulse instead of a hum.
   ========================================================================== */
.band--plate {
  background:
    linear-gradient(180deg, rgba(244,239,227,.028), transparent 42%),
    var(--ink-raised);
  border-block: 1px solid var(--plate-edge);
}

/* Section heads sit on a rule with their plate number, spec-sheet style. */
.band__head {
  border-bottom: 1px solid var(--plate-edge);
  padding-bottom: var(--stack-s);
  align-items: end;
}
.band__title {
  font-size: clamp(30px, 4.4vw, 58px);
  line-height: .92;
}

/* ==========================================================================
   CARDS — flat panels became plate cells: hairline frame, mono spec footer.
   ========================================================================== */
.card__media {
  border: 1px solid var(--plate-edge);
  background: var(--slot);
  position: relative;
}
.card__media::after {           /* cell registration tick */
  content: "";
  position: absolute; top: 7px; left: 7px;
  width: 7px; height: 7px;
  border-top: 1px solid var(--mark); border-left: 1px solid var(--mark);
  opacity: .6;
}
.card__title { font-size: 13px; line-height: 1.35; }
.card__meta {
  border-top: 1px solid var(--plate-edge);
  padding-top: 7px; margin-top: 7px;
}
.card__price { font-size: 13px; }
.card__sku   { font-size: 10px; }

/* ==========================================================================
   TAGLINE — full-bleed plate band, set in the display face at scale.
   ========================================================================== */
.tagline {
  border-block: 1px solid var(--plate-edge);
  background: var(--ink-deep);
}
.tagline__copy {
  font-size: clamp(38px, 7.2vw, 104px);
  line-height: .95;
  max-width: 15ch;
}

/* ==========================================================================
   SPEC TABLE — instrument readout.
   ========================================================================== */
.spec td { font-family: var(--font-chrome); font-size: 13px; }
.spec th { font-size: 10px; }
.spec .unresolved { font-size: 10px; }

/* ==========================================================================
   FULL-BLEED OVERFLOW FIX.
   `width:100vw` includes the scrollbar gutter, so the letter wall was ~15px
   wider than the document and produced real horizontal scroll (measured:
   h-overflow=true at 1280).

   `overflow-x: clip` — NOT `hidden`. `hidden` establishes a scroll container,
   which silently kills `position: sticky` on the header. `clip` crops without
   creating one, so the sticky header survives.
   ========================================================================== */
html, body { overflow-x: clip; }

/* Belt and braces: size the wall to the document rather than the viewport, so
   it stays correct even where `clip` is unsupported. */
.letters--wall {
  width: auto;
  margin-inline: calc(var(--shell-pad) * -1);
}
@supports (width: 100dvw) {
  .letters--wall {
    width: 100dvw;
    margin-left: calc(50% - 50dvw);
    margin-right: 0;
  }
}

/* ==========================================================================
   AMBIENT PLATE FIELD — background motion.
   ==========================================================================
   PERFORMANCE CONTRACT (optimize-web-animations):
   - Three layers, all `position: fixed`, all behind content (z-index 0).
   - ONLY transform and opacity animate. Never background-position, never
     width/top/left — those repaint or reflow every frame.
   - No JS, no rAF, no canvas, no WebGL. The compositor runs these off the
     main thread, so scrolling and the cart stay responsive.
   - `pointer-events: none` throughout — the field can never eat a click.
   - Killed entirely under prefers-reduced-motion.
   -------------------------------------------------------------------------- */
.field {
  position: fixed;
  inset: -20vmax;                /* oversize so drifting never exposes an edge */
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  contain: strict;               /* isolate from the rest of the layout tree */
}
/* Lift page content above the ambient .field layer.
   EXCLUDES anything that owns its own positioning. `body > *:not(.field)` has
   specificity (0,1,1) — the :not() contributes its argument's class weight —
   which BEATS `.drawer` at (0,1,0). That silently overrode
   `position: fixed` on the cart drawer, so the drawer stopped being
   off-canvas and rendered inline at the bottom of every page: "Nothing in the
   cart yet / Subtotal $0.00 / Checkout" as visible page content.
   Anything position-critical must be listed here. */
body > *:not(.field):not(.drawer):not(#scrim):not(.site-header):not(.navpanel) {
  position: relative;
  z-index: 1;
}

/* Layer 1 — the plate itself, drifting. Brushed steel, barely there, moving
   slowly enough that you register it as surface rather than as animation. */
.field__steel {
  position: absolute; inset: 0;
  background-image: url("/assets/img/atmos/brushed-stainless-steel-texture-1.jpg");
  background-size: 680px auto;
  background-repeat: repeat;
  opacity: .07;
  mix-blend-mode: overlay;
  will-change: transform;
  animation: drift 96s linear infinite;
}
@keyframes drift {
  0%   { transform: translate3d(0, 0, 0)        rotate(0deg); }
  50%  { transform: translate3d(-56px, -38px, 0) rotate(.35deg); }
  100% { transform: translate3d(0, 0, 0)        rotate(0deg); }
}

/* Layer 2 — the etch scan. A slow band of light travelling down the plate,
   the way a scanner or an etch bath front moves across a sheet. This is the
   one that reads as "something is happening". */
.field__scan {
  position: absolute;
  left: 0; right: 0; height: 46vh;
  top: -46vh;
  background: linear-gradient(180deg,
    transparent 0%,
    rgba(244,239,227,.020) 38%,
    rgba(244,239,227,.055) 50%,
    rgba(244,239,227,.020) 62%,
    transparent 100%);
  will-change: transform;
  animation: scan 19s cubic-bezier(.55,0,.45,1) infinite;
}
@keyframes scan {
  0%   { transform: translate3d(0, 0, 0);        opacity: 0; }
  8%   { opacity: 1; }
  92%  { opacity: 1; }
  100% { transform: translate3d(0, 190vh, 0);    opacity: 0; }
}

/* Layer 3 — vignette, breathing. Pulls the eye to the centre column and keeps
   the corners from going flat. Opacity only. */
.field__vig {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse 120% 90% at 50% 42%,
              transparent 40%, rgba(0,0,0,.55) 100%);
  will-change: opacity;
  animation: breathe 24s ease-in-out infinite;
}
@keyframes breathe {
  0%, 100% { opacity: .82; }
  50%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .field__steel, .field__scan, .field__vig { animation: none; }
  .field__scan { display: none; }
}

/* The old body::before texture is superseded by .field__steel. */
body::before { content: none; }

/* ==========================================================================
   MULTI-PAGE — page heads, nav current state, index cards.
   ========================================================================== */
.page-head {
  padding-block: clamp(48px, 8vw, 104px) var(--stack-xl);
  border-bottom: 1px solid var(--plate-edge);
}
.page-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(46px, 9.5vw, 128px);
  line-height: .86;
  text-transform: uppercase;
  margin: var(--stack-s) 0 var(--stack-m);
  background-image:
    linear-gradient(180deg, rgba(255,255,255,.26), rgba(255,255,255,0) 66%),
    url("/assets/img/atmos/brushed-stainless-steel-texture-1.jpg");
  background-size: cover, 130% auto;
  background-position: center, center 40%;
  -webkit-background-clip: text; background-clip: text;
  color: transparent; -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 1px 0 rgba(0,0,0,.8));
}
@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
  .page-title { color: var(--bone); -webkit-text-fill-color: var(--bone);
                background: none; filter: none; }
}

/* B9 — the current page MUST be indicated in the navigation. */
.site-nav a[aria-current="page"] {
  color: var(--bone);
  border-bottom: 1px solid var(--bone);
  padding-bottom: 2px;
}

/* Home index — four routes into the site, as plate cells. */
.index-grid {
  display: grid; gap: 1px;
  background: var(--plate-edge);
  border: 1px solid var(--plate-edge);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.index-card {
  display: flex; flex-direction: column; gap: 6px;
  background: var(--ink);
  padding: var(--stack-m);
  min-height: 168px;
  transition: background var(--dur) var(--fluid);
}
.index-card:hover { background: var(--ink-raised); }
.index-card__n {
  font-family: var(--font-chrome); font-size: 10px; color: var(--steel-dim);
}
.index-card__t {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(24px, 3vw, 38px); line-height: 1;
  text-transform: uppercase; color: var(--bone);
  margin-top: auto;
}
.index-card__d {
  font-family: var(--font-body); font-size: 13px; color: var(--steel);
  line-height: 1.45;
}

/* --------------------------------------------------------------------------
   NO-JS NOTICE
   The catalogue, cart and checkout are all client-rendered, so with scripts
   off the store is silent. An empty page that looks fine is worse than one
   that says why it is empty.
   -------------------------------------------------------------------------- */
.noscript-note {
  position: relative; z-index: 5;
  margin: 0; padding: 18px 24px;
  background: var(--ink); color: var(--bone);
  border-bottom: 1px solid var(--steel);
  font-family: var(--font-chrome); font-size: 13px; line-height: 1.6;
}
.noscript-note p { margin: 0 0 6px; max-width: 68ch; }
.noscript-note p:last-child { margin-bottom: 0; }

/* Checkout refusal reason. Deliberately a separate element from .drawer__note,
   which updateThreshold() rewrites on every render. */
.drawer__alert {
  margin: 10px 0 0; padding: 10px 12px;
  background: color-mix(in srgb, var(--pvd-gold) 12%, transparent);
  border-left: 2px solid var(--pvd-gold);
  color: var(--bone);
  font-family: var(--font-chrome); font-size: 12px; line-height: 1.5;
}
.drawer__alert[hidden] { display: none; }


/* ==========================================================================
   THE DROP — purchasable product on the homepage.
   ==========================================================================
   The homepage previously showed nothing that was for sale. This is the grid
   that fixes that, and it is built out of the plate language already in use
   above: hairline-separated cells like .letters--wall and .index-grid, the
   same registration tick as .card__media, and the --slot-* tokens that exist
   specifically for a cell with no photograph in it.

   WHY THE CELLS ARE EMPTY. 57 of the 58 SKUs have never been photographed,
   and nothing here invents a shot for them. Instead of repeating one apology
   twenty-one times, each cell carries its OWN SKU as the numeral — the same
   move as the oversized plate number behind every section head. Because every
   SKU differs, twenty-one cells read as a specimen sheet rather than as
   twenty-one identical grey boxes. It is a position on a plate, not a
   placeholder waiting to be replaced.

   ZERO IMAGES in this grid, deliberately: the hero AVIF is the LCP element
   and nothing added below the fold is allowed to compete with it for early
   bandwidth.
   ========================================================================== */
.pgrid {
  display: grid;
  gap: 0;
  grid-template-columns: repeat(auto-fill, minmax(206px, 1fr));
  /* Hairlines are drawn by the CELLS (border-right/bottom), closed off at the
     top and left by the container. The obvious construction — gap:1px over a
     --plate-edge background — paints that background across every cell the
     last row is short of, which rendered as a large grey slab whenever the
     card count was not an exact multiple of the responsive column count.
     Here an incomplete final row is simply empty. */
  border-top:  1px solid var(--plate-edge);
  border-left: 1px solid var(--plate-edge);
}

.pcard {
  display: flex;
  flex-direction: column;
  background: var(--ink);
  border-right:  1px solid var(--plate-edge);
  border-bottom: 1px solid var(--plate-edge);
  padding: 14px;
  transition: background var(--dur) var(--fluid);
}
.pcard:hover { background: var(--ink-raised); }

/* Stretch the title's anchor over the whole card so the card stays clickable,
   then raise the button above it. Without the z-index the overlay would eat
   every click meant for Add. */
.pcard { position: relative; }
.pcard__t::after { content: ''; position: absolute; inset: 0; z-index: 0; }
.pcard__add {
  position: relative; z-index: 1;
  margin-top: 10px; width: 100%; min-height: 40px;
  font: inherit; font-family: var(--font-chrome); font-size: var(--size-chrome);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink); background: none;
  border: var(--hairline) solid var(--rule); border-radius: 0;
  cursor: pointer; transition: background .14s ease, border-color .14s ease;
}
.pcard__add:hover { background: var(--ink-raised); border-color: var(--ink-dim, #8f8a7e); }
.pcard__add:focus-visible { outline: var(--hairline) solid var(--ink); outline-offset: 2px; }
.pcard__add[data-added] { border-color: var(--pvd-gold, #C9BFA6); color: var(--pvd-gold, #C9BFA6); }
@media (prefers-reduced-motion: reduce) { .pcard__add { transition: none; } }

.pcard__cell {
  position: relative;
  display: grid; place-items: center;
  aspect-ratio: 1 / 1;
  margin-bottom: 12px;
  background: var(--slot);
  border: 1px solid var(--slot-line);
}
.pcard__cell::after {                 /* same registration tick as .card__media */
  content: "";
  position: absolute; top: 7px; left: 7px;
  width: 7px; height: 7px;
  border-top: 1px solid var(--mark); border-left: 1px solid var(--mark);
  opacity: .6;
}
.pcard__no {
  font-family: var(--font-chrome);
  font-size: clamp(14px, 1.6vw, 20px);
  letter-spacing: -0.02em;
  color: var(--slot-text);
}

.pcard__t {
  font-family: var(--font-chrome);
  font-size: 12px; line-height: 1.4;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--bone);
}
.pcard__m {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px;
  margin-top: auto;                   /* price row bottom-aligns across cells */
  padding-top: 8px;
  border-top: 1px solid var(--plate-edge);
}
.pcard__p {
  font-family: var(--font-chrome); font-size: 14px;
  letter-spacing: -0.02em;
  color: var(--bone);
  font-variant-numeric: tabular-nums;
}
/* Sub-threshold pieces are flagged, not hidden. A $3 charm cannot carry a
   parcel on its own — the shipping bar is the reason, this is the label. */
.pcard__s {
  font-family: var(--font-chrome); font-size: 10px;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--steel-dim);
}

@media (max-width: 720px) {
  /* Two real columns rather than one 21-cell column. auto-fill at 206px would
     collapse to a single column inside a 350px shell. */
  .pgrid    { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pcard    { padding: 11px; }
  .pcard__t { font-size: 11px; }
}

/* --------------------------------------------------------------------------
   THE LETTER SYSTEM — the remaining 26 SKUs, as one row.
   The full wall lives on /letters.html; repeating it here would be the same
   asset twice. This is the A-Z set at poster scale as a single link, which
   states the family, the count and the price without duplicating the wall.
   Plain wrapping text, NOT a 26-cell flex row: the display face loads async,
   so anything relying on its exact metrics can overflow before the swap.
   -------------------------------------------------------------------------- */
.letterline {
  display: block;
  margin-top: var(--stack-xl);
  padding-block: clamp(18px, 2.6vw, 30px);
  border-block: 1px solid var(--plate-edge);
  transition: background var(--dur) var(--fluid);
}
.letterline:hover { background: var(--ink-raised); }
.letterline__az {
  display: block;
  font-family: var(--font-display); font-weight: 800;
  /* 64px broke the run after W and left an orphan "X Y Z" line at 1440.
     50px sets all 26 on one line there; balance splits it evenly where it
     still has to wrap, rather than dropping three letters onto line two. */
  font-size: clamp(23px, 4.1vw, 50px);
  line-height: 1.06;
  text-wrap: balance;
  word-spacing: .1em;
  color: var(--steel);
  transition: color var(--dur) var(--fluid);
}
.letterline:hover .letterline__az { color: var(--bone); }
.letterline__m {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: var(--stack-s);
  margin-top: var(--stack-s); padding-top: var(--stack-s);
  border-top: 1px solid var(--plate-edge);
}
.letterline__t {
  font-family: var(--font-chrome); font-size: 13px;
  letter-spacing: -0.02em; text-transform: uppercase; color: var(--bone);
}
.letterline__d {
  font-family: var(--font-chrome); font-size: 11px;
  letter-spacing: -0.02em; text-transform: uppercase; color: var(--steel);
}
