/* ============================================================
   SpaLab — Cartotecnica
   Palette, type, and spacing tokens
   ============================================================ */

:root {
  --violet-50:  #F5F3FF;
  --violet-100: #EDE9FE;
  --violet-200: #DDD6FE;
  --violet-300: #C4B5FD;
  --violet-400: #A78BFA;
  --violet-500: #8B5CF6;
  --violet-600: #7C3AED;
  --violet-700: #6D28D9;
  --violet-800: #5B21B6;
  --violet-900: #4C1D95;
  --violet-950: #2E1065;

  --ink-950: #0B0713;
  --ink-900: #14101F;
  --ink-800: #1E1930;
  --ink-700: #2C2542;
  --ink-500: #5A5270;
  --ink-400: #857D9B;
  --ink-300: #B5AEC6;
  --ink-200: #DAD6E4;
  --ink-100: #EDEBF2;
  --ink-50:  #F7F6FA;

  --font-display: "Big Shoulders Display", sans-serif;
  --font-body: "Jost", sans-serif;

  --measure: 68ch;
  --ease-press: cubic-bezier(0.16, 1, 0.3, 1);

  --lx: 30%;
  --ly: 20%;
}

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

html {
  scroll-behavior: smooth;
  /* Matches the fixed .masthead's tallest state (~112px) plus a little
     breathing room, so an anchor jump (footer nav, skip-link) doesn't
     land its target's top edge under the header. */
  scroll-padding-top: clamp(6rem, 12vw, 8rem);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 400;
  color: var(--ink-800);
  background: var(--ink-50);
  -webkit-font-smoothing: antialiased;
}

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

a { color: inherit; text-decoration: none; }

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

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--violet-700);
  color: #fff;
  padding: 0.75em 1.25em;
  z-index: 100;
  border-radius: 0 0 6px 0;
}
.skip-link:focus {
  left: 0;
}

/* A single violet-500 ring measured ~1.9:1 against the violet-700 hero
   sheet — below the 3:1 floor for non-text/UI focus indicators, on
   the primary conversion element. A white ring + dark halo pairs so
   one half of the pair always contrasts, on any of the four sheets. */
:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
  box-shadow: 0 0 0 5px rgba(11, 7, 19, 0.65);
}

/* ============================================================
   Masthead
   ============================================================ */

