/* ============================================================
   Fonts, self hosted. No third party request on any page.
   Two variable woff2 files (latin subset), served from this origin,
   which is what lets the scratchpad honestly say nothing leaves it.
   Both families are SIL Open Font License; the licence texts sit
   beside the files in css/fonts/.
   Body was Inter until 2026-08-26. It is an excellent typeface whose
   only problem was being the default answer everywhere, which on this
   site was working against the point. Public Sans replaced it: drawn
   for the US Web Design System, so legibility is the whole brief, and
   it happens to be 26.8 KB against Inter's 48.3 KB.
   The per weight blocks mirror Google's own CSS output so the
   rendering is identical: one variable file, pinned per weight.
   ============================================================ */

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin-variable.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 700;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin-variable.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Archivo";
  font-style: normal;
  font-weight: 900;
  font-stretch: 100%;
  font-display: swap;
  src: url("fonts/archivo-latin-variable.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/public-sans-latin-variable.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/public-sans-latin-variable.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Public Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/public-sans-latin-variable.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================
   Chris Haynes Lighting, dark stage theme
   ============================================================ */

:root {
  --bg: #0a0a0f;
  --bg-raised: #101018;
  --line: rgba(255, 255, 255, 0.08);
  --text: #ecebf2;
  --muted: #9d9cae;

  /* The accent is deliberately NOT a colour. Every AI built site picks
     one, and the orange this used to be had been taken by them. A warm
     bone white steps clearly off the cooler body text without competing
     with anything, which leaves the photographs to carry all the colour
     on the site. Old palette recorded in THEME-REVERT.md. */
  --accent: #f2e9d5;
  --accent-rgb: 242, 233, 213;
  --accent-soft: rgba(242, 233, 213, 0.12);
  --ink-on-accent: #0a0a0f;

  /* Who did what, studio side only. Two people told apart without
     reaching for the indigo and purple every UI kit ships with. */
  --who-mine: #7fb0bd;
  --who-client: #c4907f;

  --font-display: "Archivo", system-ui, sans-serif;
  --font-body: "Public Sans", system-ui, sans-serif;
}


* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

h1, h2, h3 {
  font-family: var(--font-display);
  line-height: 1.05;
  letter-spacing: 0.01em;
}

/* ---------- Nav ---------- */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.1rem clamp(1.25rem, 4vw, 3rem);
  transition: background 0.35s ease, box-shadow 0.35s ease;
}
.nav.scrolled {
  background: rgba(10, 10, 15, 0.82);
  backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 var(--line);
}
.nav-brand {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 1.35rem;
  text-decoration: none;
  letter-spacing: 0.04em;
}
.accent { color: var(--accent); }
.nav-links {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.5vw, 2rem);
}
.nav-links a {
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--muted);
  transition: color 0.2s ease;
}
.nav-links a:hover { color: var(--text); }
.nav-cta {
  color: var(--text) !important;
  border: 1px solid var(--line);
  padding: 0.45rem 1rem;
  border-radius: 6px;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.nav-cta:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  isolation: isolate;
}

/* Hero photo backdrop */
.hero-bg { position: absolute; inset: 0; z-index: -1; }
.hero-bg img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
}
.hero-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(10, 10, 15, 0.55), rgba(10, 10, 15, 0.25) 35%, rgba(10, 10, 15, 0.45) 100%),
    radial-gradient(ellipse 70% 60% at 50% 45%, rgba(10, 10, 15, 0.35), transparent 70%);
}
.stage-floor {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 34%;
  background: linear-gradient(to top, rgba(10, 10, 15, 0.95) 20%, transparent);
}

