/* ═══════════════════════════════════════════════════════════════════════════
   PrintPal — SWATCH
   A warm dark room with one light over the bench. Everything PrintPal prints
   is a card in a sample deck: the deck is the hero, the catalogue below is
   the same deck laid out flat, and the rest of the page is the bench it sits
   on. One accent, one light, no second idea.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  --room: #141311;
  --room-2: #0c0b0a;
  --room-3: #1c1a17;
  --card: #f6f3ec;
  --card-2: #e7e2d6;
  --ink: #17161a;
  --fg: #efeae0;
  --dim: #97907f;
  --dim-2: #6d6759;
  --line: #2b2822;
  --red: #e72235;
  --red-lift: #ff5b69;

  /* the five presses, each with its own ink */
  --i-digital: #009ee0;
  --i-offset: #e6007e;
  --i-flex: #ffcf00;
  --i-screen: #b8b2a4;
  --i-sublimation: #e72235;

  --body: 'Inter Tight', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, Consolas, monospace;
  --pass-ease: cubic-bezier(.65, 0, .35, 1);
  --gut: clamp(20px, 5vw, 84px);
  --maxw: 1440px;
  --ease: cubic-bezier(.22, .61, .36, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; overflow-x: hidden; }

body {
  margin: 0;
  background: var(--room);
  color: var(--fg);
  font-family: var(--body);
  font-size: clamp(15px, 1vw, 16.5px);
  line-height: 1.55;
  letter-spacing: -.005em;
  -webkit-font-smoothing: antialiased;
  /* one light, hanging over the bench */
  background-image: radial-gradient(ellipse 74% 52% at 62% 22%, rgba(255, 244, 224, .085), rgba(0, 0, 0, 0) 64%);
  background-attachment: fixed;
}

img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
button { font: inherit; color: inherit; }
::selection { background: var(--red); color: #fff; }

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

.mono {
  font-family: var(--mono); font-size: .66rem; font-weight: 500;
  letter-spacing: .18em; text-transform: uppercase;
}

.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

.skip {
  position: fixed; top: 10px; left: 10px; z-index: 400;
  padding: 10px 16px; background: var(--red); color: #fff;
  text-decoration: none; border-radius: 3px;
  transform: translateY(-180%); transition: transform .2s;
}
.skip:focus-visible { transform: none; }

.wrap { width: min(var(--maxw), 100% - var(--gut) * 2); margin-inline: auto; }

/* ─────────────────────────────  LOADER  ───────────────────────────── */

#loader {
  position: fixed; inset: 0; z-index: 500;
  background: var(--room); display: grid; place-items: center;
  transition: opacity .7s var(--ease), visibility .7s;
}
html:not(.loading) #loader { opacity: 0; visibility: hidden; }
.loader-in { display: grid; gap: 22px; justify-items: center; width: min(300px, 66vw); }
.loader-bar { width: 100%; height: 2px; background: var(--line); overflow: hidden; }
.loader-bar i { display: block; height: 100%; width: 0; background: var(--red); transition: width .25s linear; }

/* ─────────────────────────────  THE MARK  ─────────────────────────────
   The logo, rebuilt so its parts can move: the two words are alpha masks that
   take their colour from the page, and the red frame is real vector line, with
   the gaps where the ascenders of "t" and "l" cross it. */