.masthead {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: clamp(1rem, 2.5vw, 1.5rem) clamp(1.25rem, 4vw, 3rem);
  background: linear-gradient(rgba(11, 7, 19, 0.78), rgba(11, 7, 19, 0.62));
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.masthead__mark {
  display: flex;
  align-items: center;
}
.masthead__mark img {
  width: clamp(44px, 6vw, 64px);
  height: clamp(44px, 6vw, 64px);
}

.masthead__stamp {
  display: flex;
  align-items: center;
  gap: 0.5em;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.95rem;
  color: #fff;
  padding: 0.55em 1.1em;
  border: 1.5px solid #fff;
  border-radius: 999px;
  transition: transform 0.35s var(--ease-press), background 0.35s var(--ease-press), color 0.35s var(--ease-press);
}
.masthead__stamp svg { width: 1.05em; height: 1.05em; fill: currentColor; }
.masthead__stamp:hover {
  transform: scale(0.96);
  background: #fff;
  color: var(--violet-700);
}
/* DESIGN.md already documents this pill as getting "the same press
   treatment as the primary stamp button, scaled down" — it didn't
   until now: hover had no distinct :active state, so tapping it felt
   identical to hovering it. This gives it the same rest -> hover ->
   deeper-active progression as .press-btn, just smaller in degree. */
.masthead__stamp:active {
  transform: scale(0.92);
  transition-duration: 0.15s;
}

/* ============================================================
   Sheets — full-bleed color fields
   ============================================================ */

.sheet {
  position: relative;
  padding-inline: clamp(1.25rem, 6vw, 6rem);
  /* clip, not hidden: overflow:hidden is classified as a scroll
     container per spec (even though nothing here ever scrolls it),
     which silently hijacks any descendant's animation-timeline:view()
     — the browser resolves the nearest scroll-container ancestor as
     the timeline's scroller, so it was measuring visibility against
     this section's own box instead of the real page viewport, and
     the scroll-driven "plate register" effect below always read as
     already-complete. overflow:clip clips identically but was never
     a scroll container, so view() timelines correctly resolve to the
     document. Confirmed via isolated test page + real-page probe. */
  overflow: clip;
}

.sheet--violet {
  background: var(--violet-700);
  color: var(--violet-100);
}

.sheet--violet-deep {
  background: var(--violet-950);
  color: var(--violet-200);
  padding-block: clamp(4rem, 10vw, 7rem);
}

.sheet--paper {
  background: var(--ink-50);
  color: var(--ink-700);
  padding-block: clamp(5rem, 12vw, 9rem);
}

.sheet--ink {
  background: var(--ink-950);
  color: var(--ink-100);
  padding-block: clamp(5rem, 12vw, 8rem);
}

/* Registration marks — a real press-proof artifact, not decoration */
.reg-mark {
  position: absolute;
  width: 22px; height: 22px;
  opacity: 0.35;
  pointer-events: none;
}
.reg-mark::before, .reg-mark::after {
  content: "";
  position: absolute;
  background: currentColor;
}
.reg-mark::before { top: 50%; left: 0; right: 0; height: 1px; transform: translateY(-50%); }
.reg-mark::after { left: 50%; top: 0; bottom: 0; width: 1px; transform: translateX(-50%); }
/* Top marks sit below the fixed masthead (76-112px tall across
   breakpoints) — a press-proof mark hidden under the header is worse
   than no mark at all. */
.reg-mark--tl { top: clamp(5.25rem, 11vw, 7.5rem); left: 1.5rem; }
.reg-mark--tr { top: clamp(5.25rem, 11vw, 7.5rem); right: 1.5rem; }
.reg-mark--bl { bottom: 1.5rem; left: 1.5rem; }
.reg-mark--br { bottom: 1.5rem; right: 1.5rem; }

/* ============================================================
   Hero
   ============================================================ */

.hero {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(4rem, 12vw, 6rem);
}

.hero__inner {
  max-width: 56rem;
}

.hero__sub {
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  line-height: 1.6;
  max-width: 42rem;
  color: var(--violet-100);
  margin: 1.75rem 0 2.5rem;
}

/* Moved inside .hero__inner and left-aligned with the rest of the
   composed block (heading, sub, CTA) instead of centered on its own
   in the middle of the sheet — centered text floating apart from an
   otherwise left-anchored composition read as arbitrary, not
   authored. It's now the last line of the same group, with a small
   bobbing arrow standing in for the bare tracked caption. */
.hero__scroll {
  display: flex;
  align-items: center;
  gap: 0.5em;
  margin: clamp(2rem, 5vw, 3rem) 0 0;
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--violet-100);
  text-decoration: none;
  width: fit-content;
  transition: color 0.25s var(--ease-press);
}
.hero__scroll:hover,
.hero__scroll:focus-visible {
  color: #fff;
}
.hero__scroll svg {
  width: 0.9em;
  height: 0.9em;
  animation: scroll-bob 1.8s var(--ease-press) infinite;
}
.hero__scroll:hover svg,
.hero__scroll:focus-visible svg {
  animation-play-state: paused;
  transform: translateY(3px);
}
@keyframes scroll-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(3px); }
}

/* ============================================================
   Deboss headline — pressed into the sheet, lit by cursor light
   ============================================================ */

.deboss {
  position: relative;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(3rem, 9vw, 6rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: #fff;
  text-transform: none;
  text-shadow:
    0 1px 0 rgba(255, 255, 255, 0.12),
    0 -1px 1px rgba(0, 0, 0, 0.45),
    0 2px 3px rgba(0, 0, 0, 0.25);
}

.deboss__line { display: block; }

/* Cursor-light shine: a decorative duplicate layered on top, additive only.
   Kept separate from the base fill because Chromium visibly muddies a
   background-clip:text fill when text-shadow is present on the same
   element, even at full opacity — confirmed by a throwaway swatch test.
   The base fill was darkened (violet-200 -> violet-300, ink-300 -> ink-500)
   specifically to give this screen-blend highlight somewhere to go: screening
   white over an already-near-white base is imperceptible, confirmed by a
   two-position screenshot diff. Both bases still clear the 3:1 large-text
   floor against their sheet. */
.deboss__shine {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(
    circle 560px at var(--lx) var(--ly),
    rgba(255, 255, 255, 1),
    rgba(255, 255, 255, 0) 62%
  );
  background-clip: text;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  mix-blend-mode: screen;
}

.deboss--light {
  color: #fff;
  text-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06),
    0 -1px 1px rgba(0, 0, 0, 0.6),
    0 2px 4px rgba(0, 0, 0, 0.35);
}
.deboss--light .deboss__shine {
  background-image: radial-gradient(
    circle 560px at var(--lx) var(--ly),
    rgba(255, 255, 255, 0.9),
    rgba(255, 255, 255, 0) 62%
  );
}

/* ============================================================
   Stamped button — a pressed seal, not a rounded rectangle
   ============================================================ */

