/* ---------- 0. THE BRAND TYPEFACES ----------
   Agrandir, taken from the client's own stack. Self hosted here so a
   page renders the same offline, in a screenshot and on Netlify. */
@font-face{font-family:"Agrandir Grand";src:url("brand/Agrandir-GrandHeavy.woff2") format("woff2");font-weight:400 900;font-style:normal;font-display:swap;}
@font-face{font-family:"Agrandir";src:url("brand/AgrandirVariable.woff2") format("woff2");font-weight:300 700;font-style:normal;font-display:swap;}
@font-face{font-family:"Agrandir";src:url("brand/Agrandir-Bold.woff2") format("woff2");font-weight:700 900;font-style:normal;font-display:swap;}

/* ============================================================
   PIZZA PUNKS · campaign landing system
   Built by SocialsGroup. Duo-tonal per the client style guide
   (PIZZA PUNKS STYLE GUIDE AUG 2025 V1).

   FONTS: Agrandir Grand Heavy + Toothpick are licensed Pangram
   Pangram faces. Drop the .woff2 files into /assets/fonts/ and
   every page snaps to brand. Until then the fallback stack runs.
   ============================================================ */

/* ---------- 1. LICENSED FONT HOOKS ---------- */

@font-face {
  font-family: "Agrandir Grand";
  src: url("./fonts/Agrandir-GrandHeavy.woff2") format("woff2");
  font-weight: 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Agrandir";
  src: url("./fonts/Agrandir-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Toothpick";
  src: url("./fonts/Toothpick.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---------- 2. TOKENS ---------- */

:root {
  /* Exact palette from the client style guide. Do not alter. */
  --midnight: #141617;
  --charcoal: #1e2021;
  --anarchy: #ff2146;
  --cheese: #fd8e1d;
  --newspaper: #fdf1dc;

  /* Duo-tonal slots. Every page sets these two, and only these two,
     as its base. A third colour may appear as a signal only. */
  --ground: var(--newspaper);
  --ink: var(--midnight);
  --accent: var(--anarchy);
  --accent-ink: var(--newspaper);

  /* Neutrals derived from Newspaper so even the greys stay warm.
     Set per-page in the [data-duo] blocks below. */
  --rule: color-mix(in srgb, var(--ink) 18%, transparent);
  --muted: color-mix(in srgb, var(--ink) 62%, transparent);

  /* The real wordmark, and the paper it sits on. Every duo block below
     resets --logo to match its ground, so the mark is never the same
     value as the surface behind it. */
  --logo: url("brand/logo-dark.png");
  --paper: url("brand/tx-newspaper.jpg");

  --display: "Agrandir Grand", "Archivo Black", "Arial Black",
    system-ui, sans-serif;
  --body: "Agrandir", "Archivo", system-ui, -apple-system, sans-serif;
  --script: "Toothpick", "Caveat", cursive;
  --mono: "DM Mono", ui-monospace, "SFMono-Regular", monospace;

  /* Type scale · 1.26 ratio, clamped for fluid setting */
  --t-xs: 0.75rem;
  --t-sm: 0.875rem;
  --t-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  --t-lg: clamp(1.25rem, 1.1rem + 0.7vw, 1.6rem);
  --t-xl: clamp(1.75rem, 1.4rem + 1.6vw, 2.6rem);
  --t-2xl: clamp(2.4rem, 1.7rem + 3.4vw, 4.4rem);
  --t-3xl: clamp(2.8rem, 1.6rem + 5.2vw, 6rem);
  --t-4xl: clamp(3rem, 1.1rem + 7.6vw, 9rem);

  --gutter: clamp(1.25rem, 4vw, 5rem);
  --stack: clamp(4.5rem, 9vw, 9rem);

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-punch: cubic-bezier(0.7, 0, 0.2, 1);
}

/* These pages commit to one visual world: the brand is duo-tonal,
   high contrast and hard-lit. The palette is identical in every
   theme state so a dark-mode viewer sees the intended design
   rather than an inversion of it. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --midnight: #141617;
    --charcoal: #1e2021;
    --anarchy: #ff2146;
    --cheese: #fd8e1d;
    --newspaper: #fdf1dc;
  }
}
:root[data-theme="dark"] {
  --midnight: #141617;
  --charcoal: #1e2021;
  --anarchy: #ff2146;
  --cheese: #fd8e1d;
  --newspaper: #fdf1dc;
}

/* ---------- 3. DUO-TONAL PAGE SETS ----------
   Each campaign starts from two complementary colours, per the
   guide. The invert class swaps them at the pivot section.
   Every pairing below has been contrast-checked; no pairing puts
   the logo or icon on a matching ground. */

[data-duo="anarchy-newspaper"] {
  --ground: var(--newspaper);
  --ink: var(--midnight);
  --ink-base: var(--midnight);
  --accent: var(--anarchy);
  --accent-ink: var(--newspaper);
  --rule: color-mix(in srgb, var(--ink) 18%, transparent);
  --muted: color-mix(in srgb, var(--ink) 66%, transparent);
  --logo: url("brand/logo-dark.png");
  --paper: url("brand/tx-newspaper.jpg");
}
[data-duo="midnight-newspaper"] {
  --ground: var(--newspaper);
  --ink: var(--midnight);
  --ink-base: var(--midnight);
  --accent: var(--midnight);
  --accent-ink: var(--newspaper);
  --rule: color-mix(in srgb, var(--ink) 18%, transparent);
  --muted: color-mix(in srgb, var(--ink) 66%, transparent);
  --logo: url("brand/logo-dark.png");
  --paper: url("brand/tx-newspaper.jpg");
}
[data-duo="midnight-anarchy"] {
  --ground: var(--midnight);
  --ink: var(--newspaper);
  --ink-base: var(--newspaper);
  --accent: var(--anarchy);
  --accent-ink: var(--newspaper);
  --rule: color-mix(in srgb, var(--ink) 18%, transparent);
  --muted: color-mix(in srgb, var(--ink) 66%, transparent);
  --logo: url("brand/logo-light.png");
  --paper: url("brand/tx-midnight.jpg");
}
[data-duo="cheese-midnight"] {
  --ground: var(--midnight);
  --ink: var(--newspaper);
  --ink-base: var(--newspaper);
  --accent: var(--cheese);
  --accent-ink: var(--midnight);
  --rule: color-mix(in srgb, var(--ink) 18%, transparent);
  --muted: color-mix(in srgb, var(--ink) 66%, transparent);
  --logo: url("brand/logo-light.png");
  --paper: url("brand/tx-midnight.jpg");
}
[data-duo="cheese-newspaper"] {
  --ground: var(--newspaper);
  --ink: var(--midnight);
  --ink-base: var(--midnight);
  --accent: var(--cheese);
  --accent-ink: var(--midnight);
  --rule: color-mix(in srgb, var(--ink) 18%, transparent);
  --muted: color-mix(in srgb, var(--ink) 66%, transparent);
  --logo: url("brand/logo-dark.png");
  --paper: url("brand/tx-newspaper.jpg");
}
[data-duo="anarchy-midnight"] {
  --ground: var(--midnight);
  --ink: var(--newspaper);
  --ink-base: var(--newspaper);
  --accent: var(--anarchy);
  --accent-ink: var(--newspaper);
  --rule: color-mix(in srgb, var(--ink) 18%, transparent);
  --muted: color-mix(in srgb, var(--ink) 66%, transparent);
  --logo: url("brand/logo-light.png");
  --paper: url("brand/tx-midnight.jpg");
}

/* ---------- 4. BASE ---------- */

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

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--t-base);
  line-height: 1.55;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  transition: background 0.8s var(--ease), color 0.8s var(--ease);
}

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

a {
  color: inherit;
}

::selection {
  background: var(--accent);
  color: var(--accent-ink);
}

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

/* ---------- 5. GRAIN ----------
   The guide's photography direction is hard, un-diffused light.
   A live grain layer keeps flat colour fields from reading as
   digital-clean. Canvas rather than a huge inline SVG. */

#grain {
  position: fixed;
  inset: 0;
  z-index: 9998;
  pointer-events: none;
  opacity: 0.055;
  mix-blend-mode: multiply;
}