.pp { position: relative; display: block; width: 100%; aspect-ratio: 3658 / 1414; }
.pp > i, .pp > svg { position: absolute; inset: 0; }
.pp-print, .pp-pal {
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
.pp-print {
  background: var(--red);
  -webkit-mask-image: url(../assets/img/mark-print.png); mask-image: url(../assets/img/mark-print.png);
}
.pp-pal {
  background: var(--fg);
  -webkit-mask-image: url(../assets/img/mark-pal.png); mask-image: url(../assets/img/mark-pal.png);
}
.pp-frame { width: 100%; height: 100%; }
.pp-frame path { fill: none; stroke: var(--red); stroke-width: 53; stroke-linejoin: round; }
.pp-head { display: none; }

/* One pass of the head across the sheet: everything behind it is printed,
   everything ahead of it is still blank stock. clip-path is animated directly
   rather than through a custom property, so it needs nothing registered and
   interpolates everywhere. */
html.js .pp-pass .pp-print,
html.js .pp-pass .pp-pal,
html.js .pp-pass .pp-frame { clip-path: inset(0 100% 0 0); animation: ppPass 1.5s var(--pass-ease) forwards; }
html.js .pp-pass .pp-head {
  display: block; top: -9%; bottom: -9%; left: 0; width: 2px; inset-inline-end: auto;
  background: var(--red); opacity: 0; box-shadow: 0 0 22px 3px rgba(231, 34, 53, .5);
  animation: ppHead 1.5s var(--pass-ease) forwards;
}
@keyframes ppPass { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }
@keyframes ppHead {
  0% { left: 0; opacity: 0; } 8% { opacity: 1; } 92% { opacity: 1; }
  100% { left: 100%; opacity: 0; }
}

/* the same pass, used once more on the story headline */
.pass { position: relative; }
html.js .pass > h2 { clip-path: inset(0 100% 0 0); }
html.js .pass.in > h2 { animation: ppPass 1.4s var(--pass-ease) forwards; }
.pass[data-rev] { opacity: 1; transform: none; }
.pass-head { display: none; }
html.js .pass.in > .pass-head {
  display: block; position: absolute; top: -6%; bottom: -6%; left: 0; width: 2px;
  background: var(--red); opacity: 0; box-shadow: 0 0 22px 3px rgba(231, 34, 53, .5);
  animation: ppHead 1.4s var(--pass-ease) forwards;
}

/* ─────────────────────────────  CHROME  ───────────────────────────── */

.chrome {
  position: fixed; top: 0; left: 0; right: 0; z-index: 200;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 20px var(--gut);
  transition: padding .35s var(--ease), background-color .35s, backdrop-filter .35s;
}
.chrome.is-stuck {
  padding-top: 12px; padding-bottom: 12px;
  background: rgba(20, 19, 17, .8); backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.mark {
  display: block; width: clamp(98px, 11vw, 118px); text-decoration: none;
}

.rail { display: flex; gap: 2px; }
.rail a {
  position: relative; padding: 8px 14px; border-radius: 100px;
  text-decoration: none; font-size: .88rem; color: var(--dim);
  transition: color .25s, background-color .25s;
}
.rail a:hover { color: var(--fg); background: rgba(255, 255, 255, .05); }
.rail a.is-here { color: var(--fg); }
.rail a.is-here::after {
  content: ''; position: absolute; left: 14px; right: 14px; bottom: 3px;
  height: 1px; background: var(--red);
}

.chrome-end { display: flex; align-items: center; gap: 12px; }
.tel {
  text-decoration: none; padding: 9px 16px; border-radius: 100px;
  border: 1px solid var(--line); color: var(--fg);
  transition: background-color .25s, border-color .25s, color .25s;
}
.tel:hover { background: var(--red); border-color: var(--red); color: #fff; }

.burger {
  display: none; width: 42px; height: 42px; padding: 0; position: relative;
  background: none; border: 1px solid var(--line); border-radius: 100px; cursor: pointer;
}
.burger span {
  position: absolute; left: 12px; right: 12px; height: 1.5px; background: currentColor;
  transition: transform .3s var(--ease);
}
.burger span:nth-child(1) { top: 17px; }
.burger span:nth-child(2) { top: 23px; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(3px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { transform: translateY(-3px) rotate(-45deg); }

.drawer {
  position: fixed; inset: 0; z-index: 190;
  background: var(--room-2);
  display: grid; grid-template-rows: 1fr auto; gap: 20px;
  padding: 104px var(--gut) 44px;
  opacity: 0; visibility: hidden;
  transition: opacity .35s var(--ease), visibility .35s;
}
.drawer.is-open { opacity: 1; visibility: visible; }
.drawer nav { display: grid; align-content: center; }
.drawer nav a {
  padding: 14px 0; border-bottom: 1px solid var(--line);
  font-size: clamp(1.7rem, 8vw, 2.6rem); font-weight: 600; letter-spacing: -.04em;
  text-decoration: none;
}
.drawer-foot { display: grid; gap: 8px; color: var(--dim); }
.drawer-foot a { text-decoration: none; }
.drawer-foot p { margin: 6px 0 0; text-transform: none; letter-spacing: .04em; line-height: 1.7; }

/* ─────────────────────────────  TYPE  ─────────────────────────────── */

.eyebrow {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 22px; color: var(--dim);
}
.eyebrow u { width: 8px; height: 8px; border-radius: 50%; background: var(--red); flex: none; }

h1, h2 { margin: 0; font-weight: 600; letter-spacing: -.045em; line-height: .98; }
h1 { font-size: clamp(2.3rem, 4.4vw, 4.2rem); }
h2 { font-size: clamp(1.9rem, 3.8vw, 3.5rem); }
.h-huge { font-size: clamp(2.4rem, 6vw, 5.4rem); }
h1 em, h2 em { font-style: normal; color: var(--red-lift); }

.lede { max-width: 46ch; margin: 22px 0 0; color: var(--dim); font-size: clamp(.98rem, 1.1vw, 1.1rem); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 14px 25px; border-radius: 100px; border: 1px solid transparent;
  font-size: .94rem; font-weight: 500; text-decoration: none; cursor: pointer;
  transition: background-color .28s, border-color .28s, color .28s, transform .2s var(--ease);
}
.btn-solid { background: var(--red); color: #fff; }
.btn-solid:hover { background: #ff3247; transform: translateY(-2px); }
.btn-ghost { border-color: var(--line); color: var(--fg); }
.btn-ghost:hover { border-color: var(--fg); background: rgba(255, 255, 255, .05); }
.btn-wide { width: 100%; }

/* ─────────────────────────────  THE BENCH  ────────────────────────── */

.bench { position: relative; height: 340vh; }
.bench-pin {
  position: sticky; top: 0; height: 100svh;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto;
  align-items: center;
  padding: 96px var(--gut) 30px;
  gap: 20px;
  overflow: hidden;
}
.bench-copy { grid-column: 1; max-width: 34rem; }
.bench-copy .acts { display: flex; flex-wrap: wrap; gap: 11px; margin-top: 32px; }
/* the mark, where the location line used to sit */
.bench-mark { margin: 0 0 22px; }
.bench-mark .pp { width: clamp(132px, 15vw, 186px); }

/* and the brand line, where the three figures used to sit */
.bench-line em { font-style: normal; color: var(--red); }
.bench-line {
  position: relative; margin: 34px 0 0;
  font-size: clamp(1.5rem, 3.2vw, 2.7rem); font-weight: 600;
  letter-spacing: -.045em; line-height: 1.05; color: var(--fg);
  width: max-content; max-width: 100%;
}

/* Both wait for the curtain: the pass is the first thing you see on the page,
   and running it behind the loader would waste it. */
html.js .pp-late .pp-print,
html.js .pp-late .pp-pal,
html.js .pp-late .pp-frame,
html.js .pp-late .pp-head { animation-delay: 2.1s; }

html.js .pass-line > span {
  display: inline-block; clip-path: inset(0 100% 0 0);
  animation: ppPass 1.4s var(--pass-ease) 2.7s forwards;
}
html.js .pass-line > .pass-head {
  display: block; position: absolute; top: -12%; bottom: -12%; left: 0; width: 2px;
  background: var(--red); opacity: 0; box-shadow: 0 0 22px 3px rgba(231, 34, 53, .5);
  animation: ppHead 1.4s var(--pass-ease) 2.7s forwards;
}
.pass-line > .pass-head { display: none; }

.deck-wrap { grid-column: 2; grid-row: 1; position: relative; height: 100%; }

.bench-foot {
  grid-column: 1 / -1; grid-row: 2;
  display: flex; align-items: center; justify-content: space-between;
  gap: 20px; flex-wrap: wrap;
  padding-top: 16px; border-top: 1px solid var(--line);
}
.now { margin: 0; color: var(--dim); }
.now b { color: var(--fg); font-weight: 500; }

.tick { display: flex; gap: 3px; align-items: flex-end; height: 20px; }
.tick i { width: 2px; height: 7px; background: #453f36; transition: height .3s var(--ease), background-color .3s; }
.tick i.on { height: 20px; background: var(--red); }
.tick i.near { height: 13px; background: #7d7566; }

.deck-cue {
  position: absolute; left: 50%; bottom: 4px; transform: translateX(-50%);
  margin: 0; color: var(--dim-2); white-space: nowrap;
  transition: opacity .5s; pointer-events: none;
}

/* ─── the cards ────────────────────────────────────────────────────── */
.deck {
  position: absolute; inset: 0;
  perspective: 1500px;
  cursor: grab; touch-action: pan-y;
}
.deck.is-drag { cursor: grabbing; }

.swatch {
  position: absolute; top: 50%; left: 50%;
  width: min(320px, 74%); aspect-ratio: 3 / 4; margin: 0;
  background: var(--card); color: var(--ink);
  border-radius: 4px; overflow: hidden;
  box-shadow: 0 32px 60px -26px rgba(0, 0, 0, .9), 0 2px 5px rgba(0, 0, 0, .45);
  will-change: transform, opacity;
  /* a punched hole, the way a real swatch deck is bound */
  -webkit-mask-image: radial-gradient(circle at 50% 4.4%, transparent 11px, #000 12px);
  mask-image: radial-gradient(circle at 50% 4.4%, transparent 11px, #000 12px);
}
.swatch img { width: 100%; height: 73%; object-fit: cover; background: var(--card-2); }
.swatch figcaption {
  height: 27%; padding: 12px 15px;
  display: grid; align-content: center; gap: 4px;
  border-top: 1px solid rgba(23, 22, 26, .13);
}
.swatch h3 { margin: 0; font-size: 1.02rem; font-weight: 600; letter-spacing: -.03em; }
.swatch .mono { color: #7b756a; font-size: .58rem; }
.swatch .dot {
  position: absolute; right: 12px; top: 12px;
  width: 9px; height: 9px; border-radius: 50%;
}

/* ─────────────────────────────  SECTIONS  ─────────────────────────── */

.sec { position: relative; padding: clamp(80px, 12vh, 150px) 0; }
.sec-head { max-width: 46rem; margin-bottom: clamp(40px, 6vh, 78px); }
.sec-head-wide { max-width: 58rem; }
.sec-head-row {
  max-width: none; display: grid; gap: 30px; align-items: end;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
}
.sec-head-row .lede { margin-top: 0; }

.sec-methods, .sec-approval { background: var(--room-3); }
.sec-methods { padding-bottom: 0; }
.sec-methods::before, .sec-approval::before {
  content: ''; position: absolute; inset: 0 0 auto; height: 1px; background: var(--line);
}

/* ─── methods, as full-bleed film strips ───────────────────────────────
   Each strip is one press, filmed on the floor. The clip is the ground; the
   copy sits on a gradient that is darkest exactly where the words are. */
.strips { list-style: none; margin: 0; padding: 0; }
.strip {
  position: relative; min-height: 64svh;
  display: grid; align-items: end; overflow: hidden;
  background: var(--room-2);
}
.strip + .strip { margin-top: 3px; }
.strip figure { position: absolute; inset: 0; margin: 0; }
.strip video, .strip img {
  width: 100%; height: 100%; object-fit: cover;
  filter: saturate(.86) contrast(1.04) brightness(.72);
  transform: scale(1.03);
  transition: transform 1.6s var(--ease), filter .8s var(--ease);
}
.strip:hover video { transform: scale(1); filter: saturate(.95) contrast(1.02) brightness(.8); }
.strip::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top,
    rgba(12, 11, 10, .95) 10%, rgba(12, 11, 10, .74) 42%, rgba(12, 11, 10, .22) 78%,
    rgba(12, 11, 10, .06) 100%);
}
.strip-text {
  position: relative; z-index: 2;
  padding-block: clamp(28px, 5vh, 60px); max-width: none;
}
.strip-n {
  display: flex; align-items: center; gap: 9px;
  color: var(--this-ink, var(--red)); margin-bottom: 12px;
}
.strip-n u { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.strip h3 {
  margin: 0 0 10px; font-size: clamp(1.5rem, 3vw, 2.5rem);
  font-weight: 600; letter-spacing: -.035em;
}
.strip-text p { margin: 0; color: #cbc5b8; max-width: 46ch; }
.strip-for { color: var(--this-ink, var(--red)) !important; margin-top: 14px !important; }

[data-press="Digital"] { --this-ink: var(--i-digital); }
[data-press="Offset"] { --this-ink: var(--i-offset); }
[data-press="Flex"] { --this-ink: var(--i-flex); }
[data-press="Screen"] { --this-ink: var(--i-screen); }
[data-press="Sublimation"] { --this-ink: var(--i-sublimation); }

/* ─── catalogue, as seven drawers ───────────────────────────────────────
   Shut, the whole catalogue is seven lines; open one and its samples come out.
   Built on <details name="catalogue">, so the accordion is the browser's own:
   exclusive opening, keyboard and screen-reader behaviour and a working
   section all come free, and none of it depends on our script. */
.sec-cat { interpolate-size: allow-keywords; }
.drawers { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.drawers > li { border-bottom: 1px solid var(--line); }

.pull {
  display: grid; grid-template-columns: 4.4rem minmax(0, auto) minmax(0, 1fr) auto;
  gap: 18px; align-items: center; cursor: pointer; list-style: none;
  padding: clamp(15px, 2.2vh, 24px) 2px;
  transition: padding-left .35s var(--ease);
}
.pull::-webkit-details-marker { display: none; }
.pull:hover, .cat-drawer:focus-within > .pull { padding-left: 14px; }
.pull-n { color: var(--dim-2); }
.pull-name {
  margin: 0; font-size: clamp(1.15rem, 2.4vw, 1.9rem); font-weight: 500;
  letter-spacing: -.038em; transition: color .25s;
}
.pull:hover .pull-name, .cat-drawer[open] .pull-name { color: #fff; }
.pull-list {
  color: var(--dim-2); justify-self: end; max-width: 46ch;
  overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
}
.cat-drawer[open] .pull-list { opacity: 0; transition: opacity .3s; }
.pull-x { width: 15px; height: 15px; position: relative; justify-self: end; }
.pull-x::before, .pull-x::after {
  content: ''; position: absolute; inset: 50% 0 auto; height: 1.5px; background: var(--dim);
  transition: transform .4s var(--ease), background-color .25s;
}
.pull-x::after { transform: rotate(90deg); }
.cat-drawer[open] .pull-x::before, .cat-drawer[open] .pull-x::after { background: var(--red); }
.cat-drawer[open] .pull-x::after { transform: rotate(0deg); }

/* Chrome and friends animate the drawer open; everywhere else it simply opens,
   which is the right way round for a progressive enhancement. */
.cat-drawer::details-content {
  block-size: 0; overflow: clip;
  transition: block-size .5s var(--ease), content-visibility .5s allow-discrete;
}
.cat-drawer[open]::details-content { block-size: auto; }

.shelf {
  list-style: none; margin: 0; padding: 0 0 clamp(18px, 3vh, 30px);
  display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(178px, 1fr));
}
.samp {
  position: relative; display: block; text-decoration: none;
  background: var(--card); color: var(--ink); border-radius: 4px; overflow: hidden;
  box-shadow: 0 16px 30px -22px rgba(0, 0, 0, .95);
  transition: transform .35s var(--ease), box-shadow .35s var(--ease);
  -webkit-mask-image: radial-gradient(circle at 50% 4%, transparent 8px, #000 9px);
  mask-image: radial-gradient(circle at 50% 4%, transparent 8px, #000 9px);
}
.samp:hover, .samp:focus-visible { transform: translateY(-5px); box-shadow: 0 28px 44px -22px rgba(0, 0, 0, 1); }
.samp figure { margin: 0; }
.samp img { width: 100%; aspect-ratio: 1; object-fit: cover; background: var(--card-2); }
.samp figcaption { padding: 12px 14px 15px; border-top: 1px solid rgba(23, 22, 26, .12); }
.samp h4 { margin: 0; font-size: .95rem; font-weight: 600; letter-spacing: -.03em; }
.samp figcaption p { margin: 2px 0 8px; font-size: .79rem; color: #6d675c; }
.samp figcaption .mono { color: #8d8577; font-size: .54rem; }
.samp .dot {
  position: absolute; right: 10px; top: 10px; z-index: 2;
  width: 9px; height: 9px; border-radius: 50%; background: var(--this-ink, var(--red));
}

/* ─── approval ─────────────────────────────────────────────────────── */
.approval-grid {
  display: grid; gap: clamp(26px, 4vw, 60px);
  grid-template-columns: minmax(0, .95fr) minmax(0, 1fr);
  align-items: start;
}
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 4px; overflow: hidden; }
.steps li { background: var(--room-3); padding: 24px clamp(18px, 2vw, 28px) 28px; }
.step-n { color: var(--red-lift); display: block; margin-bottom: 20px; }
.steps h3 { margin: 0 0 4px; font-size: 1.15rem; font-weight: 600; letter-spacing: -.03em; }
.steps p { margin: 0; color: var(--dim); font-size: .92rem; }

.proof {
  position: relative; background: var(--card); color: var(--ink);
  padding: clamp(26px, 3vw, 42px) clamp(22px, 3vw, 44px) clamp(44px, 5vw, 64px);
  border-radius: 4px; transform: rotate(-.8deg);
  box-shadow: 0 40px 80px -34px rgba(0, 0, 0, .95);
}
.proof::before {
  content: ''; position: absolute; inset: 11px;
  border: 1px dashed rgba(23, 22, 26, .2); pointer-events: none;
}
.proof-tag { display: block; color: #8d8577; margin-bottom: 18px; }
.proof-list { list-style: none; margin: 0; padding: 0; }
.proof-list li {
  position: relative; padding: 13px 0 13px 28px;
  border-top: 1px solid rgba(23, 22, 26, .13); font-size: 1rem;
}
.proof-list li:last-child { border-bottom: 1px solid rgba(23, 22, 26, .13); }
.proof-list li::before { content: '✓'; position: absolute; left: 0; top: 12px; color: #9d1c2c; }
.stamp {
  position: absolute; right: clamp(16px, 3vw, 44px); bottom: -12px;
  display: grid; justify-items: center; gap: 2px;
  padding: 11px 19px 9px; border: 3px solid var(--red); color: var(--red);
  background: rgba(246, 243, 236, .9); transform: rotate(-6deg);
}
.stamp b { font-size: 1.4rem; font-weight: 700; letter-spacing: -.02em; line-height: 1; }
.stamp i { font-style: normal; font-size: .48rem; letter-spacing: .18em; }

/* ─── the wall ──────────────────────────────────────────────────────────
   The claim is proved by the work rather than by adjectives: every tile
   drifting behind the type is something PrintPal has actually printed. The
   mosaic is built in JS from the catalogue above, so it can never fall out of
   step with what is really on offer. */
.sec-wall { overflow: hidden; background: var(--room-2); }
.sec-wall::before { z-index: 3; }   /* the section hairline, above the mosaic */

.mosaic {
  position: absolute; inset: -14% -2%; z-index: 0;
  display: flex; gap: 12px; pointer-events: none;
}
.mosaic .col { flex: 1; display: grid; gap: 12px; align-content: start; will-change: transform; }
.mosaic img {
  width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 3px;
  filter: saturate(.6) brightness(.62) contrast(1.05);
}
/* the type has to sit on something, and the mosaic is busy everywhere */
.sec-wall::after {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(ellipse 68% 62% at 50% 50%,
      rgba(12, 11, 10, .97) 22%, rgba(12, 11, 10, .82) 52%,
      rgba(12, 11, 10, .42) 78%, rgba(12, 11, 10, .2) 100%),
    linear-gradient(to bottom, rgba(12, 11, 10, .92), rgba(12, 11, 10, .34) 26%,
      rgba(12, 11, 10, .34) 74%, rgba(12, 11, 10, .92));
}

.wall-in { position: relative; z-index: 2; text-align: center; }
.wall-in .eyebrow { justify-content: center; }
.wall-in h2 { font-size: clamp(2.2rem, 6vw, 4.6rem); max-width: 16ch; margin-inline: auto; }
.wall-in h2 em { font-style: normal; color: var(--red); }
.wall-in .lede { max-width: 52ch; margin: 26px auto 0; }

.wall-copy {
  display: grid; gap: 18px clamp(24px, 4vw, 54px);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  max-width: 60rem; margin: clamp(30px, 4vh, 46px) auto 0; text-align: left;
}
.wall-copy p { margin: 0; color: var(--dim); }

/* ─── the client wall, inside the story ─────────────────────────────────
   The people PrintPal prints for, running where the four figures used to sit.
   Each cell shows a logo when `assets/clients/<slug>.<ext>` exists and its own
   name, well set, when it does not — so the wall is complete and honest from
   day one, and dropping a logo file in later needs no change to the markup. */
.cl-say {
  margin: clamp(38px, 6vh, 66px) auto 16px; color: var(--dim-2);
  max-width: none; text-align: center; line-height: 1.9;
}
.cl-say u {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--red); margin-right: 10px; vertical-align: middle;
}

/* The box carries the ground and the border so the strip reads as one solid
   thing over the mosaic; the fade at the ends belongs to the moving rail
   inside it, or it would eat the border along with the logos. */
.cl-box {
  background: rgba(12, 11, 10, .92); backdrop-filter: blur(8px);
  border: 1px solid var(--line); border-radius: 4px; overflow: hidden;
}
.cl-rail {
  position: relative; display: flex;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.cl-run {
  list-style: none; margin: 0; padding: 0; flex: none;
  display: flex; align-items: center; gap: clamp(34px, 5vw, 80px);
  padding: clamp(20px, 3vh, 34px) clamp(17px, 2.5vw, 40px);
  animation: clRun 62s linear infinite;
}
.cl-rail:hover .cl-run, .cl-rail:focus-within .cl-run { animation-play-state: paused; }
@keyframes clRun { to { transform: translateX(-100%); } }

.cl {
  flex: none; display: grid; place-items: center;
  min-width: clamp(112px, 13vw, 168px); height: clamp(44px, 5.6vw, 64px);
  filter: grayscale(1) opacity(.62);
  transition: filter .4s var(--ease), transform .4s var(--ease);
}
.cl:hover { filter: none; transform: translateY(-2px); }
/* The cell is a flex item inside an auto-sized row, so a percentage height
   here resolves against the content, not the cell — which let a square logo
   push the rail open. Absolute caps are the only reliable way to size these. */
.cl img {
  width: auto; height: auto; object-fit: contain;
  max-height: clamp(44px, 5.6vw, 64px);
  max-width: clamp(150px, 17vw, 230px);
}

/* the fallback, which is a design rather than a gap */
.cl-word {
  display: grid; justify-items: center; gap: 3px; text-align: center;
  font-size: clamp(.95rem, 1.5vw, 1.22rem); font-weight: 600;
  letter-spacing: -.035em; color: var(--fg); line-height: 1.1; white-space: nowrap;
}
.cl-sub {
  font-family: var(--mono); font-size: .48rem; letter-spacing: .14em;
  text-transform: uppercase; font-weight: 400; color: var(--dim-2); white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .cl-rail { overflow-x: auto; }
  .cl-run { animation: none; }
}

/* ─── contact ──────────────────────────────────────────────────────── */
.contact-grid {
  display: grid; gap: clamp(28px, 4vw, 64px);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
}
.details { list-style: none; margin: 0; padding: 0; align-content: start; display: grid; }
.details li { padding: 24px 0; border-top: 1px solid var(--line); }
.details li:last-child { border-bottom: 1px solid var(--line); }
.details li > span { display: block; color: var(--dim); margin-bottom: 11px; }
.details p { margin: 0 0 11px; font-size: clamp(1.08rem, 1.6vw, 1.4rem); letter-spacing: -.03em; }
.details p a { text-decoration: none; }
.details p a:hover { color: var(--red-lift); }
.ln { display: inline-flex; align-items: center; gap: 7px; font-size: .85rem; color: var(--red-lift); text-decoration: none; }
.ln::after { content: '→'; transition: transform .25s var(--ease); }
.ln:hover::after { transform: translateX(4px); }

.ticket { background: var(--room-3); border: 1px solid var(--line); border-radius: 4px; padding: clamp(22px, 3vw, 36px); }
.ticket-head {
  display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: baseline;
  margin: 0 0 24px; padding-bottom: 16px; border-bottom: 1px solid var(--line);
}
.ticket-head b { color: var(--fg); }
.ticket-head span { color: var(--dim); text-transform: none; letter-spacing: 0; font-size: .74rem; }
.ticket fieldset { border: 0; margin: 0 0 20px; padding: 0; }
.ticket legend {
  padding: 0; margin-bottom: 11px; color: var(--dim);
  font-family: var(--mono); font-size: .66rem; letter-spacing: .18em; text-transform: uppercase;
}
.opts { display: flex; flex-wrap: wrap; gap: 7px; }
.opts label { cursor: pointer; }
.opts input { position: absolute; opacity: 0; width: 0; height: 0; }
.opts span {
  display: inline-block; padding: 8px 14px; border-radius: 100px;
  border: 1px solid var(--line); font-size: .85rem;
  transition: background-color .25s, border-color .25s, color .25s;
}
.opts label:hover span { border-color: var(--dim); }
.opts input:checked + span { background: var(--red); border-color: var(--red); color: #fff; }
.opts input:focus-visible + span { outline: 2px solid var(--red-lift); outline-offset: 2px; }

.field { margin-bottom: 15px; }
.field label { display: block; color: var(--dim); margin-bottom: 7px; }
.field input, .field textarea {
  width: 100%; font: inherit; color: inherit; resize: vertical;
  background: rgba(255, 255, 255, .04); border: 1px solid var(--line);
  border-radius: 3px; padding: 12px 14px;
  transition: border-color .25s, background-color .25s;
}
.field input:focus, .field textarea:focus { border-color: var(--red); outline: none; }
.field.is-bad input, .field.is-bad textarea { border-color: var(--red); }
.ticket-note { margin: 13px 0 0; color: var(--dim); text-transform: none; letter-spacing: 0; font-size: .78rem; }
.ticket-note.is-ok { color: #55c98a; }
.ticket-note.is-bad { color: var(--red-lift); }
.ticket-note a { color: inherit; text-underline-offset: .18em; }
.ticket-note a:hover { color: #fff; }

/* ─────────────────────────────  FOOTER  ───────────────────────────── */

.foot { background: var(--room-2); border-top: 1px solid var(--line); padding-top: 34px; overflow: hidden; }
.marquee { overflow: hidden; padding-bottom: 30px; }
.marquee-run { display: flex; width: max-content; animation: run 48s linear infinite; }
.marquee-run span { font-size: clamp(1.3rem, 3.2vw, 2.6rem); font-weight: 600; letter-spacing: -.04em; white-space: nowrap; color: #211f1b; }
@keyframes run { to { transform: translateX(-50%); } }
.foot-row {
  display: flex; flex-wrap: wrap; gap: 12px 28px; justify-content: space-between;
  padding-bottom: 34px; color: var(--dim-2);
}
.foot-row p { margin: 0; }
.up { color: var(--fg); text-decoration: none; }
.up:hover { color: var(--red-lift); }

/* ─────────────────────────────  REVEALS  ──────────────────────────── */

html.js [data-rev] {
  opacity: 0; transform: translateY(18px);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
  transition-delay: calc(var(--d, 0) * 80ms);
}
html.js [data-rev].in { opacity: 1; transform: none; }

/* ─────────────────────────────  RESPONSIVE  ───────────────────────── */

@media (max-width: 1080px) {
  .rail { display: none; }
  .burger { display: block; }
  .sec-head-row, .approval-grid, .contact-grid { grid-template-columns: 1fr; }
}

@media (max-width: 820px) {
  .bench { height: 300vh; }
  /* The deck is absolutely positioned inside its wrapper, so anything that
     lets the wrapper outgrow its row drops cards on top of the copy. The row
     keeps a floor, the wrapper takes exactly the row's height, and the card is
     sized from that height rather than from the width — so it cannot spill,
     however little room is left. */
  .bench-pin {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(132px, 1fr) auto auto;
    align-items: stretch; padding-top: 76px; gap: 12px;
  }
  .deck-wrap { grid-column: 1; grid-row: 1; min-height: 0; height: 100%; }
  .bench-copy { grid-column: 1; grid-row: 2; align-self: start; }
  .bench-copy .acts { margin-top: 18px; }
  .bench-line { font-size: clamp(1.2rem, 5.6vw, 1.8rem); margin-top: 18px; }
  .bench-mark { margin-bottom: 14px; }
  .bench-mark .pp { width: 108px; }
  .bench-foot { grid-row: 3; align-self: end; }
  .swatch { height: min(206px, 100%); width: auto; }
  .deck-cue { bottom: -2px; }

  .strip { min-height: 56svh; }
  .pull { grid-template-columns: 3.6rem minmax(0, 1fr) auto; }
  .pull-list { display: none; }
  .shelf { grid-template-columns: repeat(auto-fill, minmax(146px, 1fr)); gap: 8px; }
  .samp figcaption { padding: 10px 11px 12px; }
  .samp h4 { font-size: .88rem; }
  .samp figcaption p { font-size: .74rem; }
  .wall-copy { grid-template-columns: 1fr; }
  .mosaic .col:nth-child(n+4) { display: none; }
  .proof { transform: none; }
  .stamp { right: 12px; transform: rotate(-5deg) scale(.88); }
  .tel { display: none; }
}

/* ─────────────────────────────  FALLBACKS  ────────────────────────── */

/* Without the script the deck is never built, so the bench collapses to an
   ordinary hero and the page reads as a plain document. */
html:not(.js) .bench { height: auto; }
html:not(.js) .bench-pin { position: static; height: auto; grid-template-columns: 1fr; padding-block: 140px 60px; }
html:not(.js) .deck-wrap, html:not(.js) .bench-foot { display: none; }

/* the mosaic is built by the script, so with no JS there is nothing behind
   the story and its lede must not claim there is */
html:not(.js) .wall-in .lede { display: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  html.js [data-rev] { opacity: 1; transform: none; }
}