.press-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 1.05rem;
  color: var(--violet-700);
  background: #fff;
  padding: 0.9em 1.75em;
  border-radius: 999px;
  border: 1.5px solid rgba(255, 255, 255, 0.4);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.5) inset,
    0 10px 24px rgba(11, 7, 19, 0.28),
    0 2px 6px rgba(11, 7, 19, 0.18);
  transition: transform 0.28s var(--ease-press), box-shadow 0.28s var(--ease-press);
}
.press-btn svg { width: 1.15em; height: 1.15em; fill: currentColor; }

.press-btn:hover {
  transform: translateY(-2px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.5) inset,
    0 16px 32px rgba(11, 7, 19, 0.32),
    0 4px 10px rgba(11, 7, 19, 0.2);
}
.press-btn:active {
  transform: translateY(1px) scale(0.98);
  box-shadow:
    0 1px 6px rgba(11, 7, 19, 0.35) inset,
    0 4px 10px rgba(11, 7, 19, 0.2);
}

/* Shadow uses the same dark-ink formula as the primary .press-btn
   (see Shadow Vocabulary in DESIGN.md) instead of a colored violet
   glow — a tinted glow on a saturated background reads as a generic
   "neon button" tell, not a pressed seal. */
.press-btn--light {
  color: var(--ink-950);
  background: var(--violet-500);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.25) inset,
    0 10px 24px rgba(11, 7, 19, 0.35),
    0 2px 6px rgba(11, 7, 19, 0.25);
}
.press-btn--light:hover {
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.25) inset,
    0 16px 32px rgba(11, 7, 19, 0.4),
    0 4px 10px rgba(11, 7, 19, 0.28);
}

/* ============================================================
   Proof section
   ============================================================ */

.proof__inner {
  max-width: 46rem;
  margin-inline: auto;
}

.proof__lede {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.75rem, 4vw, 2.75rem);
  line-height: 1.3;
  color: var(--ink-900);
  margin: 0 0 1.75rem;
}
.proof__lede em {
  font-style: normal;
  color: var(--violet-700);
}

.proof__body {
  font-size: 1.05rem;
  line-height: 1.75;
  max-width: var(--measure);
  color: var(--ink-500);
  margin: 0 0 3rem;
}

/* The section's own signature device — DESIGN.md already calls this
   "a literal printed color-swatch strip," but at 2rem chips and no
   captions it read as a footnote next to the copy, not a specimen.
   Turned up to full strength here: larger chips, real hex captions
   (an actual swatch card would print its codes), stacked as its own
   panel below the copy instead of squeezed inline beside it. Same
   4px chip radius, same five colors, same border-top divider — no
   new primitive, just the existing device at the scale it earns. */
.swatchbar {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.5rem;
  padding-top: clamp(2rem, 4vw, 2.75rem);
  border-top: 1px solid var(--ink-200);
}
.swatchbar__chips {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1rem, 2.5vw, 1.75rem);
}
.swatchbar__swatch {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.65rem;
}
.swatchbar__chip {
  width: clamp(3rem, 6vw, 4.5rem);
  height: clamp(3rem, 6vw, 4.5rem);
  border-radius: 4px;
  background: var(--c);
  box-shadow: 0 2px 4px rgba(11, 7, 19, 0.18);
}
.swatchbar__hex {
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: var(--ink-500);
}
.swatchbar__label {
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  color: var(--ink-500);
}

/* ============================================================
   Specimen — service sheet as a type-proof
   ============================================================ */

.specimen__inner {
  max-width: 64rem;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  gap: clamp(3rem, 7vw, 5rem);
}

.specimen__row {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: end;
  padding-bottom: clamp(2rem, 5vw, 3rem);
  border-bottom: 1px solid rgba(196, 181, 253, 0.18);
}
.specimen__row:last-child { border-bottom: none; padding-bottom: 0; }

.specimen__ramp {
  display: flex;
  flex-direction: column;
  gap: 0.15em;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 0.98;
  color: var(--violet-200);
}
.specimen__ramp span:first-child { color: #fff; font-weight: 700; }
/* 400, not 500: Big Shoulders Display is only requested at 400/600/700,
   so 500 was being faux-bolded/snapped by the browser. 400 is both an
   available weight and a full step lighter than the 600 base — a
   cleaner three-tier ladder (700 -> 600 -> 400) than a synthesized 500. */
.specimen__ramp span:last-child { color: var(--violet-400); font-weight: 400; }

.specimen__desc {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--violet-300);
  margin: 0;
  max-width: 32ch;
}

/* ============================================================
   Contact
   ============================================================ */

.contact__inner {
  max-width: 44rem;
}

.contact h2.deboss {
  font-size: clamp(2.5rem, 7vw, 5.25rem);
  margin-bottom: 2.5rem;
}

.contact__note {
  font-size: 0.95rem;
  color: var(--ink-400);
  margin: 1.5rem 0 0;
}