.hero-content {
  position: relative;
  padding: 6rem 1.5rem 4rem;
  max-width: 60rem;
}
.hero-kicker {
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1.4rem;
}
.hero-title {
  font-size: clamp(3.4rem, 12vw, 8.5rem);
  font-weight: 900;
  letter-spacing: 0.02em;
  /* The one glow the site keeps, and it is the key light on the name.
     Single layer: the second was a blue that only ever read as a screen
     effect. */
  text-shadow: 0 0 70px rgba(var(--accent-rgb), 0.22);
}
.hero-sub {
  margin: 1.6rem auto 0;
  max-width: 34rem;
  color: var(--muted);
}
.hero-actions {
  margin-top: 2.4rem;
  display: flex;
  gap: 0.9rem;
  justify-content: center;
  flex-wrap: wrap;
}
/* Four buttons of uneven length wrap raggedly on their own: 1 / 2 / 1 on
   a phone, 3 / 1 on a tablet, both of which read as an accident rather
   than a layout. The four together measure about 650px plus gaps, so
   they need roughly 700px of viewport to sit on one line and this
   breakpoint keeps a margin over that. Below it they go to a grid and
   share widths instead of wrapping: two even columns on a tablet, one
   full width column on a phone. Re-measure if a label changes length. */
@media (max-width: 739px) {
  .hero-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.7rem;
    max-width: 34rem;
    margin-left: auto;
    margin-right: auto;
  }
  .hero-actions .btn { text-align: center; }
}
@media (max-width: 560px) {
  .hero-actions {
    grid-template-columns: 1fr;
    max-width: 22rem;
  }
}

.btn {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  padding: 0.8rem 1.7rem;
  border-radius: 6px;
  transition: background 0.18s ease, border-color 0.18s ease, filter 0.18s ease;
}
.btn-solid {
  background: var(--accent);
  color: var(--ink-on-accent);
}
.btn-solid:hover {
  filter: brightness(1.08);
}
.btn-ghost {
  border: 1px solid var(--line);
  color: var(--text);
}
.btn-ghost:hover {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* ---------- Sections ---------- */
.section {
  padding: clamp(4.5rem, 9vw, 7.5rem) clamp(1.25rem, 5vw, 4rem);
  max-width: 78rem;
  margin: 0 auto;
}
/* The eyebrow label. It is a real pattern, but putting one above EVERY
   heading with no exception is what reads as machine written, so the
   homepage now carries none of these: its headings say what the section
   is on their own. What is left uses it as document navigation on the
   long plugin pages and the tour pages, where a reader is scanning for a
   part rather than reading down. Do not put it back on the homepage.
   Tracking is 0.18em everywhere now. It used to be five different values
   between 0.18 and 0.32, and the very wide ones were the loudest part of
   the tell. */
.section-kicker {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.8rem;
}
.section-head { margin-bottom: 2.8rem; }
.section h2 {
  font-size: clamp(1.9rem, 4.5vw, 3rem);
  font-weight: 700;
}

/* ---------- Selected Work ----------
   Was one auto-fit grid of five identical cards, which is the layout an
   LD's portfolio can least afford: the photographs are the product and
   the grid gave them all the same small box. Now there is a hierarchy
   that matches the actual credits, and three different shapes on the way
   down the page.

   The image ratios are chosen against the real files, not picked for
   looks. Everything is a 1600x1067 three-by-two EXCEPT atreyu.jpg, which
   is 1600x2399 portrait. The old grid letterboxed it to 16/10 and threw
   away most of the frame, so it is now the one card drawn tall. */

/* The lead credit. Only element on the homepage that breaks the 78rem
   container, capped at 92rem so it does not become absurd on a wide
   monitor, and the only one with its text over the picture. */
.work-lead {
  position: relative;
  left: 50%;
  transform: translateX(-50%);
  width: min(100vw - 2.5rem, 92rem);
  display: block;
  border-radius: 14px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  isolation: isolate;
}
.work-lead img {
  width: 100%;
  /* 2/1 from a 1.5 source crops a quarter of the height. Beam shots
     survive that; 21/9 did not, it cut the trusses off. */
  aspect-ratio: 2 / 1;
  object-fit: cover;
  transition: transform 0.5s ease;
}
.work-lead:hover img { transform: scale(1.02); }
.work-lead-body {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: clamp(1.25rem, 4vw, 2.5rem);
  background: linear-gradient(to top, rgba(10, 10, 15, 0.92), rgba(10, 10, 15, 0.55) 45%, transparent);
}
.work-lead-body h3 {
  font-size: clamp(1.3rem, 3vw, 2.1rem);
  font-weight: 700;
  margin-bottom: 0.3rem;
}
.work-lead-body p { color: var(--text); opacity: 0.85; font-size: 0.95rem; }

/* Two unequal rows, weighted opposite ways so the page zigzags rather
   than marching. The wide side is the bigger gallery in each pair. */
.work-row {
  display: grid;
  gap: 1.4rem;
  align-items: start;
  margin-top: 1.4rem;
}
.work-row-wide-first { grid-template-columns: 3fr 2fr; }
.work-row-wide-last  { grid-template-columns: 2fr 3fr; }
.work-card {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
  transition: border-color 0.25s ease;
}
.work-card:hover {
  border-color: rgba(var(--accent-rgb), 0.35);
}
/* Native three-by-two, so the landscape shots are not cropped at all. */
.work-media {
  aspect-ratio: 3 / 2;
  display: grid;
  place-items: center;
  position: relative;
  overflow: hidden;
}
/* The portrait one. 3/4 against a 0.67 source is a light trim. */
.work-card-tall .work-media { aspect-ratio: 3 / 4; }
/* The wide one, to sit against the tall card without towering over it. */
.work-media-wide { aspect-ratio: 16 / 9; }
.media-note {
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  border: 1px dashed rgba(255, 255, 255, 0.25);
  padding: 0.35rem 0.8rem;
  border-radius: 3px;
}
.work-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s ease;
}
.work-card:hover .work-media img { transform: scale(1.04); }