/* ---------- 6. TYPE ---------- */

h1,
h2,
h3,
.display {
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 0.86;
  text-transform: uppercase;
  text-wrap: balance;
  margin: 0;
}

h1 {
  font-size: var(--t-3xl);
}
h2 {
  font-size: var(--t-2xl);
}
h3 {
  font-size: var(--t-xl);
  line-height: 0.94;
}

p {
  margin: 0;
  max-width: 62ch;
}

.lede {
  font-size: var(--t-lg);
  line-height: 1.4;
  max-width: 32ch;
}

.script {
  font-family: var(--script);
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
}

.eyebrow {
  font-family: var(--mono);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--muted);
  margin: 0;
}

.hot {
  color: var(--accent);
}

/* ---------- 7. LAYOUT ---------- */

.wrap {
  width: 100%;
  max-width: 1560px;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

section {
  position: relative;
  padding-block: var(--stack);
}

.split {
  display: grid;
  gap: clamp(2rem, 5vw, 5rem);
  align-items: center;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .split {
    grid-template-columns: 1fr 1fr;
  }
  .split--wide-left {
    grid-template-columns: 1.25fr 1fr;
  }
  .split--wide-right {
    grid-template-columns: 1fr 1.25fr;
  }
}

.stack-sm {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: flex-start;
}
.stack-md {
  display: flex;
  flex-direction: column;
  gap: 1.75rem;
  align-items: flex-start;
}

/* ---------- 8. NAV ---------- */

.nav {
  position: sticky;
  top: 0;
  z-index: 200;
  background: var(--accent);
  color: var(--accent-ink);
  border-bottom: 2px solid var(--accent-ink);
  transition: padding 0.35s var(--ease), background 0.8s var(--ease);
}
.nav__in {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: clamp(0.7rem, 1.4vw, 1.15rem);
}
.nav.is-condensed .nav__in {
  padding-block: 0.5rem;
}

.brand {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  text-decoration: none;
  flex: 0 0 auto;
}
.brand__mark {
  display: block;
  width: clamp(132px, 15vw, 186px);
  aspect-ratio: 1000 / 339;
  background: var(--logo) left center / contain no-repeat;
  /* The text stays in the DOM for screen readers and for the one client
     that blocks images. It is pushed out of sight, not display:none. */
  text-indent: -9999px;
  overflow: hidden;
  white-space: nowrap;
}
.brand__mantra {
  display: none;
  font-family: var(--mono);
  font-size: 0.5rem;
  letter-spacing: 0.4em;
  text-transform: uppercase;
  opacity: 0.85;
  border-top: 1.5px solid currentColor;
  padding-top: 0.2rem;
}

.nav__links {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}
.nav__links .btn {
  padding: 0.55rem 0.85rem;
}
@media (max-width: 1079px) {
  .nav__links .btn:not(:first-child) {
    display: none;
  }
}

/* ---------- 9. BUTTONS ---------- */

.btn {
  --btn-ink: var(--accent-ink);
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--display);
  font-size: clamp(0.75rem, 1vw, 0.9rem);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  text-decoration: none;
  padding: 0.7rem 1.15rem;
  border: 2px solid var(--btn-ink);
  color: var(--btn-ink);
  background: transparent;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--btn-ink);
  transform: translateY(101%);
  transition: transform 0.4s var(--ease-punch);
  z-index: -1;
}
.btn:hover::before,
.btn:focus-visible::before {
  transform: translateY(0);
}
.btn:hover,
.btn:focus-visible {
  color: var(--accent);
}