.contact__footer {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem 2.5rem;
  margin-top: clamp(4rem, 10vw, 6rem);
  padding-top: clamp(1.75rem, 3vw, 2.25rem);
  border-top: 1px solid var(--ink-800);
  font-size: 1rem;
  color: var(--ink-400);
}

.contact__footer-brand {
  display: flex;
  align-items: center;
  gap: 0.9em;
}
.contact__footer-brand img {
  width: clamp(34px, 4vw, 44px);
  height: clamp(34px, 4vw, 44px);
  flex-shrink: 0;
}
.contact__footer-brand p {
  display: flex;
  flex-direction: column;
  gap: 0.15em;
  margin: 0;
}
.contact__footer-name {
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1;
  color: #fff;
}
.contact__footer-tag {
  font-size: 0.8rem;
  /* ink-500 measured 2.73:1 on ink-950 here — fails WCAG AA. ink-400
     clears 5.13:1 and is the same token already used for the footer
     nav links right next to it. */
  color: var(--ink-400);
}

.contact__footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75em 1.75em;
}
.contact__footer-links a {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  color: var(--ink-400);
  transition: color 0.25s var(--ease-press);
}
.contact__footer-links a:hover,
.contact__footer-links a:focus-visible {
  color: var(--violet-300);
}

.contact__footer-meta {
  display: flex;
  align-items: center;
  gap: 1.5em;
  font-size: 0.85rem;
  /* ink-500 measured 2.73:1 on ink-950 (the "© 2026 SpaLab" text) —
     fails WCAG AA. ink-400 clears 5.13:1. */
  color: var(--ink-400);
}
.contact__footer-meta a {
  color: var(--ink-400);
  transition: color 0.25s var(--ease-press);
}
.contact__footer-meta a:hover,
.contact__footer-meta a:focus-visible {
  color: var(--violet-300);
}

/* ============================================================
   Legal pages — privacy, cookie: Read mode, comprehension first
   ============================================================ */

.legal__inner {
  max-width: 40rem;
  margin-inline: auto;
  padding-top: clamp(3rem, 6vw, 4rem);
}

.legal__back {
  display: inline-block;
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--violet-700);
  margin-bottom: 2.5rem;
}
.legal__back:hover,
.legal__back:focus-visible {
  text-decoration: underline;
}

.legal__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.25rem, 5vw, 3.25rem);
  line-height: 1;
  color: var(--ink-900);
  margin: 0 0 0.75rem;
}

.legal__updated {
  font-size: 0.9rem;
  color: var(--ink-500);
  margin: 0 0 3rem;
}

.legal h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  color: var(--ink-900);
  margin: 2.75rem 0 1rem;
}

.legal p,
.legal li {
  font-size: 1rem;
  line-height: 1.75;
  max-width: var(--measure);
  color: var(--ink-500);
}

.legal p { margin: 0 0 1.25rem; }

.legal ul {
  margin: 0 0 1.25rem;
  padding-left: 1.25rem;
}
.legal li { margin-bottom: 0.75rem; }
.legal li:last-child { margin-bottom: 0; }