.work-info { padding: 1.1rem 1.25rem 1.3rem; }
.work-info h3 { font-size: 1.08rem; font-weight: 700; margin-bottom: 0.25rem; }
.work-info p  { font-size: 0.9rem; color: var(--muted); }

a.work-card {
  text-decoration: none;
  color: inherit;
  display: block;
}
.gallery-hint {
  display: inline-block;
  margin-top: 0.6rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  opacity: 0.75;
  transition: opacity 0.2s ease;
}
.work-card:hover .gallery-hint { opacity: 1; }

/* ---------- Tour pages ---------- */
.tour-main { padding-top: 5.5rem; }
.tour-layout {
  display: grid;
  grid-template-columns: minmax(280px, 400px) 1fr;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
  max-width: 78rem;
  margin: 0 auto;
  padding: 1.5rem clamp(1.25rem, 5vw, 4rem) clamp(3rem, 6vw, 5rem);
}
.tour-info {
  position: sticky;
  top: 6rem;
}
.tour-info h1 {
  font-size: clamp(2.1rem, 4.5vw, 3.4rem);
  font-weight: 900;
  line-height: 1.02;
  margin-top: 0.3rem;
}
.tour-year {
  color: var(--muted);
  margin-top: 0.7rem;
  font-size: 0.95rem;
}
.tour-credits {
  margin-top: 1.8rem;
  border-top: 1px solid var(--line);
}
.credit {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.75rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.95rem;
}
.credit span {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}
.tour-blurb {
  margin-top: 1.5rem;
  color: var(--muted);
  font-size: 0.95rem;
}
.tour-back {
  margin-top: 1.8rem;
  display: inline-block;
}
.tour-photos {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
  min-width: 0;
}
.tour-photos img {
  width: 100%;
  border-radius: 12px;
  border: 1px solid var(--line);
}

/* EDM collage page */
.collage {
  columns: 2 300px;
  column-gap: 1.1rem;
  min-width: 0;
}
.collage img {
  display: block;
  width: 100%;
  margin-bottom: 1.1rem;
  border-radius: 12px;
  border: 1px solid var(--line);
  break-inside: avoid;
}
.tour-festival-list {
  margin-top: 1.5rem;
}
.tour-festival-list li {
  font-size: 0.8rem;
  padding: 0.35rem 0.85rem;
}

.more-work {
  border-top: 1px solid var(--line);
  background: var(--bg-raised);
}
.more-work-inner {
  max-width: 78rem;
  margin: 0 auto;
  padding: clamp(2.5rem, 5vw, 4rem) clamp(1.25rem, 5vw, 4rem);
}
/* The homepage stopped using this when Selected Work became an editorial
   layout, but the "More Work" strip at the foot of all five tour pages
   still does, and it is the right shape there: two or three equal
   siblings with no hierarchy between them. Do not delete it again. */
.work-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.4rem;
}
.more-work .section-kicker { margin-bottom: 1.6rem; }

@media (max-width: 860px) {
  .tour-layout { grid-template-columns: 1fr; }
  .tour-info { position: static; }
}

