/* ============================================================
   Ink Fusion v28 — base: reset, typography, overlays, shared bits
   ============================================================ */
* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-body);
  line-height: 1.5;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
/* paper halftone texture */
body::before {
  content: "";
  position: fixed; inset: 0; z-index: 9998; pointer-events: none; opacity: 0.4;
  background-image: radial-gradient(rgba(21,19,16,0.14) 1px, transparent 1.3px);
  background-size: 6px 6px; mix-blend-mode: multiply;
}
*::selection { background: var(--mag-ground); color: var(--paper); }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 48px; }
.mono { font-family: var(--f-mono); }
@media (max-width: 860px) { .wrap { padding: 0 20px; } }

/* animated film grain */
#grain {
  position: fixed; inset: -40%; z-index: 9997; pointer-events: none;
  opacity: 0.05; mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
  animation: grain 1.2s steps(3) infinite;
}
@keyframes grain {
  0% { transform: translate(0, 0); }
  33% { transform: translate(-5%, 3%); }
  66% { transform: translate(4%, -4%); }
  100% { transform: translate(5%, 4%); }
}

/* CMYK chip cluster */
.chips { display: inline-flex; gap: 5px; }
.chips i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
.chips i:nth-child(1) { background: var(--cyan); }
.chips i:nth-child(2) { background: var(--mag); }
.chips i:nth-child(3) { background: var(--yel); }
.chips i:nth-child(4) { background: var(--ink); }

/* eyebrow */
.eyebrow {
  font-family: var(--f-mono); font-size: 12px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 12px;
  background: var(--yel); color: var(--ink); padding: 7px 14px; border: 2px solid var(--ink);
}

/* scroll reveal */
.reveal { opacity: 0; transform: translateY(24px); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }
.reveal.in { opacity: 1; transform: none; }

/* reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01s !important;
  }
  /* scroll-behavior is neither an animation nor a transition, so the rule above
     never reached it: a vestibular-sensitive visitor pressing the skip link still
     got a full animated scroll of the document. */
  html { scroll-behavior: auto !important; }
  #grain { display: none !important; }
  .pinwrap { height: auto !important; }
}

/* ============================================================
   BASE LAYER RECLAIMED FROM main.min.css — 2026-09-03
   ------------------------------------------------------------
   The legacy pre-v28 stylesheet was ~96% dead but carried the
   site's ONLY base layer. It also painted `.page-hero` dark while
   site-v28 painted its text dark, which made the hero unreadable
   on all fifteen v28 pages. These are the rules worth keeping,
   restated in v28 tokens so the legacy sheet can go.

   Deliberately NOT brought across:
     --base-2 / --color-bg  GeneratePress' theme.json sets
                            body{background:var(--base-2)} and the
                            legacy sheet supplied the value (#f7f8f9).
                            Leaving it undefined is what lets cart and
                            My Account fall through to v28 paper, which
                            is the intended ground.
     .site-account (21 rules)  dead. page-cart.php and page-checkout.php
                            only OVERRIDE the class; nothing renders the
                            markup, and no element exists in the DOM.
     .page-hero dark ground the bug itself.
   ============================================================ */

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

/* Bare headings. site-v28 styles headings only through SCOPED
   selectors (.acct-head h1, h2.split, .filmcard .lbl h3), so without
   this every unscoped h1-h6 fell back to the body face. */
h1, h2, h3, h4, h5, h6 { font-family: var(--f-display); line-height: 1.2; color: var(--ink); }
h1 { font-size: clamp(30px, 5vw, 56px); font-weight: 800; }
h2 { font-size: clamp(26px, 3.5vw, 40px); font-weight: 700; }
h3 { font-size: clamp(20px, 2.5vw, 26px); font-weight: 600; }
h4 { font-size: 20px; font-weight: 600; }
h5, h6 { font-size: 16px; font-weight: 600; }

p { line-height: 1.625; }
ul, ol { list-style: none; }
video { max-width: 100%; display: block; }
button { cursor: pointer; border: none; background: none; font-family: inherit; }
input, textarea, select { font-family: inherit; }
textarea { resize: vertical; }

/* iOS ZOOM GUARD — do not lower below 16px.
   Mobile Safari zooms the viewport when a focused control's text is
   under 16px, which on checkout throws the customer into a zoomed,
   horizontally-scrolled form mid-purchase. This existed ONLY in the
   legacy sheet; losing it silently was the most expensive part of
   removing that file. */
select, textarea,
input[type="text"], input[type="email"], input[type="tel"], input[type="number"],
input[type="password"], input[type="search"], input[type="url"] { font-size: 16px !important; }

/* Accessibility skip target — used by gs-builder-body.php and the
   gang-sheet static shell. Also only defined in the legacy sheet. */
.skip-link {
  position: absolute; top: -100%; left: 16px; z-index: 10000;
  padding: 12px 24px; background: var(--ink); color: var(--paper);
  border-radius: 4px; font-weight: 600;
}
.skip-link:focus { top: 16px; }

/* Screen-reader-only text. Added 2026-09-11 for the comparison tables'
   corner <th>, which was empty — axe flags an unnamed table header, and a
   screen reader announces nothing for the column that labels every row. */
.visually-hidden { position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0);
  clip-path: inset(50%); white-space: nowrap; border: 0; }