.legal a {
  color: var(--violet-700);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.legal__table-wrap {
  max-width: var(--measure);
  overflow-x: auto;
  margin: 0 0 1.75rem;
}
.legal__table {
  width: 100%;
  min-width: 28rem;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.legal__table th,
.legal__table td {
  text-align: left;
  padding: 0.65rem 1rem 0.65rem 0;
  border-bottom: 1px solid var(--ink-200);
}
.legal__table th {
  font-weight: 500;
  color: var(--ink-900);
}
.legal__table td {
  color: var(--ink-500);
}
.legal__table code {
  font-family: monospace;
  font-size: 0.85em;
  color: var(--ink-900);
}

.legal-footer .contact__footer {
  margin-top: 0;
  border-top: none;
}

/* ============================================================
   Reveal-on-scroll — one authored moment
   ============================================================ */

/* Scoped to html:not(.no-js): the inline unblocking script in <head>
   removes .no-js before first paint whenever JS runs. If a script is
   blocked, fails, or hasn't executed yet, content stays visible by
   default instead of sitting at opacity:0 forever — the animation is
   an enhancement, never a requirement to read the page. */
html:not(.no-js) [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.9s var(--ease-press), transform 0.9s var(--ease-press);
  transition-delay: var(--delay, 0s);
}
/* Must out-specify the hidden rule above (which now carries an extra
   html:not() selector) or the reveal never fires and every section
   stays permanently invisible. */
html:not(.no-js) [data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* The hero headline: the one authored focal entrance, not another
   instance of the generic reveal above. The page's own thesis is that
   the message is impressed, not printed on — so its first line earns
   a distinct motion: it lands slightly oversized and settles past 1
   before resting, reading as an impact rather than a fade-and-rise.
   Every other section keeps the quieter shared reveal; repeating this
   for every heading would turn one authored moment into a tic. */
html:not(.no-js) .hero h1.deboss[data-reveal] {
  transform: none;
}
html:not(.no-js) .hero h1.deboss[data-reveal].is-visible {
  animation: stamp-press 0.7s var(--ease-press) both;
  animation-delay: var(--delay, 0s);
}
@keyframes stamp-press {
  0% { opacity: 0; transform: scale(1.06); }
  55% { opacity: 1; transform: scale(0.985); }
  100% { opacity: 1; transform: scale(1); }
}
/* .deboss__shine is a second, independently-rasterized copy of the
   same letterforms (needed for the cursor-light effect). Scaling the
   parent while both copies are visible re-rasterizes them each frame
   at slightly different sub-pixel rounding, which reads as doubled,
   overlapping letters mid-animation — confirmed by screenshot. Keep
   only the single base layer visible while the transform is moving,
   and cross-fade the shine in once the element is at rest and static. */
html:not(.no-js) .hero h1.deboss[data-reveal] .deboss__shine {
  opacity: 0;
  transition: opacity 0.3s ease;
}
html:not(.no-js) .hero h1.deboss[data-reveal].is-visible .deboss__shine {
  opacity: 1;
  transition-delay: calc(var(--delay, 0s) + 0.7s);
}

/* ============================================================
   Plate registration — scroll-driven sheet transitions
   ============================================================
   Overdrive direction: each sheet below the hero arrives like a
   printing plate dropping into register, not just fading in. The
   motion is tied to scroll position itself (animation-timeline:
   view()) rather than to a timer, so it feels mechanically connected
   to the reader's own gesture — the way a press plate locks into
   place as the sheet is pulled through.

   Progressive enhancement, not a redesign: browsers without
   view-timeline support (Firefox at the time of writing) get exactly
   the existing IntersectionObserver fade-and-rise, untouched, inside
   this same @supports gate. Nothing here removes that fallback. */

@supports (animation-timeline: view()) {
  @keyframes plate-register {
    from { opacity: 0; transform: translateY(30px) rotate(-1.4deg) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) rotate(0deg) scale(1); }
  }
  @keyframes mark-register {
    from { opacity: 0; transform: rotate(10deg) scale(1.5); }
    to   { opacity: 0.35; transform: rotate(0deg) scale(1); }
  }

  /* One plate, one registration event — the whole sheet settles as a
     single unit rather than staggering its own children. Individual
     children below are neutralized out of the older per-element
     reveal so the two systems don't fight over the same properties. */
  .proof__inner,
  .specimen__row,
  .contact__inner {
    animation-name: plate-register;
    animation-timing-function: linear;
    animation-fill-mode: both;
    animation-timeline: view();
    animation-range: entry 0% entry 55%;
  }

  /* !important is deliberate: html:not(.no-js) [data-reveal] (the
     older JS-driven system) outranks a same-specificity override by
     one element selector (html), so a plain override loses the fight
     silently. This @supports gate gives one system exclusive control
     per browser; !important makes that handoff actually happen.

     .specimen__row is deliberately NOT in this list — it carries
     [data-reveal] itself but is also the element the new plate-register
     animation runs on directly (not a child of an animated wrapper like
     the others below). Forcing its transform/opacity static here would
     cancel the very animation this block exists to enable: a keyframe
     animation already overrides the older transition-based value for
     the same property, so it needs no static override at all. */
  .proof__lede[data-reveal],
  .proof__body[data-reveal],
  .swatchbar[data-reveal],
  .contact h2.deboss[data-reveal],
  .contact .press-btn[data-reveal],
  .contact__note[data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    animation: none !important;
  }

  /* The registration marks snap into alignment slightly ahead of the
     content around them — the plate locks in position, then the ink
     sets. Hero's marks are already on-screen at load with no scroll
     to drive, so they simply render at their resting, aligned state:
     unchanged from today. */
  .reg-mark {
    animation-name: mark-register;
    animation-timing-function: linear;
    animation-fill-mode: both;
    animation-timeline: view();
    animation-range: entry 0% entry 35%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .proof__inner,
  .specimen__row,
  .contact__inner {
    animation: none !important;
    opacity: 1;
    transform: none;
  }
  /* Not resetting opacity/transform here: .reg-mark's own base rule
     (opacity: 0.35, no transform) already applies once the animation
     above is removed — that IS its correct resting look. */
  .reg-mark {
    animation: none !important;
  }
}

/* ============================================================
   Responsive
   ============================================================ */

@media (max-width: 480px) {
  /* The base clamp's 3rem floor doesn't shrink further below ~600px,
     so "Un design che si vede" wraps mid-word into an orphaned second
     line on narrow phones. Lower the floor so each authored line
     holds as one visual line down to 360px. */
  .hero .deboss {
    font-size: clamp(2rem, 10.5vw, 3rem);
  }
}

@media (max-width: 720px) {
  .specimen__row {
    grid-template-columns: 1fr;
  }
  .specimen__desc { max-width: none; }

  /* Keep the "Scrivimi" label instead of collapsing to an icon-only
     circle: on mobile — the primary device — this is the only CTA
     reachable at every scroll position, so it stays labelled and
     clears the 44px tap-target floor instead of shrinking to 39px. */
  .masthead__stamp {
    padding: 0.65em 0.9em;
    font-size: 0.85rem;
    gap: 0.4em;
    min-height: 44px;
  }

  .contact__footer {
    flex-direction: column;
    align-items: flex-start;
    gap: 1.5rem;
  }
  .contact__footer-links,
  .contact__footer-meta {
    gap: 0.6em 1.5em;
  }
  .contact__footer-links a,
  .contact__footer-meta a {
    display: inline-block;
    padding-block: 0.6em;
  }
}

/* ============================================================
   WooCommerce — single product, the sheet as a product proof
   ============================================================
   Same paper sheet + pill-stamp vocabulary as the rest of the site:
   flat content, no card shadows, the "Aggiungi al carrello" button
   reuses .press-btn, and the price reads like an ink swatch caption
   rather than a boxed price tag. No markup changes — every selector
   below targets WooCommerce's own default template classes. */

.product-page__inner {
  max-width: 78rem;
  margin-inline: auto;
}

.product-page .legal__back {
  margin-bottom: clamp(2rem, 5vw, 3rem);
}

.product-page-footer .contact__footer {
  max-width: 78rem;
  margin-inline: auto;
}

.woocommerce #primary.content-area {
  width: 100%;
}

.woocommerce-breadcrumb {
  font-family: var(--font-body);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  color: var(--ink-400);
  margin: 0 0 clamp(2rem, 5vw, 3rem);
}
.woocommerce-breadcrumb a {
  color: var(--ink-500);
}
.woocommerce-breadcrumb a:hover,
.woocommerce-breadcrumb a:focus-visible {
  color: var(--violet-700);
  text-decoration: underline;
}

/* ---- Product layout: gallery | summary, same 1.4fr/1fr row the
   specimen section already uses ---- */
.woocommerce div.product {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
  position: relative;
}

/* ---- Gallery ---- */
.woocommerce div.product .woocommerce-product-gallery {
  position: relative;
}
.woocommerce div.product .woocommerce-product-gallery__wrapper {
  margin: 0;
  padding: 0;
  list-style: none;
}
.woocommerce div.product .woocommerce-product-gallery__image {
  background: #fff;
  border: 1px solid var(--ink-200);
}
.woocommerce div.product .woocommerce-product-gallery__image img {
  width: 100%;
  height: auto;
  display: block;
}
.woocommerce div.product .flex-control-thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0.75rem 0 0;
  padding: 0;
  list-style: none;
}
.woocommerce div.product .flex-control-thumbs li {
  width: clamp(3.5rem, 8vw, 4.5rem);
}
.woocommerce div.product .flex-control-thumbs img {
  width: 100%;
  height: auto;
  display: block;
  background: #fff;
  border: 1px solid var(--ink-200);
  cursor: pointer;
  opacity: 0.65;
  transition: opacity 0.2s var(--ease-press), border-color 0.2s var(--ease-press);
}
.woocommerce div.product .flex-control-thumbs img:hover,
.woocommerce div.product .flex-control-thumbs img.flex-active {
  opacity: 1;
  border-color: var(--violet-500);
}

.woocommerce span.onsale {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 2;
  min-width: 0;
  height: auto;
  line-height: 1;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  color: #fff;
  background: var(--violet-700);
  padding: 0.5em 0.9em;
  border-radius: 999px;
  margin: 0;
}

/* ---- Summary ---- */
.woocommerce div.product .summary.entry-summary {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.woocommerce div.product .product_title.entry-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.75rem, 3.5vw, 2.5rem);
  line-height: 1.1;
  color: var(--ink-900);
  margin: 0;
}