/* ---------- Festivals ---------- */
.festivals {
  margin-top: 4rem;
  border-top: 1px solid var(--line);
  padding-top: 3rem;
}
.festivals-head h3 {
  font-size: 1.5rem;
  font-weight: 700;
}
.festivals-head p {
  color: var(--muted);
  margin-top: 0.3rem;
}
.festival-list {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 1.4rem;
}
.festival-list li {
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--text);
  border: 1px solid var(--line);
  background: var(--bg-raised);
  border-radius: 999px;
  padding: 0.42rem 1rem;
  white-space: nowrap;
  position: relative;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.festival-list li:hover {
  border-color: rgba(var(--accent-rgb), 0.45);
  background: var(--accent-soft);
}

/* Hover photo popover */
.chip-photo {
  position: absolute;
  bottom: calc(100% + 12px);
  left: 50%;
  width: 250px;
  transform: translateX(-50%) translateY(8px) rotate(-1.5deg);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  z-index: 30;
  transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s linear 0.25s;
}
.festival-list li:hover .chip-photo {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0) rotate(-1.5deg);
  transition-delay: 0s;
}
.chip-photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.65);
}
/* No popovers on touch devices */
@media (hover: none) {
  .chip-photo { display: none; }
}
.festival-list .festival-more {
  color: var(--muted);
  border-style: dashed;
  background: none;
}
.festival-more a {
  color: inherit;
  text-decoration: none;
}
.festival-list li:hover.festival-more,
.festival-more:hover {
  color: var(--accent);
  border-color: rgba(var(--accent-rgb), 0.5);
}
.festival-strip {
  margin-top: 1.8rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1rem;
}
.festival-strip img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 12px;
  border: 1px solid var(--line);
}

/* ---------- Scratchpad ----------
   Deliberately NOT another card grid. This section is two big pictures
   telling one story, sketch on the left and the render that came out of
   it on the right, so it breaks the run of grids either side of it.
   No kicker on this one either: the heading says what it is. */
.sketch-head { max-width: 46rem; }
.sketch-head h2 { margin-bottom: 1rem; }
.sketch-head p { color: var(--muted); }
.sketch-points {
  list-style: none;
  margin: 1.4rem 0 1.8rem;
  display: grid;
  gap: 0.55rem;
}
.sketch-points li {
  color: var(--text);
  font-size: 0.95rem;
  padding-left: 1.1rem;
  position: relative;
}
.sketch-points li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.5em;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.sketch-shots { margin-top: clamp(2rem, 4vw, 3rem); }
.sketch-pair {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.1rem;
  align-items: start;
}
.sketch-pair .shot { min-width: 0; }
/* The two shots come from different places and are different shapes:
   the scratchpad grab is 734x520 and the Capture render is 1920x1080.
   A shared ratio is what makes the pair read as one comparison rather
   than two loose pictures, and it lines the captions up. Both crop
   kindly at 16/10: the scratchpad shot loses dark air top and bottom,
   the render loses a sliver of beam at the sides. */
.sketch-pair img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--bg-raised);
}
/* The label sits under its own picture rather than floating over it, so
   nobody has to guess which side is which. */
.sketch-pair .shot span {
  display: block;
  margin-top: 0.6rem;
  font-size: 0.8rem;
  color: var(--muted);
}
.sketch-shots figcaption {
  margin-top: 1.2rem;
  font-size: 0.9rem;
  color: var(--muted);
}

@media (max-width: 720px) {
  .sketch-pair { grid-template-columns: 1fr; gap: 1.6rem; }
}

/* ---------- Plugin store ---------- */
.section-plugins { max-width: none; background: var(--bg-raised); border-block: 1px solid var(--line); }
.store-inner { max-width: 78rem; margin: 0 auto; }
.store-sub { color: var(--muted); margin-top: 0.8rem; max-width: 36rem; }