/* Primary CTA sits on the page ground, not the nav */
.btn--solid {
  --btn-ink: var(--ink);
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
  font-size: clamp(0.95rem, 1.5vw, 1.25rem);
  padding: 1.05rem 2rem;
}
.btn--solid::before {
  background: var(--ink);
}
.btn--solid:hover,
.btn--solid:focus-visible {
  color: var(--ground);
  border-color: var(--ink);
}

.btn--ghost {
  --btn-ink: var(--ink);
  font-size: clamp(0.85rem, 1.2vw, 1rem);
  padding: 0.9rem 1.6rem;
}
.btn--ghost:hover,
.btn--ghost:focus-visible {
  color: var(--ground);
}

/* ---------- 10. HERO ---------- */

.hero {
  position: relative;
  min-height: clamp(520px, 82vh, 880px);
  display: grid;
  align-items: end;
  padding-block: 0;
  overflow: hidden;
  border-bottom: 2px solid var(--ink);
}
.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  background: var(--charcoal);
}
.hero__media video,
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Hard-light grade per the guide: crushed shadows, lifted
     highlights, no softening. */
  filter: contrast(1.18) saturate(1.06) brightness(0.92);
  will-change: transform;
}
/* Two layers, not one. The vertical gradient alone was enough for a
   dark plate but not for the brighter library shots, where the
   headline sat on arugula and lost its edges. The horizontal layer
   protects the left column where all hero content lives, and fades
   out before the right edge so the photograph still reads. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
      to right,
      color-mix(in srgb, var(--midnight) 88%, transparent) 0%,
      color-mix(in srgb, var(--midnight) 66%, transparent) 34%,
      color-mix(in srgb, var(--midnight) 10%, transparent) 72%,
      transparent 100%
    ),
    linear-gradient(
      to top,
      color-mix(in srgb, var(--midnight) 88%, transparent) 0%,
      color-mix(in srgb, var(--midnight) 40%, transparent) 46%,
      color-mix(in srgb, var(--midnight) 14%, transparent) 100%
    );
}
@media (max-width: 899px) {
  /* No room to dodge the subject on a phone, so the plate takes a
     flat knock-down instead of a directional one. */
  .hero__scrim {
    background: linear-gradient(
      to top,
      color-mix(in srgb, var(--midnight) 92%, transparent) 0%,
      color-mix(in srgb, var(--midnight) 68%, transparent) 55%,
      color-mix(in srgb, var(--midnight) 52%, transparent) 100%
    );
  }
}
.hero__in {
  --muted: color-mix(in srgb, #fdf1dc 74%, transparent);
  position: relative;
  z-index: 2;
  padding-block: clamp(3rem, 8vh, 7rem);
  color: var(--newspaper);
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  align-items: flex-start;
}
.hero h1 {
  font-size: var(--t-4xl);
  letter-spacing: -0.05em;
}
.hero .lede {
  color: color-mix(in srgb, var(--newspaper) 88%, transparent);
  max-width: 40ch;
}
.hero .btn--ghost {
  --btn-ink: var(--newspaper);
}
.hero .btn--ghost:hover,
.hero .btn--ghost:focus-visible {
  color: var(--midnight);
}

/* Masked line reveal for the hero headline */
.reveal-line {
  display: block;
  overflow: hidden;
}
.reveal-line > span {
  display: block;
  transform: translateY(105%);
  animation: line-up 1.05s var(--ease) forwards;
}
.reveal-line:nth-child(1) > span {
  animation-delay: 0.12s;
}
.reveal-line:nth-child(2) > span {
  animation-delay: 0.22s;
}
.reveal-line:nth-child(3) > span {
  animation-delay: 0.32s;
}
.reveal-line:nth-child(4) > span {
  animation-delay: 0.42s;
}
@keyframes line-up {
  to {
    transform: translateY(0);
  }
}

/* ---------- 11. SCROLL REVEALS ---------- */

[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.85s var(--ease), transform 0.85s var(--ease);
  transition-delay: var(--d, 0s);
}
[data-reveal].is-in {
  opacity: 1;
  transform: none;
}

[data-reveal="wipe"] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 1.05s var(--ease-punch);
  transition-delay: var(--d, 0s);
}
[data-reveal="wipe"].is-in {
  clip-path: inset(0 0 0 0);
}

/* ---------- 12. THE DUO-TONAL INVERT ----------
   The page's two colours swap at the pivot. This is the guide's
   duo-tonal rule turned into the motion system. */

.invert {
  background: var(--accent);
  color: var(--accent-ink);
  --ink: var(--accent-ink);
  --rule: color-mix(in srgb, var(--accent-ink) 24%, transparent);
  --muted: color-mix(in srgb, var(--accent-ink) 72%, transparent);
  position: relative;
  overflow: hidden;
}
.invert::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ground);
  transform-origin: bottom;
  transform: scaleY(1);
  transition: transform 1.1s var(--ease-punch);
}
.invert.is-in::before {
  transform: scaleY(0);
}
.invert > * {
  position: relative;
  z-index: 1;
}
.invert .btn--solid {
  background: var(--accent-ink);
  color: var(--accent);
  border-color: var(--accent-ink);
}
.invert .btn--solid::before {
  background: var(--accent);
}
.invert .btn--solid:hover,
.invert .btn--solid:focus-visible {
  color: var(--accent-ink);
  border-color: var(--accent-ink);
}

/* ---------- 13. HAND-DRAWN MARKS ----------
   Their site already owns the scribble and the circle. Here they
   draw themselves in on scroll instead of sitting still. */

.mark {
  position: absolute;
  pointer-events: none;
  overflow: visible;
}
.mark path,
.mark ellipse {
  fill: none;
  stroke: var(--accent);
  stroke-width: 9;
  stroke-linecap: round;
  stroke-dasharray: var(--len, 1200);
  stroke-dashoffset: var(--len, 1200);
}
.mark.is-in path,
.mark.is-in ellipse {
  transition: stroke-dashoffset 1.15s var(--ease) var(--d, 0.1s);
  stroke-dashoffset: 0;
}