.woocommerce div.product .woocommerce-product-rating {
  display: flex;
  align-items: center;
  gap: 0.6em;
  margin: 0;
}
.woocommerce div.product .star-rating {
  color: var(--violet-500);
  font-size: 0.95rem;
}
.woocommerce div.product .woocommerce-review-link {
  font-size: 0.85rem;
  color: var(--ink-500);
}
.woocommerce div.product .woocommerce-review-link:hover {
  color: var(--violet-700);
}

.woocommerce div.product p.price,
.woocommerce div.product span.price {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  color: var(--violet-700);
  margin: 0;
}
.woocommerce div.product p.price del {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 0.65em;
  color: var(--ink-300);
  opacity: 1;
  margin-right: 0.5em;
}
.woocommerce div.product p.price ins {
  text-decoration: none;
}

.woocommerce div.product .woocommerce-product-details__short-description {
  font-size: 1rem;
  line-height: 1.75;
  color: var(--ink-500);
  max-width: 42ch;
}
.woocommerce div.product .woocommerce-product-details__short-description p:last-child {
  margin-bottom: 0;
}

.woocommerce div.product .stock {
  display: inline-block;
  width: fit-content;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  padding: 0.4em 0.9em;
  border-radius: 999px;
  margin: 0;
  background: var(--ink-100);
  color: var(--ink-500);
}
.woocommerce div.product .stock.in-stock {
  background: var(--violet-50);
  color: var(--violet-700);
}
.woocommerce div.product .stock.out-of-stock {
  background: var(--ink-100);
  color: var(--ink-500);
}