.product-card {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 1.5rem 1.6rem;
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
  transition: border-color 0.25s ease;
}
.product-card:hover {
  border-color: rgba(var(--accent-rgb), 0.35);
}
.product-card h3 {
  font-size: 1.15rem;
  font-weight: 700;
  margin-bottom: 0.5rem;
}
.product-card p { color: var(--muted); font-size: 0.95rem; }
.product-body { flex: 1; }
.product-card h3 a {
  text-decoration: none;
  transition: color 0.2s ease;
}
.product-card h3 a:hover { color: var(--accent); }
.product-more {
  display: inline-block;
  margin-top: 0.9rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  text-decoration: none;
  opacity: 0.8;
  transition: opacity 0.2s ease;
}
.product-more:hover { opacity: 1; }

.product-buy {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  border-top: 1px solid var(--line);
  padding-top: 1.1rem;
}
.product-price {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 1.5rem;
}
.product-buy .btn { padding: 0.6rem 1.4rem; }

/* Flagship card */
.product-featured {
  flex-direction: row;
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3rem);
  border-color: rgba(var(--accent-rgb), 0.4);
  margin-bottom: 1.4rem;
}
.product-featured .product-buy {
  border-top: none;
  border-left: 1px solid var(--line);
  padding-top: 0;
  padding-left: clamp(1.5rem, 3vw, 2.5rem);
  flex-direction: column;
  align-items: center;
  gap: 0.8rem;
  flex: none;
}
.product-featured .product-price { font-size: 2.2rem; }
.product-featured h3 { font-size: clamp(1.3rem, 2.6vw, 1.7rem); }
.product-badge {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  border: 1px solid rgba(var(--accent-rgb), 0.45);
  border-radius: 3px;
  padding: 0.25rem 0.75rem;
  margin-bottom: 0.9rem;
}
.product-points {
  list-style: none;
  margin-top: 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
}
.product-points li {
  color: var(--text);
  font-size: 0.9rem;
  padding-left: 1.1rem;
  position: relative;
}
.product-points li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.45em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.4rem;
}

.plugins-note {
  font-size: 0.85rem;
  color: var(--muted);
  margin-top: 2rem;
  text-align: center;
}
.plugins-note a { color: var(--text); }

@media (max-width: 720px) {
  .product-featured { flex-direction: column; align-items: stretch; }
  .product-featured .product-buy {
    border-left: none;
    border-top: 1px solid var(--line);
    padding-left: 0;
    padding-top: 1.1rem;
    flex-direction: row;
    justify-content: space-between;
  }
}

/* ---------- Mailing list ---------- */
.section-updates { text-align: center; }
.updates-inner { max-width: 40rem; margin: 0 auto; }
.updates-sub {
  color: var(--muted);
  margin-top: 0.9rem;
}
.signup-form {
  margin-top: 2rem;
  display: flex;
  gap: 0.7rem;
  justify-content: center;
  flex-wrap: wrap;
}
.signup-input {
  flex: 1 1 18rem;
  min-width: 0;
  max-width: 24rem;
  font-family: var(--font-body);
  font-size: 0.98rem;
  color: var(--text);
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 0.8rem 1.3rem;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.signup-input::placeholder { color: var(--muted); }
.signup-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.signup-form .btn { border: none; cursor: pointer; }
.signup-note {
  margin-top: 1.4rem;
  font-size: 0.85rem;
  color: var(--muted);
}
/* Spam trap: must stay hidden from people, visible to the form handler */
.signup-hp { position: absolute; left: -9999px; }
.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;
}

/* ---------- Plugin detail pages ---------- */
.plugin-main { padding-top: 5.5rem; }
.plugin-layout {
  display: grid;
  grid-template-columns: minmax(280px, 380px) 1fr;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
  max-width: 78rem;
  margin: 0 auto;
  padding: 1.5rem clamp(1.25rem, 5vw, 4rem) clamp(3rem, 6vw, 5rem);
}
.plugin-side { position: sticky; top: 6rem; }
.plugin-buy-card {
  background: var(--bg-raised);
  border: 1px solid rgba(var(--accent-rgb), 0.28);
  border-radius: 16px;
  padding: 1.6rem 1.6rem 1.8rem;
}
.plugin-buy-card h1 {
  font-size: clamp(1.7rem, 3.2vw, 2.4rem);
  font-weight: 900;
  line-height: 1.05;
}
.plugin-tagline {
  color: var(--muted);
  font-size: 0.95rem;
  margin-top: 0.8rem;
}
.plugin-price-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 1.4rem;
}
.plugin-price-row .product-price { font-size: 2.1rem; }
.plugin-spec {
  margin-top: 1.6rem;
  border-top: 1px solid var(--line);
}
.plugin-spec .credit { font-size: 0.9rem; }