.circled {
  position: relative;
  display: inline-block;
  padding-inline: 0.15em;
}
.circled .mark {
  inset: -34% -9% -30% -9%;
  width: 118%;
  height: 168%;
}

.struck {
  position: relative;
  display: inline-block;
}
.struck .mark {
  left: -4%;
  right: -4%;
  top: 38%;
  width: 108%;
  height: 40%;
}

/* ---------- 14. MARQUEE ----------
   The brand pattern carries the mantra. Speed reacts to scroll. */

.ticker {
  border-block: 2px solid currentColor;
  padding-block: clamp(0.5rem, 1.2vw, 0.9rem);
  overflow: hidden;
  white-space: nowrap;
  user-select: none;
}
.ticker__track {
  display: inline-flex;
  gap: 2.5rem;
  align-items: center;
  will-change: transform;
}
.ticker__item {
  font-family: var(--display);
  font-size: clamp(1.5rem, 3.4vw, 3rem);
  text-transform: uppercase;
  letter-spacing: -0.03em;
  display: inline-flex;
  align-items: center;
  gap: 2.5rem;
}
.ticker__item::after {
  content: "";
  width: clamp(0.4rem, 0.9vw, 0.7rem);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--accent);
  flex: 0 0 auto;
}
.ticker--invert .ticker__item::after {
  background: currentColor;
}

/* ---------- 15. TYPEWRITER ---------- */

.typewriter {
  min-height: 1.2em;
}
.typewriter::after {
  content: "";
  display: inline-block;
  width: 0.06em;
  height: 0.8em;
  background: currentColor;
  margin-left: 0.06em;
  vertical-align: baseline;
  animation: caret 0.9s steps(1) infinite;
}
.typewriter.is-done::after {
  animation: none;
  opacity: 0;
}
@keyframes caret {
  50% {
    opacity: 0;
  }
}

/* ---------- 16. EXPANDING CARD STRIP ----------
   Their homepage uses this. Here the panels carry the campaign's
   proof points rather than generic brand pillars. */

.strip {
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-block: 2px solid var(--ink);
}
@media (min-width: 900px) {
  .strip {
    flex-direction: row;
    height: clamp(440px, 62vh, 680px);
  }
}
.panel {
  position: relative;
  flex: 1 1 0;
  min-height: 240px;
  overflow: hidden;
  background: var(--charcoal);
  color: var(--newspaper);
  border: 0;
  text-align: left;
  cursor: pointer;
  font: inherit;
  padding: 0;
  transition: flex-grow 0.75s var(--ease);
}
@media (min-width: 900px) {
  .panel {
    min-height: 0;
  }
  .panel.is-open {
    flex-grow: 3.2;
  }
}
.panel__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
}
.panel__media .plate {
  width: 100%;
  height: 100%;
}
.panel__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: contrast(1.2) saturate(1.05) brightness(0.78);
  transition: transform 1.1s var(--ease), filter 0.6s var(--ease);
}
.panel.is-open .panel__media img {
  transform: scale(1.04);
  filter: contrast(1.15) saturate(1.08) brightness(0.9);
}
.panel__in {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0.9rem;
  padding: clamp(1.25rem, 2.4vw, 2rem);
  background: linear-gradient(
    to top,
    color-mix(in srgb, var(--midnight) 88%, transparent) 0%,
    transparent 62%
  );
}
.panel h3 {
  max-width: 12ch;
}
/* A collapsed panel is a narrow column, so a long word has to break
   rather than run out of the frame. Only the closed state needs it,
   the open one has the room. */
.panel:not(.is-open) h3 {
  font-size: clamp(1rem, 1.35vw, 1.4rem);
  overflow-wrap: anywhere;
  hyphens: auto;
}
/* A collapsed panel's body must take no vertical space, or the
   heading floats up off the bottom edge and the strip looks
   mis-set. Opacity alone left the box in the layout. */
.panel__body {
  max-width: 46ch;
  max-height: 0;
  overflow: hidden;
  opacity: 0;
  transform: translateY(12px);
  transition: max-height 0.6s var(--ease), opacity 0.45s var(--ease) 0.12s,
    transform 0.5s var(--ease) 0.12s;
}
.panel.is-open .panel__body {
  max-height: 22rem;
  opacity: 1;
  transform: none;
}
@media (max-width: 899px) {
  .panel__body {
    max-height: none;
    opacity: 1;
    transform: none;
  }
}