/* ---- Add-to-cart form: quantity stepper + the stamped CTA ---- */
.woocommerce div.product form.cart {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin: 0.5rem 0 0;
}
.woocommerce div.product .quantity {
  margin: 0;
}
.woocommerce div.product .quantity .qty {
  width: 4.5rem;
  height: 3.1rem;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink-800);
  background: #fff;
  border: 1.5px solid var(--ink-200);
  border-radius: 999px;
  text-align: center;
  padding: 0 0.5rem;
}
.woocommerce div.product .quantity .qty:focus-visible {
  outline: 2px solid var(--violet-500);
  outline-offset: 2px;
}

.woocommerce div.product .single_add_to_cart_button {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 1.05rem;
  color: #fff;
  background: var(--violet-700);
  padding: 0.9em 1.75em;
  border-radius: 999px;
  border: none;
  cursor: pointer;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.15) inset,
    0 10px 24px rgba(11, 7, 19, 0.2),
    0 2px 6px rgba(11, 7, 19, 0.14);
  transition: transform 0.28s var(--ease-press), box-shadow 0.28s var(--ease-press), background 0.28s var(--ease-press);
}
.woocommerce div.product .single_add_to_cart_button:hover {
  background: var(--violet-800);
  transform: translateY(-2px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.15) inset,
    0 16px 32px rgba(11, 7, 19, 0.24),
    0 4px 10px rgba(11, 7, 19, 0.16);
}
.woocommerce div.product .single_add_to_cart_button:active {
  transform: translateY(1px) scale(0.98);
  box-shadow: 0 1px 6px rgba(11, 7, 19, 0.25) inset;
}
.woocommerce div.product .single_add_to_cart_button.disabled {
  background: var(--ink-200);
  color: var(--ink-400);
  cursor: not-allowed;
  box-shadow: none;
}

/* ---- Variable products: swatch-styled variation selects ---- */
.woocommerce div.product table.variations {
  width: 100%;
  border: none;
  margin: 0;
}
.woocommerce div.product table.variations td,
.woocommerce div.product table.variations th {
  border: none;
  padding: 0 0 0.75rem;
  vertical-align: middle;
}
.woocommerce div.product table.variations label {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  color: var(--ink-500);
}
.woocommerce div.product table.variations select {
  width: 100%;
  height: 2.9rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--ink-800);
  background: #fff;
  border: 1.5px solid var(--ink-200);
  border-radius: 6px;
  padding: 0 0.9rem;
}
.woocommerce div.product .woocommerce-variation-price .price {
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
}
.woocommerce div.product .reset_variations {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.85rem;
  color: var(--ink-400);
}
.woocommerce div.product .reset_variations:hover {
  color: var(--violet-700);
}

/* ---- Product meta: SKU, categories, tags ---- */
.woocommerce div.product .product_meta {
  font-size: 0.85rem;
  color: var(--ink-400);
  padding-top: 1rem;
  border-top: 1px solid var(--ink-200);
  margin-top: 0.5rem;
}
.woocommerce div.product .product_meta > span {
  display: block;
  margin-bottom: 0.35rem;
}
.woocommerce div.product .product_meta > span:last-child {
  margin-bottom: 0;
}
.woocommerce div.product .product_meta a {
  color: var(--ink-500);
}
.woocommerce div.product .product_meta a:hover {
  color: var(--violet-700);
  text-decoration: underline;
}