/* Content column */
.plugin-content { min-width: 0; }
.plugin-block { margin-bottom: clamp(2.5rem, 5vw, 3.6rem); }
.plugin-block h2 {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  font-weight: 700;
  margin-bottom: 1rem;
}
.plugin-block p { color: var(--muted); max-width: 44rem; }
.plugin-block p + p { margin-top: 0.9rem; }
.plugin-block a:not(.btn) { color: var(--accent); }
.plugin-block code {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.88em;
  color: var(--text);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 0.08em 0.4em;
}
.plugin-block strong { color: var(--text); font-weight: 600; }

.feature-list, .step-list {
  list-style: none;
  margin-top: 1.2rem;
  max-width: 44rem;
}
.feature-list li {
  color: var(--muted);
  font-size: 0.95rem;
  padding-left: 1.4rem;
  position: relative;
  margin-bottom: 0.9rem;
}
.feature-list-tight li { margin-bottom: 0.6rem; }
.feature-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.62em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
}
.step-list { counter-reset: step; }
.step-list li {
  counter-increment: step;
  color: var(--muted);
  font-size: 0.95rem;
  padding-left: 2.4rem;
  position: relative;
  margin-bottom: 1rem;
}
.step-list li::before {
  content: counter(step);
  position: absolute;
  left: 0; top: 0;
  width: 1.7rem; height: 1.7rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(var(--accent-rgb), 0.45);
  color: var(--accent);
  font-family: var(--font-display);
  font-size: 0.85rem;
  font-weight: 700;
}

.feature-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.1rem;
  margin-top: 1.4rem;
}
.feature-card {
  background: var(--bg-raised);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 1.2rem 1.3rem;
  transition: border-color 0.25s ease;
}
.feature-card:hover {
  border-color: rgba(var(--accent-rgb), 0.32);
}
.feature-card h3 {
  font-size: 1rem;
  font-weight: 700;
  margin-bottom: 0.45rem;
}
.feature-card p { font-size: 0.92rem; }

/* ---------- Screenshots on the plugin pages (audit item 14) ---------- */
/* These are UI grabs, not photographs, so they are NEVER cropped by CSS:
   a punt page with its edge cut off proves nothing, which is the whole
   reason the pictures are going on. That is why there is no aspect-ratio
   or object-fit here, unlike .sketch-pair on the homepage where two
   photos of different shapes had to be made to match.

   `max-width` rather than `width`, deliberately. The content column is
   682px at 1440, and the five real files land either side of it: the
   Color Brain grab is 1344 wide and the punt page 820, so those two
   scale DOWN to fit, but the three feedback-window grabs are 688, 609
   and 599, and stretching those to fill the column would blur crisp
   monospace text for nothing. Small ones sit at native size and leave
   the space to their right. Every img carries width and height
   attributes so nothing reflows while they load.

   The two that scale down are wrapped in a link to the file itself, so
   the browser's own image viewer is the zoom. No lightbox, no script. */
.plugin-shot { margin-top: 1.6rem; }
.plugin-shot img {
  display: block;
  max-width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg-raised);
}
/* The link is only ever a wrapper around the picture, so it must not
   pick up the accent colour and underline that .plugin-block a carries. */
.plugin-shot > a {
  display: block;
  text-decoration: none;
  border-radius: 10px;
}
.plugin-shot > a:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.plugin-shot > a img { transition: border-color 0.25s ease; }
.plugin-shot > a:hover img { border-color: rgba(var(--accent-rgb), 0.32); }

.plugin-shot figcaption {
  margin-top: 0.7rem;
  font-size: 0.9rem;
  color: var(--muted);
  max-width: 44rem;
}
/* Says the picture opens full size, without a magnifier icon on top of
   the image. Only put this on a shot that is actually wrapped in a link. */
.plugin-shot .shot-zoom {
  color: var(--accent);
  font-size: 0.82rem;
}

/* Two grabs read as one comparison: the same button pressed once and
   twice, the same pool before and after. Side by side or it is not a
   comparison, so these two DO share a ratio. Crop to suit when the
   files land; until then they sit at their natural size. */