/* ---------- 17. STAT ROW ----------
   Only confirmed facts appear here. Anything unconfirmed uses the
   TBC token in section 19 instead. */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 2px;
  background: var(--rule);
  border: 2px solid var(--ink);
}
.stat {
  background: var(--ground);
  padding: clamp(1.4rem, 3vw, 2.4rem);
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.invert .stat {
  background: var(--accent);
}
.stat__n {
  font-family: var(--display);
  font-size: var(--t-2xl);
  line-height: 0.85;
  letter-spacing: -0.05em;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.invert .stat__n {
  color: var(--accent-ink);
}
.stat__l {
  font-family: var(--mono);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--muted);
}

/* ---------- 18. CITY LIST ---------- */

.cities {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0;
  align-items: baseline;
  font-family: var(--display);
  font-size: var(--t-xl);
  text-transform: uppercase;
  letter-spacing: -0.03em;
  line-height: 1.1;
}
.cities span:not(:last-child)::after {
  content: "·";
  color: var(--accent);
  margin-inline: 0.45em;
}
.invert .cities span:not(:last-child)::after {
  color: var(--accent-ink);
}

/* ---------- 19. UNCONFIRMED TERMS ----------
   Standing rule: never invent a number. Anything not confirmed in
   writing renders as a machine-looking token that cannot be
   mistaken for copy, and trips the draft banner. */

.tbc {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-family: var(--mono);
  font-size: 0.8em;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  background: var(--newspaper);
  color: var(--midnight);
  border: 2px dashed var(--anarchy);
  padding: 0.15em 0.55em 0.15em 0;
  vertical-align: middle;
  white-space: nowrap;
}
/* The chip is always Anarchy red so an unconfirmed term shouts on
   every one of the five grounds, not just the pale ones. */
.tbc::before {
  content: "TBC";
  font-weight: 700;
  background: var(--anarchy);
  color: var(--newspaper);
  align-self: stretch;
  display: flex;
  align-items: center;
  padding: 0 0.5em;
}

.draftbar {
  position: relative;
  z-index: 300;
  background: repeating-linear-gradient(
    45deg,
    var(--cheese) 0 18px,
    var(--midnight) 18px 36px
  );
  padding: 3px;
}
.draftbar__in {
  background: var(--midnight);
  color: var(--newspaper);
  font-family: var(--mono);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  padding: 0.75rem var(--gutter);
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  justify-content: space-between;
}
.draftbar strong {
  color: var(--cheese);
}

/* ---------- 20. TERMS TABLE ---------- */

.terms {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--mono);
  font-size: var(--t-sm);
}
.terms caption {
  text-align: left;
  font-family: var(--display);
  font-size: var(--t-lg);
  text-transform: uppercase;
  letter-spacing: -0.03em;
  padding-bottom: 1rem;
}
.terms th,
.terms td {
  text-align: left;
  padding: 0.85rem 1rem;
  border-bottom: 1.5px solid var(--rule);
  vertical-align: top;
}
.terms th {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: var(--t-xs);
  color: var(--muted);
  width: 34%;
}
.tablewrap {
  overflow-x: auto;
}

/* ---------- 21. QUOTE ---------- */

.quote {
  font-family: var(--display);
  font-size: var(--t-2xl);
  line-height: 0.94;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  max-width: 22ch;
  margin: 0;
}
.quote__by {
  font-family: var(--mono);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--muted);
  margin-top: 1.5rem;
}

/* ---------- 22. FOOTER ---------- */

.foot {
  background: var(--midnight);
  color: var(--newspaper);
  padding-block: clamp(3rem, 6vw, 5rem) 2rem;
  --rule: color-mix(in srgb, #fdf1dc 22%, transparent);
  --muted: color-mix(in srgb, #fdf1dc 66%, transparent);
}
.foot__grid {
  display: grid;
  gap: 2.5rem;
  grid-template-columns: 1fr;
}
@media (min-width: 780px) {
  .foot__grid {
    grid-template-columns: 1.4fr 1fr 1fr;
  }
}
.foot h4 {
  font-family: var(--mono);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--muted);
  margin: 0 0 0.9rem;
  font-weight: 400;
}
.foot ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.foot a {
  text-decoration: none;
  border-bottom: 1.5px solid transparent;
  transition: border-color 0.25s var(--ease);
}
.foot a:hover {
  border-bottom-color: var(--anarchy);
}
.foot__base {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1.5px solid var(--rule);
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  justify-content: space-between;
}

/* ---------- 23. CURSOR ---------- */

.cursor {
  position: fixed;
  top: 0;
  left: 0;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--anarchy);
  pointer-events: none;
  z-index: 9999;
  mix-blend-mode: difference;
  transform: translate3d(-100px, -100px, 0);
  transition: width 0.28s var(--ease), height 0.28s var(--ease),
    opacity 0.28s var(--ease);
}
.cursor.is-lg {
  width: 62px;
  height: 62px;
}
@media (hover: none), (pointer: coarse) {
  .cursor {
    display: none;
  }
}

/* ---------- 24. UTILITIES ---------- */

.frame {
  border: 2px solid var(--ink);
  overflow: hidden;
}
.frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: contrast(1.15) saturate(1.05);
}
.ratio-4-5 {
  aspect-ratio: 4 / 5;
}
.ratio-3-2 {
  aspect-ratio: 3 / 2;
}
.ratio-1-1 {
  aspect-ratio: 1 / 1;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 999;
  background: var(--midnight);
  color: var(--newspaper);
  padding: 0.75rem 1.25rem;
  font-family: var(--mono);
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
}
.skip:focus {
  left: 0;
}

/* ---------- 25. REDUCED MOTION ---------- */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal-line > span {
    transform: none;
  }
  [data-reveal] {
    opacity: 1;
    transform: none;
    clip-path: none;
  }
  .invert::before {
    display: none;
  }
  .mark path,
  .mark ellipse {
    stroke-dashoffset: 0;
  }
  .panel__body {
    opacity: 1;
    transform: none;
  }
  #grain,
  .cursor {
    display: none;
  }
  .typewriter::after {
    display: none;
  }
}

/* ---------- 26. IMAGE PLATE SLOTS ----------
   Every image slot names the exact shot it needs. Until the real
   plate is dropped in, the slot renders as a labelled placeholder,
   so the page doubles as the shot list for the 22 Sept shoot and
   for the Higgsfield generation pack. Replace .plate with an
   <img> or <video> and nothing else changes. */