/* ---- Tabs: description / additional information / reviews ---- */
.woocommerce div.product .woocommerce-tabs {
  grid-column: 1 / -1;
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(2rem, 4vw, 2.75rem);
  border-top: 1px solid var(--ink-200);
}
.woocommerce div.product .woocommerce-tabs ul.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(1.5rem, 4vw, 2.5rem);
  margin: 0 0 clamp(1.75rem, 3.5vw, 2.5rem);
  padding: 0;
  list-style: none;
  border-bottom: 1px solid var(--ink-200);
}
.woocommerce div.product .woocommerce-tabs ul.tabs li {
  margin: 0;
  padding: 0 0 1rem;
}
.woocommerce div.product .woocommerce-tabs ul.tabs li a {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--ink-400);
}
.woocommerce div.product .woocommerce-tabs ul.tabs li.active {
  position: relative;
}
.woocommerce div.product .woocommerce-tabs ul.tabs li.active a {
  color: var(--ink-900);
}
.woocommerce div.product .woocommerce-tabs ul.tabs li.active::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -1px;
  height: 2px;
  background: var(--violet-700);
}
.woocommerce div.product .woocommerce-tabs .woocommerce-Tabs-panel {
  max-width: var(--measure);
  overflow-x: auto;
}
.woocommerce div.product .woocommerce-tabs .woocommerce-Tabs-panel h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  color: var(--ink-900);
  margin: 0 0 1rem;
}
.woocommerce div.product .woocommerce-tabs .woocommerce-Tabs-panel p,
.woocommerce div.product .woocommerce-tabs .woocommerce-Tabs-panel li {
  font-size: 1rem;
  line-height: 1.75;
  color: var(--ink-500);
}
.woocommerce div.product .woocommerce-tabs table.shop_attributes {
  width: 100%;
  min-width: 26rem;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.woocommerce div.product .woocommerce-tabs table.shop_attributes th,
.woocommerce div.product .woocommerce-tabs table.shop_attributes td {
  text-align: left;
  padding: 0.65rem 1rem 0.65rem 0;
  border-bottom: 1px solid var(--ink-200);
}
.woocommerce div.product .woocommerce-tabs table.shop_attributes th {
  font-weight: 500;
  color: var(--ink-900);
  width: 30%;
}
.woocommerce div.product .woocommerce-tabs table.shop_attributes td {
  color: var(--ink-500);
}

/* ---- Related products: flat grid, hairline dividers, no cards ---- */
.woocommerce div.product .related.products {
  grid-column: 1 / -1;
  margin-top: clamp(3rem, 6vw, 5rem);
  padding-top: clamp(2rem, 4vw, 2.75rem);
  border-top: 1px solid var(--ink-200);
}
.woocommerce div.product .related.products > h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  color: var(--ink-900);
  margin: 0 0 clamp(1.5rem, 3vw, 2.25rem);
}
.woocommerce div.product .related.products ul.products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: clamp(1.5rem, 3vw, 2.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
}
.woocommerce div.product .related.products ul.products li.product {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}
.woocommerce div.product .related.products ul.products li.product a {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}
.woocommerce div.product .related.products ul.products li.product img {
  width: 100%;
  height: auto;
  background: #fff;
  border: 1px solid var(--ink-200);
  transition: border-color 0.2s var(--ease-press);
}
.woocommerce div.product .related.products ul.products li.product:hover img {
  border-color: var(--violet-400);
}
.woocommerce div.product .related.products ul.products li.product .woocommerce-loop-product__title {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.95rem;
  color: var(--ink-800);
  margin: 0;
}
.woocommerce div.product .related.products ul.products li.product .price {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.9rem;
  color: var(--violet-700);
}

/* ---- Notices (added to cart, errors) ---- */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error,
.woocommerce-noreviews {
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--violet-800);
  background: var(--violet-50);
  padding: 1em 1.25em;
  margin: 0 0 1.5rem;
  list-style: none;
}
.woocommerce-message a.button,
.woocommerce-error a.button {
  color: var(--violet-700);
  font-weight: 500;
  text-decoration: underline;
}

@media (max-width: 720px) {
  .woocommerce div.product {
    grid-template-columns: 1fr;
  }
  .woocommerce div.product .summary.entry-summary {
    gap: 1rem;
  }

  /* Quantity + CTA side-by-side get cramped once the summary column
     is full viewport width — stack them and let the button take the
     full row so it clears the 44px tap-target comfortably. */
  .woocommerce div.product form.cart {
    flex-direction: column;
    align-items: stretch;
  }
  .woocommerce div.product .quantity .qty {
    width: 100%;
  }
  .woocommerce div.product .single_add_to_cart_button {
    justify-content: center;
  }

  .woocommerce div.product table.variations select {
    height: 3.1rem;
  }

  .woocommerce-breadcrumb {
    font-size: 0.8rem;
  }
}

@media (max-width: 480px) {
  .woocommerce div.product .product_title.entry-title {
    font-size: clamp(1.5rem, 7vw, 1.75rem);
  }
  .woocommerce div.product .related.products ul.products {
    grid-template-columns: repeat(2, 1fr);
    gap: 1.25rem;
  }
}