.plugin-shot-pair {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.1rem;
  align-items: start;
}
.plugin-shot-pair > div { min-width: 0; }
.plugin-shot-pair span {
  display: block;
  margin-top: 0.55rem;
  font-size: 0.8rem;
  color: var(--muted);
}
@media (max-width: 720px) {
  .plugin-shot-pair { grid-template-columns: 1fr; gap: 1.5rem; }
}

.plugin-callout {
  margin-top: 1.2rem;
  border-left: 2px solid var(--accent);
  background: var(--accent-soft);
  border-radius: 0 10px 10px 0;
  padding: 0.9rem 1.1rem;
  font-size: 0.93rem;
  color: var(--text) !important;
}

.plugin-cta {
  border-top: 1px solid var(--line);
  padding-top: clamp(2rem, 4vw, 2.6rem);
}
.plugin-cta .plugins-note { text-align: left; margin-top: 1.4rem; }
.plugin-cta .plugins-note a { color: var(--accent); }

/* Mini cards in the "more plugins" strip */
a.plugin-mini { text-decoration: none; color: inherit; }
a.plugin-mini .product-buy .gallery-hint { margin-top: 0; }

@media (max-width: 900px) {
  .plugin-layout { grid-template-columns: 1fr; }
  .plugin-side { position: static; }
}

/* ---------- About ---------- */
.about-inner {
  display: grid;
  grid-template-columns: minmax(240px, 340px) 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
.about-photo {
  aspect-ratio: 4 / 5;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: radial-gradient(ellipse at 50% 115%, #2c2410, #12121c 75%);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.about-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.about-copy h2 { margin-bottom: 1rem; }
.about-copy p  { color: var(--muted); max-width: 34rem; }
.about-copy p + p { margin-top: 1rem; }

/* ---------- Contact ---------- */
.section-contact { text-align: center; }
.contact-mail {
  display: inline-block;
  margin-top: 1.2rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.15rem, 3.2vw, 1.9rem);
  text-decoration: none;
  border-bottom: 2px solid var(--accent);
  padding-bottom: 0.2rem;
  transition: color 0.2s ease;
}
.contact-mail:hover { color: var(--accent); }
.contact-social { margin-top: 1.6rem; }
.contact-social a {
  color: var(--muted);
  font-size: 0.95rem;
  text-decoration: none;
}
.contact-social a:hover { color: var(--text); }

/* ---------- Footer ---------- */
.footer {
  border-top: 1px solid var(--line);
  padding: 1.6rem;
  text-align: center;
  color: var(--muted);
  font-size: 0.85rem;
}
/* Both tools live here, on EVERY page. The client sign in is a door for
   people who already have a key rather than something to sell a visitor,
   so it does not belong in the hero, but it does have to be findable:
   the first version of this was on the homepage alone and Chris could
   not find his own studio. The links carry a standing underline because
   muted grey with no underline did not read as clickable. */
.footer-links {
  margin-top: 0.6rem;
  font-size: 0.82rem;
  display: flex;
  gap: 1.5rem;
  justify-content: center;
  flex-wrap: wrap;
}
.footer-links a {
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  padding-bottom: 1px;
  transition: color 0.2s ease, border-color 0.2s ease;
}
.footer-links a:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ---------- Responsive ---------- */
@media (max-width: 820px) {
  .plugins-inner { grid-template-columns: 1fr; }
  .about-inner   { grid-template-columns: 1fr; }
  .about-media   { max-width: 300px; }
}

/* One column below this, and the lead stops breaking out and stops being
   cinematic: a 2/1 crop on a narrow screen is a letterbox slot.
   860 rather than 760 because at 820 the 2fr column lands on exactly
   280px, which was the OLD grid's minimum, and a 3/4 card that narrow
   reads as a sliver. Stacking beats squeezing. */
@media (max-width: 860px) {
  .work-row-wide-first,
  .work-row-wide-last { grid-template-columns: 1fr; }
  .work-lead { left: auto; transform: none; width: 100%; }
  .work-lead img { aspect-ratio: 3 / 2; }
  .work-card-tall .work-media { aspect-ratio: 3 / 2; }
  .work-media-wide { aspect-ratio: 3 / 2; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