.plate {
  position: relative;
  background: var(--charcoal);
  color: var(--newspaper);
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  isolation: isolate;
}
.plate::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  background-image: repeating-linear-gradient(
      135deg,
      color-mix(in srgb, #fdf1dc 5%, transparent) 0 2px,
      transparent 2px 11px
    ),
    radial-gradient(
      120% 90% at 22% 8%,
      color-mix(in srgb, #fdf1dc 16%, transparent) 0%,
      transparent 58%
    );
}
.plate__tag {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: none;
  padding: clamp(0.85rem, 1.8vw, 1.35rem);
  font-family: var(--mono);
  font-size: var(--t-xs);
  line-height: 1.5;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: linear-gradient(
    to top,
    color-mix(in srgb, #141617 92%, transparent),
    transparent
  );
}
.plate__tag b {
  display: block;
  color: var(--cheese);
  letter-spacing: 0.16em;
  margin-bottom: 0.3rem;
}
.plate__tag span {
  color: color-mix(in srgb, #fdf1dc 68%, transparent);
  text-transform: none;
  letter-spacing: 0.02em;
  font-size: 0.95em;
}

/* An unfilled slot inside a collapsed strip panel has nowhere to
   put its brief without landing on the heading. Hold it back until
   the panel is opened, where there is room for it. */
.panel:not(.is-open) .panel__media .plate__tag {
  opacity: 0;
  pointer-events: none;
}
.panel__media .plate__tag {
  transition: opacity 0.35s var(--ease);
}

/* Hero plate variant sits behind the headline */
.hero__media .plate {
  width: 100%;
  height: 100%;
  align-items: flex-start;
  justify-content: flex-end;
}
.hero__media .plate__tag {
  width: min(38ch, 60%);
  align-self: flex-start;
  background: none;
  text-align: right;
  opacity: 0.72;
}

/* ---------- 27. RUNNING ORDER (campaign index) ---------- */

.index-grid {
  display: grid;
  gap: 2px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  background: var(--rule);
  border: 2px solid var(--ink);
}
.card {
  background: var(--ground);
  padding: clamp(1.5rem, 3vw, 2.25rem);
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  text-decoration: none;
  color: inherit;
  position: relative;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}
.card:hover,
.card:focus-visible {
  background: var(--accent);
  color: var(--accent-ink);
}
.card:hover .card__k,
.card:focus-visible .card__k {
  color: var(--accent-ink);
  border-color: var(--accent-ink);
}
.card h3 {
  font-size: var(--t-lg);
}
.card p {
  font-size: var(--t-sm);
  line-height: 1.5;
}
.card__k {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  border: 1.5px solid var(--rule);
  padding: 0.2rem 0.5rem;
  align-self: flex-start;
  color: var(--muted);
}
.card__k--hold {
  background: var(--cheese);
  color: var(--midnight);
  border-color: var(--midnight);
}
.card__k--go {
  background: var(--accent);
  color: var(--accent-ink);
  border-color: var(--accent);
}

/* ---------- 28. REAL PHOTOGRAPHY IN THE SLOTS ----------
   An <img> sits inside every plate. When it loads, the slot label
   is hidden and the photograph takes over. When the file is not
   there, punk.js drops the image and the labelled brief stays.
   Half a folder of photography works; nothing needs editing. */

.plate__img {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The guide's hard-light direction. Most restaurant photography
     arrives diffused, so it gets pushed here rather than in post. */
  filter: contrast(1.16) saturate(1.06) brightness(0.97);
}

.plate.has-img .plate__tag {
  display: none;
}

/* With a real plate behind it the diagonal scaffolding pattern
   would show through the photograph. */
.plate.has-img::before {
  display: none;
}

/* Panels crop harder and sit under a gradient, so they can take a
   touch more contrast without losing the subject. */
.panel__media .plate__img {
  filter: contrast(1.2) saturate(1.05) brightness(0.78);
  transition: transform 1.1s var(--ease), filter 0.6s var(--ease);
}
.panel.is-open .panel__media .plate__img {
  transform: scale(1.04);
  filter: contrast(1.15) saturate(1.08) brightness(0.9);
}

/* The hero plate is the one place a photograph is doing the work of
   a video, so it gets the parallax transform from punk.js. */
.hero__media .plate__img {
  will-change: transform;
  filter: contrast(1.14) saturate(1.04) brightness(0.78);
}

/* ---------- STEPS ----------
   Used by the workplace and venue pages. The employee half of
   Friday Pizza Club has to be understood in about five seconds,
   so the action is a numbered run rather than prose. The numeral
   is a CSS counter, which keeps it out of the rendered text and
   therefore out of the copy the number rule checks. */

.steps {
  list-style: none;
  counter-reset: step;
  display: grid;
  gap: 2px;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr));
  background: var(--rule);
  border: 2px solid var(--ink);
}

.step {
  counter-increment: step;
  background: var(--ground);
  padding: clamp(1.1rem, 2.2vw, 1.6rem);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  position: relative;
}

.step::before {
  content: counter(step);
  font-family: var(--display);
  font-size: clamp(2rem, 1.4rem + 2vw, 3.2rem);
  line-height: 0.8;
  color: var(--accent);
  letter-spacing: -0.05em;
}

.step h3 {
  font-size: var(--t-lg);
  line-height: 1.05;
}

.step p {
  font-size: var(--t-sm);
  line-height: 1.5;
  color: var(--muted);
}

/* A card grid that is not a link. Same frame as the index grid,
   used for the three ways a workplace can pay. */
.card--static {
  cursor: default;
}
.card--static:hover,
.card--static:focus-visible {
  background: var(--ground);
  color: inherit;
}
.card--static:hover .card__k {
  color: var(--accent-ink);
  border-color: var(--accent);
}

/* The one line proposition, set as a hard band. Duo-tonal by
   definition: accent ground, accent ink, nothing else in it. */
.band {
  background: var(--accent);
  color: var(--accent-ink);
  padding: clamp(1.5rem, 4vw, 2.75rem) 0;
}
.band p {
  font-family: var(--display);
  font-size: var(--t-xl);
  line-height: 0.98;
  letter-spacing: -0.03em;
  text-transform: uppercase;
  max-width: 22ch;
}


/* ---------- 14. THE PAPER ----------
   Their own Newspaper, Midnight, Anarchy and Cheese grounds, set per
   duo in section 3. Solid --ground stays underneath, so a page that
   cannot load the texture still lands on the right colour. */
body {
  background-color: var(--ground);
  background-image: var(--paper);
  background-size: 900px auto;
  background-repeat: repeat;
  background-attachment: fixed;
}
.brand { align-items: flex-start; }

/* ---------- The street competition entry form ----------
   The only form in the whole campaign. Built so the journey and
   the copy can be signed off; it posts nowhere, because there is
   no destination and no confirmed data protection wording. */
.entry {
  display: grid;
  gap: 1rem;
  max-width: 34rem;
  margin-top: 0.5rem;
}
.entry label {
  display: grid;
  gap: 0.4rem;
}
.entry label span {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.75;
}
.entry input {
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  background: transparent;
  border: 2px solid var(--ink);
  border-radius: 0;
  padding: 0.85rem 1rem;
  width: 100%;
}
.entry input::placeholder {
  color: var(--muted);
  opacity: 0.8;
}
.entry input:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
.entry button {
  justify-self: start;
}
.entry__note {
  font-family: var(--mono);
  font-size: 0.72rem;
  line-height: 1.6;
  opacity: 0.8;
}

/* Punctuation immediately after a drawn mark, pulled back
   against the mark's own inline padding so it does not float
   away from the word it belongs to. */
.mark-tail {
  margin-left: -0.17em;
}
/* A drawn mark overshoots its text box by design. A headline
   carrying one needs the extra leading or the ellipse crashes
   into the line above it. */
h2:has(.circled),
h2:has(.struck) {
  line-height: 1.16;
}
.circled,
.struck {
  white-space: nowrap;
}

/* ============================================================
   SURFACES INSIDE AN INVERTED SECTION

   .invert redefines --ink and `color` for its whole subtree so
   body copy flips to the accent ink. Four things inside it draw
   their own background from --ground and take `color: inherit`:
   .card, .card--static, .step and .stat. On an inverted section
   they ended up as accent-ink text on a --ground panel, which
   on cheese-midnight and anarchy-newspaper is invisible.

   This never showed up on the original thirteen pages because
   none of them put a card or a step inside .invert. The home
   delivery pages and the Pizza Punks for Work pages both do.

   A panel is its own surface. It keeps its own background and
   gets the page's normal ink back, whatever the section around
   it is doing.
   ============================================================ */
.invert .card,
.invert .card--static,
.invert .step,
.invert .stat {
  color: var(--ink-base, var(--midnight));
  --ink: var(--ink-base, var(--midnight));
  --rule: color-mix(in srgb, var(--ink-base, var(--midnight)) 24%, transparent);
  --muted: color-mix(in srgb, var(--ink-base, var(--midnight)) 70%, transparent);
}
.invert .card:hover,
.invert .card:focus-visible,
.invert .card--static:hover,
.invert .card--static:focus-visible {
  background: var(--accent);
  color: var(--accent-ink);
  --ink: var(--accent-ink);
}
.invert .card:hover .card__k,
.invert .card--static:hover .card__k {
  color: var(--accent-ink);
  border-color: var(--accent-ink);
}
/* A held token on an inverted ground draws its border from
   --rule, which the rule above has just re-pointed at the panel
   ink. Outside a panel it still needs its own treatment. */
.invert > .wrap .tbc,
.invert > .wrap > * .tbc {
  background: var(--ground);
  color: var(--ink-base, var(--midnight));
  border-color: var(--ink-base, var(--midnight));
}

/* ============================================================
   THE INTRO · the brand moment on the delivery pages

   Ships hidden. punk-intro.js is the only thing that unhides
   it, after it has checked the session, the connection, reduced
   motion and its own load budget. A visitor with JavaScript off
   never sees a frame of it and can never be trapped behind it.

   The page underneath is fully rendered and interactive the
   whole time. This is an overlay, not a gate.

   The timeline lives in punk-intro.js; the durations here match
   FLOOD_MS, HOLD_MS and WIPE_MS in that file.
   ============================================================ */

.intro[hidden] {
  display: none;
}
.intro {
  position: fixed;
  inset: 0;
  z-index: 9999;
  /* Midnight from the first painted frame, so there is never a
     white flash before the film arrives. */
  background: #141617;
  overflow: hidden;
  transform: translate3d(0, 0, 0);
  /* A firm ease out with no overshoot. The overlay should feel
     lifted away, not bounced. */
  transition: transform 0.52s cubic-bezier(0.76, 0, 0.24, 1);
}

/* The exit is a wipe, not a cross-dissolve.
   Fading the overlay out over the page put the mark on top of
   the headline, the buttons and the draft bar for about half a
   second, which reads as a rendering fault rather than as a
   transition. Moving it off screen keeps the two layers apart:
   you see the intro, then you see the page. */
.intro.is-out {
  transform: translate3d(0, -101%, 0);
  pointer-events: none;
}

/* Scroll is locked only while the overlay is up, and the class
   comes off before the wipe starts, so the page is already
   scrollable as it is revealed. */
.has-intro body {
  overflow: hidden;
}

.intro__media {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
}
.intro__media video,
.intro__still {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The film settles rather than appearing. It eases down from a
   slight scale as it fades up, which is the difference between
   a shot arriving and a shot being switched on. */
.intro video {
  position: relative;
  z-index: 2;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity 0.34s ease-out, transform 1.5s cubic-bezier(0.22, 1, 0.36, 1);
}
.intro.is-playing video {
  opacity: 1;
  transform: scale(1);
}

/* The poster holds the first frame until the film is actually
   running, so the overlay is never an empty rectangle. */
.intro__still {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0.9;
}
.intro.is-playing .intro__still {
  opacity: 0;
  transition: opacity 0.3s ease-out;
}

/* Portrait footage on a landscape screen. Showing the whole
   frame centred, with the film's own colour bled out behind it,
   reads as deliberate; cropping a 9:16 shot down to a 16:9 slot
   throws away most of the picture. */
@media (min-aspect-ratio: 1/1) {
  .intro__media::before {
    content: "";
    position: absolute;
    inset: -10%;
    background: radial-gradient(
      ellipse at center,
      #4a0f1c 0%,
      #1c0a10 58%,
      #141617 100%
    );
  }
  .intro__media video,
  .intro__still {
    width: auto;
    max-width: 100%;
    object-fit: contain;
  }
}

/* ---------- THE MARK ----------
   Flat brand red, not a translucent scrim over a dimmed video
   frame. The mark needs a clean ground to land on; sitting it
   on a darkened still made it muddy and cheap. */
.intro__mark {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: grid;
  place-items: center;
  background: #ff2146;
  opacity: 0;
  pointer-events: none;
  /* A snap, not a dissolve. A slow crossfade from the film to
     flat red spends its middle as a muddy blend of the two,
     which was what made the mark look cheap. */
  transition: opacity 0.12s linear;
}
.intro.is-mark .intro__mark {
  opacity: 1;
}
.intro__mark img {
  /* Scales with the screen rather than capping early. A 340px
     cap left the mark marooned in the middle of a 1440px field
     of red on a laptop. */
  width: clamp(200px, 30vw, 520px);
  max-width: 76%;
  height: auto;
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 0.34s ease-out 0.12s,
    transform 0.62s cubic-bezier(0.22, 1, 0.36, 1) 0.1s;
}
.intro.is-mark .intro__mark img {
  opacity: 1;
  transform: scale(1);
}

/* Belt and braces. A visitor who asked for less motion never
   gets the overlay at all, but if the class somehow lands,
   nothing animates. */
@media (prefers-reduced-motion: reduce) {
  .intro,
  .intro video,
  .intro__still,
  .intro__mark,
  .intro__mark img {
    transition: none;
  }
}

/* A plate whose picture is a silent loop rather than a still.
   The frame, the border and the label are the plate's; only the
   media element differs, so it sits in the grid exactly as a
   photograph does. */
.plate--loop video.plate__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The offer band. Present only when src/offers.mjs has an offer
   for that city, which is why it is a single block rather than
   something threaded through the page: an offer appears, or the
   page reads as if there never was one. */
.offerband {
  background: var(--cheese);
  color: var(--midnight);
  padding-block: 0.9rem;
  border-top: 2px solid var(--midnight);
  border-bottom: 2px solid var(--midnight);
}
.offerband__line {
  font-family: var(--head);
  font-size: clamp(1.1rem, 0.8rem + 1.4vw, 1.75rem);
  line-height: 1.05;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  margin: 0;
}
.offerband__detail {
  font-family: var(--mono);
  font-size: 0.78rem;
  margin: 0.3rem 0 0;
}
.offerband__terms {
  font-family: var(--mono);
  font-size: 0.72rem;
  line-height: 1.6;
  opacity: 0.78;
  max-width: 62ch;
}

/* ============================================================
   PIZZA PUNKS FOR WORK · additions

   Everything above this line is the shared stylesheet, copied
   verbatim from the offers site. Only what the work subdomain
   needs on top lives below, so the two stay in step by copying
   punk.css across and re-appending this block.
   ============================================================ */

/* ---------- The slot picker ----------
   Presentation only until there is an ordering surface. It
   exists so an employee, and more importantly a gatekeeper
   being shown a demo, understands that windows are capped
   before they reach a checkout. The full one is deliberately in
   the set: a greyed out slot explains the capacity rule faster
   than a sentence about it does. */
.slots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0.75rem;
}
.slot {
  appearance: none;
  border: 2px solid var(--ink);
  background: transparent;
  color: var(--ink);
  border-radius: 0;
  padding: 1.15rem 1.25rem;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  cursor: pointer;
  transition: background 0.18s var(--ease-punch), color 0.18s var(--ease-punch),
    transform 0.18s var(--ease-punch);
}
.slot:hover:not(:disabled),
.slot:focus-visible:not(:disabled) {
  background: var(--accent);
  color: var(--accent-ink);
  transform: translateY(-2px);
}
.slot.is-picked {
  background: var(--ink);
  color: var(--ground);
}
.slot__t {
  font-family: var(--head);
  font-size: 1.15rem;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}
.slot__s {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.72;
}
.slot--full {
  cursor: not-allowed;
  opacity: 0.42;
  border-style: dashed;
}
.slot--full:hover {
  transform: none;
}

/* ---------- The demo banner ----------
   Shown only when the building page is opened with no building
   in the query string, so a demo can never be mistaken for a
   real building's page. Hidden in the markup and revealed by
   punk-work.js, which means it stays hidden if the script does
   not run rather than appearing on a live building page. */
.demo-note {
  border: 2px dashed var(--ink);
  padding: 0.85rem 1rem;
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1.5;
  max-width: 52ch;
  background: color-mix(in srgb, var(--ground) 82%, transparent);
}
.hero .demo-note {
  color: var(--newspaper);
  border-color: color-mix(in srgb, var(--newspaper) 52%, transparent);
  background: color-mix(in srgb, #141617 62%, transparent);
}

/* ---------- Table heads ----------
   The shared stylesheet only ever needed a two column key and
   value table. The objection and comparison tables on this
   subdomain have a real header row. */
.terms thead th {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: left;
  padding: 0.75rem 1rem;
  border-bottom: 2px solid var(--ink);
  opacity: 0.7;
}

/* The hero headline scales with its own length. shell.mjs sets
   --h1-scale from the copy, so a long headline comes down and a
   short one stays as big as it was. See the note in shell.mjs. */
.hero h1 {
  font-size: calc(var(--t-4xl) * var(--h1-scale, 1));
  line-height: 0.92;
  max-width: 18ch;
}
@media (max-width: 899px) {
  .hero h1 {
    max-width: 14ch;
  }
}
