/* ==========================================================================
   Coffer Studios, Design System
   Fonts: Urbanist only (site-wide), used upright and italic for accents
   ========================================================================== */

:root {
  --ink: #0f0f0f;
  --paper: #ffffff;
  --paper-soft: #fcfcfc;
  --muted: #6b7280;
  --line: #e6e6e6;
  --surface-dark: #181818;
  --accent: #066aab;

  --font-sans: 'Urbanist', sans-serif;
  --font-serif: 'Urbanist', sans-serif;

  --container: 1240px;
  --gutter: clamp(20px, 5vw, 64px);

  --radius: 4px;
}

/* ==========================================================================
   Dark theme, proof-of-concept. Only ever applied via the toggle button
   on index.html (data-theme="dark" on <html>); no other page sets this
   attribute, so this block is inert everywhere else. Remove this block
   plus the toggle script in index.html to fully revert.
   ========================================================================== */
[data-theme="dark"] {
  --ink: #f2f2f2;
  --paper: #181818;
  --paper-soft: #202020;
  --muted: #9a9ea6;
  --line: #2a2a2a;
}
[data-theme="dark"] .site-header,
[data-theme="dark"] body.has-transparent-header .site-header.is-scrolled {
  background: #181818;
  border-bottom-color: #2a2a2a;
}
[data-theme="dark"] .section--soft { background: var(--paper-soft); }
[data-theme="dark"] .service-row:hover { background: #262626; }
[data-theme="dark"] .stars { color: var(--ink); }
[data-theme="dark"] .cta-split { border: 1px solid var(--line); }
[data-theme="dark"] #home-process { background: #000000; }
[data-theme="dark"] .notice-box { border-color: #4a4020; background: #2a2410; color: #d4c489; }

/* Header while transparent sits over the hero photo, which never changes
   with the theme, so nav/logo must stay in their light-mode colours there
   regardless of theme. Only once scrolled to a solid dark bar should they
   flip (which --ink already does automatically; only the raster logo
   needs an explicit invert since it isn't colour-driven by CSS). */
[data-theme="dark"] body.has-transparent-header .site-header:not(.is-scrolled) {
  color: #0f0f0f;
}
[data-theme="dark"] body.has-transparent-header .site-header:not(.is-scrolled) .main-nav a::after,
[data-theme="dark"] body.has-transparent-header .site-header:not(.is-scrolled) .nav-toggle span {
  background: #0f0f0f;
}
/* The mobile nav flyout is a solid dark panel of its own, not an overlay
   on the hero photo, so it needs to opt back out of the "stay dark" rule
   above even while the header itself is still unscrolled/transparent. */
[data-theme="dark"] body.has-transparent-header .site-header:not(.is-scrolled) .main-nav.is-open {
  color: var(--ink);
}
[data-theme="dark"] body.has-transparent-header .site-header:not(.is-scrolled) .main-nav.is-open a::after {
  background: var(--ink);
}
/* Every other page has an always-solid header, so the logo always needs
   to invert in dark mode; the homepage is the one exception (transparent
   over its unchanging hero photo) until it scrolls to a solid bar. */
[data-theme="dark"] .site-header .logo img { filter: invert(1); }
[data-theme="dark"] body.has-transparent-header .site-header:not(.is-scrolled) .logo img {
  filter: none;
}

/* Hero buttons sit on the same unchanged hero photo, so pin them to their
   light-mode look too instead of inverting with the theme. */
[data-theme="dark"] .hero-banner .btn {
  background: #0f0f0f; color: #ffffff; border-color: #0f0f0f;
}
[data-theme="dark"] .hero-banner .btn--outline {
  background: transparent; color: #0f0f0f; border-color: #0f0f0f;
}
[data-theme="dark"] .hero-banner .btn--outline:hover {
  background: #0f0f0f; color: #ffffff;
}
/* ...except Explore Our Process, which is pinned to its orange hover
   accent (see .btn-explore below) in light mode too, this rule would
   otherwise silently override that back to black in dark mode. */
[data-theme="dark"] .hero-banner .btn-explore:hover {
  background: rgb(231,139,28); border-color: rgb(231,139,28); color: #fff;
}

/* Cookie banner and back-to-top are small floating utility chips, always
   a dark pill regardless of theme (same idea as the footer, which never
   changes colour either); pin them rather than let them invert. */
[data-theme="dark"] .back-to-top { background: #0f0f0f; color: #fff; border-color: #0f0f0f; }
[data-theme="dark"] .back-to-top:hover { background: #fff; color: #0f0f0f; }
[data-theme="dark"] .cookie-banner { background: #0f0f0f; color: #fff; }
[data-theme="dark"] .cookie-btn-accept { background: #fff; color: #0f0f0f; }
[data-theme="dark"] .cookie-btn-decline { background: transparent; color: #fff; }

/* Sun/moon slider toggle for the dark theme POC above. Colours are fixed
   (not tied to --ink/--paper) since the switch itself needs to look right
   regardless of which theme is currently active. */
.theme-toggle-switch {
  /* Same height, radius and bottom offset as .back-to-top so the two
     fixed corner buttons read as a matched pair. */
  position: fixed; bottom: 24px; left: 24px; z-index: 200;
  width: 72px; height: 40px;
  padding: 4px;
  border: none; border-radius: 8px;
  background: #181818;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(0,0,0,.3);
  transition: background .3s ease;
}
.theme-toggle-switch .knob {
  width: 32px; height: 32px;
  border-radius: 5px;
  background: #ffffff;
  display: flex; align-items: center; justify-content: center;
  transform: translateX(0);
  transition: transform .3s ease, background .3s ease;
}
.theme-toggle-switch .knob svg { width: 16px; height: 16px; }
.theme-toggle-switch .icon-sun { color: #181818; }
.theme-toggle-switch .icon-moon { display: none; color: #f2f2f2; }
.theme-toggle-switch.is-dark { background: #f2f2f2; }
.theme-toggle-switch.is-dark .knob { transform: translateX(32px); background: #181818; }
.theme-toggle-switch.is-dark .icon-sun { display: none; }
.theme-toggle-switch.is-dark .icon-moon { display: block; }
[data-theme="dark"] .testimonial-scroll .testimonial-card { background: var(--paper-soft); }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

/* Browsers render <button> in a native system font by default rather
   than inheriting the page font, which silently throws off line-height
   (and therefore height) on any button that isn't a plain <a>. */
button { font-family: inherit; font-size: inherit; line-height: inherit; color: inherit; }

body {
  margin: 0;
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--paper);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

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

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

h1, h2, h3, h4 { margin: 0 0 .5em; font-weight: 600; line-height: 1.1; letter-spacing: -0.01em; }

p { margin: 0 0 1em; color: var(--muted); }

.container {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ==========================================================================
   Page loader, full-black overlay with a spinning mark. Hidden by default;
   only fades in if the page is still loading after a short delay (see the
   inline script in header.html), so a fast page load never flashes it.
   ========================================================================== */
#page-loader {
  position: fixed; inset: 0; z-index: 9999;
  background: #000;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity .4s ease;
}
#page-loader.is-visible { opacity: 1; visibility: visible; pointer-events: auto; }
#page-loader.is-hiding { opacity: 0; }
.page-loader-spinner { width: 120px; height: 120px; }

.italic-accent {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
}

.eyebrow {
  font-size: 13px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 14px;
  display: block;
}

/* Top-only padding: adjacent sections used to each add their own top+bottom
   padding, so the gap at a section boundary was double the gap after a
   hero (which only contributes one section's top padding). Zeroing the
   bottom means every boundary's gap is set by a single value: the padding
   of whichever section comes next.
   The last section on a page has no "next section" to borrow a gap from,
   and the footer's own top padding doesn't read as a visible gap (its
   dark background fills that space right up to its own edge), so it gets
   its bottom padding back explicitly here. */
.section { padding: clamp(48px, 6vw, 88px) 0 0; }
.section--tight { padding: clamp(32px, 4vw, 56px) 0 0; }
main > .section:last-child { padding-bottom: clamp(48px, 6vw, 88px); }
main > .section--tight:last-child { padding-bottom: clamp(32px, 4vw, 56px); }
/* Unlike a plain .section, these have their own visibly distinct
   background, so they can't borrow breathing room from whatever comes
   next; the boundary is a real colour seam, so they need their own
   bottom padding regardless of position on the page. */
.section--dark, .section--soft { padding-bottom: clamp(48px, 6vw, 88px); }
.section--dark { background: var(--surface-dark); color: var(--paper); }
.section--dark p { color: #b7bbc2; }
.section--soft { background: #ffffff; }
/* A plain section's content can sit flush against its own bottom edge
   (no visible seam there normally), but if a distinctly-coloured section
   comes right after, that edge IS a real colour seam, so the plain
   section needs its own trailing space too, not just rely on the
   coloured section's top padding (which reads as "inside the new
   colour", not as a gap after the previous content). */
.section:has(+ .section--soft), .section:has(+ .section--dark),
.hero:has(+ .section--soft), .hero:has(+ .section--dark) {
  padding-bottom: clamp(48px, 6vw, 88px);
}
.section--tight:has(+ .section--soft), .section--tight:has(+ .section--dark) {
  padding-bottom: clamp(32px, 4vw, 56px);
}

.text-center { text-align: center; }

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 14px 30px;
  border-radius: 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  border: 1px solid var(--ink);
  cursor: pointer;
  transition: background .2s ease, color .2s ease, transform .2s ease;
  background: var(--ink);
  color: var(--paper);
}
.btn:hover { transform: translateY(-2px); }
.btn--outline { background: transparent; color: var(--ink); }
.btn--outline:hover { background: var(--ink); color: var(--paper); }
/* --ink/--paper invert in dark mode (dark theme block near the top of this
   file), so this rule alone would fill outline buttons white on hover
   instead of dark, pin it to fixed values so dark mode keeps the same
   solid-dark-fill look light mode already has. */
[data-theme="dark"] .btn--outline:hover { background: #0f0f0f; color: #fff; }
.section--dark .btn--outline { border-color: var(--paper); color: var(--paper); }
.section--dark .btn--outline:hover { background: var(--paper); color: var(--ink); }

/* Hero "Explore Our Process" button: always an orange accent on
   hover/touch, regardless of scroll position. */
.btn-explore {
  transition: background .2s ease, color .2s ease, border-color .2s ease, transform .2s ease;
}
.btn-explore:hover { background: rgb(231,139,28); border-color: rgb(231,139,28); color: #fff; }

/* ==========================================================================
   Header / Nav
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: #ffffff;
  border-bottom: 1px solid var(--line);
  transition: background .25s ease, border-color .25s ease;
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 72px;
}
.site-header .logo img { height: 30px; width: auto; transition: transform .2s ease; transform-origin: left center; }
.site-header .logo:hover img { transform: scale(1.07); }

/* Homepage only: header starts transparent, overlaid on the hero image,
   and only becomes a solid bar once the user scrolls past it. */
body.has-transparent-header .site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  background: transparent;
  border-bottom-color: transparent;
}
body.has-transparent-header .site-header.is-scrolled {
  background: #ffffff;
  border-bottom-color: var(--line);
}

.main-nav { display: flex; align-items: center; gap: 40px; }
.main-nav ul { list-style: none; display: flex; gap: 32px; margin: 0; padding: 0; }
.main-nav a {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  position: relative;
}
.main-nav a::after {
  content: '';
  position: absolute;
  left: 0; bottom: -6px;
  width: 0; height: 1px;
  background: var(--ink);
  transition: width .2s ease;
}
.main-nav a:hover::after, .main-nav a.is-active::after { width: 100%; }
.main-nav .btn { padding: 11px 24px; }

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
}
.nav-toggle span { width: 24px; height: 2px; background: var(--ink); }

@media (max-width: 900px) {
  .nav-toggle { display: flex; }
  .main-nav {
    position: fixed;
    inset: 73px 0 0 0;
    background: var(--paper);
    flex-direction: column;
    align-items: flex-start;
    padding: 32px var(--gutter);
    transform: translateX(100%);
    transition: transform .3s ease;
    overflow-y: auto;
  }
  .main-nav.is-open { transform: translateX(0); }
  .main-nav ul { flex-direction: column; gap: 22px; }
  .main-nav a { font-size: 20px; }
}

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  /* Bottom padding intentionally 0, see .section comment above: the gap
     below this hero comes from the next section's own top padding. */
  padding: clamp(70px, 12vw, 140px) 0 0;
  text-align: center;
}
.hero h1 {
  font-size: clamp(32px, 6vw, 68px);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 24px;
}
.hero h1 .sep { color: var(--muted); font-weight: 300; padding: 0 .25em; }
.hero .sub {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(18px, 2.4vw, 26px);
  color: var(--muted);
  max-width: 640px;
  margin: 0 auto 36px;
}
.hero .hero-actions { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; margin-top: 24px; }
@media (max-width: 480px) { .hero .hero-actions { flex-direction: column; align-items: stretch; } .hero .hero-actions .btn { justify-content: center; } }

/* ==========================================================================
   Project showcase grid, image card + separate caption strip below,
   matching the home page's small-ratio (3:4) / wide-ratio (16:9) system.
   ========================================================================== */
.project-grid { display: flex; flex-direction: column; gap: 28px; }
.project-row { display: flex; align-items: start; gap: 28px; }
.project-card {
  display: block;
  overflow: hidden;
  border-radius: 13px;
  background: #000;
  text-decoration: none;
  transition: transform .3s ease;
}
/* One portrait + one landscape per row: give the portrait card roughly a
   third of the row so its 3:4 media lines up in height with the 16:9
   landscape card taking the rest. */
.project-card.portrait { flex: 0 0 31%; }
.project-card.landscape { flex: 1 1 auto; }
.project-card:hover { transform: translateY(-4px) translateZ(0); }
.project-card-media {
  position: relative; width: 100%; height: 380px;
  background: #0d0d0f;
  display: flex; align-items: center; justify-content: center;
  /* The hover-scaled img/video below gets promoted to its own compositing
     layer; without a matching clip here, a hairline of that layer's edge
     can peek past the outer card's rounded corner. Only the top corners
     touch the card's own rounded edge, so only round those (the bottom
     edge is an internal seam against the caption and should stay square).
     transform: translateZ(0) forces this clipping container onto its own
     layer too, so the rounded mask and the scaled child are rasterised
     together instead of independently, removing a hairline seam Chromium
     otherwise leaves at the corners. */
  border-radius: 13px 13px 0 0; overflow: hidden;
  transform: translateZ(0);
}
.project-card-media img, .project-card-media video {
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .5s ease;
}
.project-card:hover .project-card-media img,
.project-card:hover .project-card-media video { transform: scale(1.04); }
.project-card-caption {
  padding: 14px 18px; background: #000; height: 90px;
  display: flex; flex-direction: column; justify-content: flex-start;
  overflow: hidden;
}
.project-card-caption .label {
  display: block; font-size: 12px; font-weight: 600; letter-spacing: .04em;
  color: #fff; margin-bottom: 5px;
}
.project-card-caption p { color: rgba(255,255,255,.5); font-size: 13px; line-height: 1.4; margin: 0; }
@media (max-width: 700px) {
  .project-grid { gap: 20px; }
  .project-row { flex-direction: column; gap: 20px; }
  .project-card.portrait, .project-card.landscape { flex: 0 0 auto; width: 100%; }
  .project-card-media { height: 300px; }
}

/* One-row-at-a-time slider (Contact page): holds each .project-row full
   width in a horizontal track that slides over to the next row on a timer
   (see main.js), instead of stacking every row on the page at once. */
.project-row-slider { overflow: hidden; }
.project-row-track { display: flex; transition: transform 1.1s cubic-bezier(.45,0,.2,1); }
.project-row-track.is-snapping { transition: none; }
.project-row-track .project-row { flex: 0 0 100%; min-width: 100%; }

/* ==========================================================================
   Discipline cards (Expertise page), landscape image with title overlay,
   stacked vertically one per row, dark caption strip below each.
   ========================================================================== */
.discipline-stack { display: flex; flex-direction: column; gap: 32px; }
.discipline-card {
  display: block; border-radius: 11px; overflow: hidden; background: #000;
  scroll-margin-top: 90px; transition: transform .3s ease;
  transform: translateZ(0);
}
.discipline-card:hover { transform: translateY(-4px) translateZ(0); }
.discipline-media { position: relative; width: 100%; aspect-ratio: 2.69 / 1; background: #0d0d0f; overflow: hidden; }
.discipline-media img {
  width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .5s ease;
}
.discipline-card:hover .discipline-media img { transform: scale(1.04); }
.discipline-caption { padding: 19px 31px 22px; background: #000; }
.discipline-caption .discipline-name {
  display: block; font-size: 11px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .08em; color: rgba(255,255,255,.5); margin-bottom: 7px;
}
.discipline-caption h3 {
  color: #fff; font-size: clamp(14.5px, 1.7vw, 18px); text-transform: uppercase;
  letter-spacing: .03em; margin-bottom: 9px;
}
.discipline-caption p { color: rgba(255,255,255,.6); font-size: 13px; line-height: 1.65; margin: 0; }
@media (max-width: 700px) {
  .discipline-stack { gap: 22px; }
  .discipline-media { aspect-ratio: 1.57 / 1; }
  .discipline-caption { padding: 15px 19px 19px; }
}

/* ==========================================================================
   Testimonials
   ========================================================================== */
.testimonial-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px;
}
.testimonial-card {
  padding: 32px;
  background: var(--paper-soft);
  border-radius: var(--radius);
}
.testimonial-card p { color: var(--ink); font-size: 16px; }
.testimonial-card .who {
  display: flex; align-items: center; gap: 12px; margin-top: 20px;
}
.testimonial-card .who img { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; }
.testimonial-card .who strong { font-size: 14px; display: block; }
.testimonial-card .who span { font-size: 13px; color: var(--muted); }
@media (max-width: 900px) { .testimonial-grid { grid-template-columns: 1fr; } }

/* Single-card testimonial rotator (Contact page): cycles one card at a
   time via JS (see main.js), swapping every 5s. */
.testimonial-rotator { position: relative; margin-top: 12px; }
.testimonial-rotator .testimonial-card { display: none; }
.testimonial-rotator .testimonial-card.is-active { display: block; animation: testimonial-rotator-fade .5s ease; }
@keyframes testimonial-rotator-fade {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ==========================================================================
   Process timeline, alternating left/right steps along a central line
   ========================================================================== */
.process-timeline { display: flex; flex-direction: column; }
.process-row { display: grid; grid-template-columns: 1fr 60px 1fr; gap: 40px; }
.process-node { position: relative; display: flex; justify-content: center; }
.process-node::before {
  content: ''; position: absolute; top: 0; bottom: -72px; left: 50%;
  width: 1px; background: var(--line); transform: translateX(-50%);
}
.process-row:last-child .process-node::before { display: none; }
.process-node span {
  position: relative; z-index: 1; flex-shrink: 0;
  width: 34px; height: 34px; border-radius: 50%;
  background: var(--paper); border: 1px solid var(--ink);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 600;
}
.process-content img {
  width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
  border-radius: var(--radius); margin-bottom: 20px; display: block;
}
.process-content h3 { font-size: 20px; text-transform: uppercase; margin-bottom: 4px; }
.process-content .process-tagline { display: block; color: var(--muted); font-size: 14px; margin-bottom: 16px; }
.process-content p { margin-bottom: 14px; }
.process-content p:last-child { margin-bottom: 0; }
.process-content--right { text-align: left; }
@media (max-width: 800px) {
  .process-row { grid-template-columns: 34px 1fr; column-gap: 20px; row-gap: 0; padding-bottom: 40px; }
  .process-node { grid-column: 1; grid-row: 1; }
  .process-node::before { bottom: -40px; }
  .process-content--left, .process-content--right { grid-column: 2; grid-row: 1; }
}

/* ==========================================================================
   Forms
   ========================================================================== */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.form-field { display: flex; flex-direction: column; gap: 8px; }
.form-field.full { grid-column: 1 / -1; }
.form-field label { font-size: 13px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase; }
.form-field input, .form-field select, .form-field textarea {
  font-family: var(--font-sans);
  font-size: 15px;
  padding: 13px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink);
  width: 100%;
  box-sizing: border-box;
}
/* Browsers default textareas to resize: both, which lets a visitor drag
   #message wider than its grid column and overlap the column next to it
   (e.g. the testimonials on the Contact page). Only vertical resizing
   makes sense here since the field's width is fixed by the grid. */
.form-field textarea { resize: vertical; }
.form-field input:focus, .form-field select:focus, .form-field textarea:focus {
  outline: none; border-color: var(--ink);
}
.form-note { font-size: 13px; color: var(--muted); margin-top: 14px; }
.consent-check { display: flex; align-items: flex-start; gap: 10px; margin-top: 20px; font-size: 13px; color: var(--muted); cursor: pointer; }
.consent-check input { margin-top: 3px; flex-shrink: 0; }
.consent-check a { text-decoration: underline; color: inherit; }
.form-status { margin-top: 16px; font-size: 14px; display: none; }
.form-status.is-visible { display: block; }
.form-status.success { color: #157347; }
.form-status.error { color: #b42318; }

@media (max-width: 700px) { .form-grid { grid-template-columns: 1fr; } }

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  background: var(--surface-dark);
  color: #d7d7d7;
  padding: 64px 0 28px;
}
.footer-top {
  display: flex;
  justify-content: space-between;
  gap: 40px;
  flex-wrap: wrap;
  padding-bottom: 40px;
  border-bottom: 1px solid rgba(255,255,255,.12);
}
.footer-brand img { height: 30px; margin-bottom: 14px; }
.footer-brand p { max-width: 320px; color: #9a9ea6; }
.footer-cols { display: flex; gap: 64px; flex-wrap: wrap; }
.footer-col h4 {
  color: #fff; font-size: 13px; text-transform: uppercase; letter-spacing: .08em; margin-bottom: 16px;
}
.footer-col a { display: block; color: #9a9ea6; font-size: 14px; margin-bottom: 10px; }
.footer-col a:hover { color: #fff; }
.footer-social { display: flex; gap: 14px; margin-top: 16px; }
.footer-social a {
  width: 36px; height: 36px; border-radius: 6px;
  border: 1px solid rgba(255,255,255,.25);
  display: flex; align-items: center; justify-content: center;
  font-size: 14px;
}
.footer-social a:hover { background: #fff; color: var(--ink); }
.footer-bottom {
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px;
  padding-top: 22px; font-size: 13px; color: #7d818a;
}
.footer-bottom a { color: #9a9ea6; }
.footer-legal-links { display: flex; gap: 20px; }

/* ==========================================================================
   Back to top
   ========================================================================== */
.back-to-top {
  position: fixed; right: 24px; bottom: 24px; z-index: 95;
  width: 56px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: #fff;
  border: 1px solid var(--ink); border-radius: 8px;
  cursor: pointer;
  opacity: 0; visibility: hidden; transform: translateY(10px);
  transition: opacity .25s ease, transform .25s ease, visibility .25s, background .2s ease, color .2s ease;
}
.back-to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.back-to-top:hover { background: #fff; color: var(--ink); }

/* ==========================================================================
   Cookie consent
   ========================================================================== */
.cookie-banner {
  position: fixed; left: 20px; right: 20px; bottom: 20px;
  max-width: 560px;
  margin: 0 auto;
  background: var(--ink);
  color: #fff;
  padding: 22px 26px;
  border-radius: 10px;
  display: none;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  z-index: 999;
  box-shadow: 0 10px 40px rgba(0,0,0,.25);
}
.cookie-banner.is-visible { display: flex; flex-wrap: wrap; }
.cookie-banner p { color: #d7d7d7; font-size: 13px; margin: 0; flex: 1 1 260px; }
.cookie-banner .actions { display: flex; gap: 10px; }
.cookie-banner button {
  border-radius: 8px; padding: 9px 18px; font-size: 12px; font-weight: 600;
  text-transform: uppercase; cursor: pointer; border: 1px solid #fff;
}
.cookie-btn-accept { background: #fff; color: var(--ink); }
.cookie-btn-decline { background: transparent; color: #fff; }

/* ==========================================================================
   Misc utility
   ========================================================================== */
.badge-row { display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }
.badge-row img { height: 54px; width: auto; filter: grayscale(1); opacity: .8; }
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 60px; align-items: center; }
.two-col--text-lead { grid-template-columns: 1.5fr 1fr; }
.two-col--img-lead { grid-template-columns: 1fr 1.5fr; }
@media (max-width: 900px) { .two-col, .two-col--text-lead, .two-col--img-lead { grid-template-columns: 1fr; } }
.beliefs-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; }
@media (max-width: 700px) { .beliefs-grid { grid-template-columns: 1fr; } }
.belief-item { padding: 28px 0; border-top: 1px solid var(--line); }
.tag-list { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
.tag { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; padding: 6px 14px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); }
.article-card { padding: 28px 0; border-bottom: 1px solid var(--line); display: grid; grid-template-columns: 1fr 2fr; gap: 28px; }
.article-card h3 { font-size: 20px; margin-bottom: 8px; }
.article-card .eyebrow { margin-bottom: 8px; }
@media (max-width: 700px) { .article-card { grid-template-columns: 1fr; } }
.notice-box { border: 1px dashed #c9c9c9; background: #fffdf6; padding: 18px 22px; border-radius: var(--radius); font-size: 14px; color: #7a6a2f; margin: 20px 0; }

/* ==========================================================================
   Synthesis article cards, portrait cards, same visual language as the
   Projects page (image top, dark caption below).
   ========================================================================== */
.synthesis-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; }
.synthesis-card {
  display: block; text-decoration: none; border-radius: 13px; overflow: hidden;
  background: #000; transition: transform .3s ease;
  transform: translateZ(0);
}
.synthesis-card:hover { transform: translateY(-4px) translateZ(0); }
.synthesis-card.is-coming-soon { opacity: .55; pointer-events: none; }
.synthesis-card-media { position: relative; width: 100%; aspect-ratio: 3 / 4; background: #0d0d0f; }
.synthesis-card-media img {
  width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .5s ease;
}
.synthesis-card:hover .synthesis-card-media img { transform: scale(1.04); }
.synthesis-card-caption { padding: 20px 24px 24px; background: #000; }
.synthesis-card-caption .label {
  display: block; font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: rgba(255,255,255,.5); margin-bottom: 10px;
}
.synthesis-card-caption h3 { color: #fff; font-size: 17px; line-height: 1.3; margin-bottom: 10px; }
.synthesis-card-caption p { color: rgba(255,255,255,.6); font-size: 14px; line-height: 1.6; margin: 0; }
@media (max-width: 900px) { .synthesis-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .synthesis-grid { grid-template-columns: 1fr; } }

/* Long-form article/case-study body copy: darker than the default muted
   gray used for captions, since it's read start to finish, not skimmed. */
.prose p { color: var(--ink); font-size: 17px; line-height: 1.75; }
.prose h3 { margin-top: 1.6em; font-size: 21px; }
/* .prose's dark ink color otherwise wins a specificity tie against
   .section--dark p (same specificity, .prose declared later), which made
   body copy nearly invisible against a dark background. */
.section--dark .prose p { color: #b7bbc2; }

/* ==========================================================================
   Homepage hero banner, matches live site's .banner-wrap exactly
   ========================================================================== */
.hero-banner { position: relative; width: 100%; height: 100vh; overflow: hidden; background: #ddd; }
/* Dynamic viewport height where supported: mobile browsers resize their
   address bar as you scroll, which makes a plain 100vh hero jump/resize
   awkwardly on load. 100dvh tracks the actual visible area instead. */
@supports (height: 100dvh) { .hero-banner { height: 100dvh; } }
.hero-banner img { width: 100%; height: 100%; object-fit: cover; object-position: center bottom; position: absolute; top: 0; left: 0; }
/* Without this, dragging a finger across the hero to play with the colour
   reveal fights with the browser's own default touch gestures (edge-swipe
   back/forward navigation, horizontal pan), which is what made the whole
   page visibly shift left/right on a phone. pan-y keeps normal vertical
   scrolling working, it just stops the browser treating the drag itself
   as a navigation/pan gesture. */
.hero-banner { touch-action: pan-y; }
.hero-banner #hero-canvas { width: 100%; height: 100%; position: absolute; top: 0; left: 0; display: block; cursor: pointer; touch-action: pan-y; }

/* A visible marker for the colour-reveal position on touch devices, since
   there's no mouse cursor to show where it is (this matters most during
   the auto-sweep, when nothing is actually touching the screen). Hidden
   entirely on devices that have a real hover-capable pointer, where the
   cursor itself already does this job. main.js moves it every frame. */
#hero-touch-cursor {
  display: none;
  position: absolute; top: -27px; left: -27px; z-index: 3;
  width: 54px; height: 54px;
  border-radius: 50%; pointer-events: none;
  border: 2px solid rgba(255,255,255,.85);
  box-shadow: 0 0 22px rgba(255,255,255,.55), inset 0 0 14px rgba(255,255,255,.25);
  opacity: 0; transition: opacity .3s ease;
  will-change: transform;
  transform: translate(-1000px, -1000px);
}
#hero-touch-cursor.is-visible { opacity: 1; }
@media (hover: none), (pointer: coarse) {
  #hero-touch-cursor { display: block; }
}
.hero-banner .banner-content {
  position: relative; z-index: 2; height: 100%;
  display: flex; align-items: center; justify-content: center;
  text-align: center; color: #000; padding: 20px;
}
.hero-banner .banner-content .inner { max-width: 800px; transform: translateY(-24px); }
.hero-banner .eyebrow { justify-content: center; color: #000; }
.hero-banner h1 { font-size: 45px; font-weight: 700; margin-bottom: 15px; text-transform: uppercase; letter-spacing: .02em; }
.hero-banner h1 .sep { color: #444; font-weight: 300; padding: 0 .2em; }
.hero-banner p { font-size: 16px; line-height: 20px; margin: 0; font-family: var(--font-sans); font-style: normal; font-weight: 400; color: #000; }
.hero-banner .hero-actions { display: flex; gap: 14px; justify-content: center; margin-top: 28px; }
/* Full-screen hero at every size, including mobile, the image always
   fills the viewport rather than being boxed into a shorter aspect ratio. */
@media (max-width: 1024px) { .hero-banner h1 { font-size: 36px; } .hero-banner p { font-size: 14px; } }
@media (max-width: 768px)  { .hero-banner h1 { font-size: 28px; } .hero-banner p { font-size: 13px; } .hero-banner .hero-actions { flex-direction: column; align-items: center; margin-top: 20px; } }
@media (max-width: 480px)  { .hero-banner h1 { font-size: 22px; } .hero-banner p { font-size: 12px; } }

/* ==========================================================================
   Projects masonry grid (lv-grid), matches live site exactly
   ========================================================================== */
.lv-grid { display: grid; grid-template-columns: 1fr 1.185fr 1.185fr 1fr; gap: 22px; align-items: stretch; }
.lv-item.item-1 { grid-column: 1; }
.lv-item.item-2 { grid-column: 2 / 4; }
.lv-item.item-3 { grid-column: 4; }
.lv-item.item-4 { grid-column: 1 / 3; }
.lv-item.item-5 { grid-column: 3 / 5; }
.lv-item.item-7 { grid-column: 1; }
.lv-item.item-8 { grid-column: 2 / 4; }
.lv-item.item-9 { grid-column: 4; }
.lv-card { position: relative; display: block; width: 100%; height: 100%; overflow: hidden; background: #111; text-decoration: none; transform: translateZ(0); }
.lv-card.small-ratio { aspect-ratio: 3 / 4; }
.lv-card.wide-ratio { aspect-ratio: 16 / 9; }
.lv-card img, .lv-card video { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .6s ease, filter .3s ease; }
.lv-card::before { content: ''; position: absolute; inset: 0; background: rgba(0,0,0,.35); opacity: 0; transition: .3s; z-index: 1; }
.lv-overlay { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-40%); text-align: center; opacity: 0; transition: .3s; z-index: 2; width: 100%; }
.lv-overlay h2 { color: #fff; font-size: clamp(20px, 3vw, 40px); margin: 0; text-transform: uppercase; }
.lv-overlay p { color: #fff; font-size: 16px; margin-top: 6px; }
.lv-card:hover::before, .lv-card:hover .lv-overlay { opacity: 1; }
.lv-card:hover .lv-overlay { transform: translate(-50%,-50%); }
.lv-card:hover img, .lv-card:hover video { transform: scale(1.05); filter: brightness(.7); }
@media (max-width: 1024px) { .lv-grid { gap: 14px; } }
@media (max-width: 767px) {
  .lv-grid { grid-template-columns: 1fr; gap: 20px; }
  .lv-item { grid-column: 1 !important; }
}

/* ==========================================================================
   Expertise service table (Service / Features / 3D Illustration)
   ========================================================================== */
.service-table-head {
  display: grid; grid-template-columns: 1fr 1.3fr 90px; gap: 20px;
  padding-bottom: 16px; margin-bottom: 20px; border-bottom: 1px solid var(--line);
  font-size: 15px; color: var(--muted);
}
.service-table-head span:last-child { justify-self: start; transform: translateX(-100px); }
.service-row {
  display: grid; grid-template-columns: 1fr 1.3fr 90px; gap: 20px;
  padding: 40px 32px; margin: 0 -32px; align-items: center;
  border-bottom: 1px solid var(--line);
  border-radius: var(--radius);
  background: transparent;
  transition: background .2s ease, border-color .2s ease;
}
.service-row:hover { background: #f0f0f0; border-bottom-color: transparent; }
.service-row h3 { font-size: 20px; margin: 0; }
.service-row ul { list-style: none; margin: 0; padding: 0; color: var(--muted); font-size: 14px; line-height: 2; }
.service-row img {
  width: 95px; height: 95px; object-fit: contain; justify-self: start;
  transform: translateX(-100px);
}
.service-row:hover img { animation: icon-float 1.1s ease-in-out infinite; }
/* Touch devices: main.js toggles this class on tap for one reliable,
   complete play-through instead of depending on :hover persistence. */
.service-row img.is-floating { animation: icon-float 1.1s ease-in-out; }
@keyframes icon-float {
  0%, 100% { transform: translateX(-100px) translateY(0); }
  50% { transform: translateX(-100px) translateY(-12px); }
}
@media (max-width: 800px) {
  .service-table-head { display: none; }
  .service-row { grid-template-columns: 1fr; gap: 12px; padding: 26px 24px; margin: 0 -24px; }
  .service-row img { justify-self: start; transform: none; }
}
/* Disable the hover-triggered float on any touch-primary device (not just
   narrow ones, an iPad in portrait is already wider than the 800px
   breakpoint above). A tap simulates :hover once but iOS doesn't fire a
   matching "unhover" the way a mouse does, so the infinite animation can
   get stuck mid-cycle or only appear to "play once." Below, main.js
   retriggers the same float deliberately and reliably on tap instead. */
@media (hover: none), (pointer: coarse) {
  .service-row:hover img { animation: none; }
}

/* ==========================================================================
   Testimonial carousel (horizontal scroll, matches live swiper behaviour)
   ========================================================================== */
/* Fade the left/right edges with solid overlay gradients rather than
   CSS mask-image: iOS Safari has a known bug where a masked element
   animating for an extended period can lose its mask and render fully
   blank (observed on iPad). Overlay gradients achieve the same look
   without relying on masking at all. */
.testimonial-scroll { position: relative; overflow: hidden; }
.testimonial-scroll::before, .testimonial-scroll::after {
  content: ''; position: absolute; top: 0; bottom: 0; width: 64px; z-index: 2; pointer-events: none;
}
.testimonial-scroll::before { left: 0; background: linear-gradient(90deg, var(--paper), rgba(255,255,255,0)); }
.testimonial-scroll::after { right: 0; background: linear-gradient(270deg, var(--paper), rgba(255,255,255,0)); }
.testimonial-track {
  display: flex; align-items: stretch; gap: 20px; width: max-content;
  will-change: transform;
}
.testimonial-scroll .testimonial-card {
  flex: 0 0 270px; background: #fcfcfc;
  display: flex; flex-direction: column;
}
.testimonial-scroll .testimonial-card .who { margin-top: auto; padding-top: 20px; }
.stars { color: #000; font-size: 14px; letter-spacing: 2px; margin-bottom: 14px; }

/* ==========================================================================
   Final split CTA (dark, text left / video right)
   ========================================================================== */
.cta-split {
  display: grid; grid-template-columns: 1.5fr 1fr; grid-template-rows: 100%; align-items: stretch;
  background: #000; color: var(--paper);
  border-radius: 16px; overflow: hidden;
  aspect-ratio: 3.2 / 1;
  width: 90%; margin: 0 auto;
}
.cta-split p { color: #b7bbc2; margin-bottom: 14px; }
.cta-split .eyebrow { margin-bottom: 8px; }
.cta-split .cta-text { padding: 28px 48px; align-self: center; }
.cta-split .cta-text h2 { margin-bottom: 10px; }
.cta-split .cta-text .btn { padding: 10px 22px; font-size: 12px; }
.cta-split .cta-buttons { display: flex; gap: 12px; flex-wrap: wrap; transform: translateY(-6px); }
.cta-split .btn--outline { border-color: #fff; color: #fff; }
.cta-split .btn--outline:hover { background: #fff; color: #0f0f0f; }
.cta-split .cta-text .btn:not(.btn--outline):hover { background: #fff; color: #0f0f0f; border-color: #fff; }
.cta-split video { width: 100%; height: 100%; margin: auto; object-fit: contain; object-position: 50% 30%; display: block; }
.cta-split .btn span { display: inline-block; transition: transform .2s ease; }
.cta-split .btn:hover span { transform: translate(2px, -2px); }
.cta-split .btn span svg { display: block; }
@media (max-width: 900px) {
  .cta-split {
    display: flex; flex-direction: column;
    border-radius: 12px; aspect-ratio: auto; width: 100%;
  }
  .cta-split .cta-text { padding: 48px 32px; align-self: stretch; }
  .cta-split video { width: 100%; height: auto; aspect-ratio: 16 / 9; margin: 0; }
}

/* ==========================================================================
   FAQ accordion
   ========================================================================== */
.faq-accordion { border: 1px solid var(--line); border-radius: var(--radius); }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item:last-child { border-bottom: none; }
.faq-question {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  gap: 20px; background: none; border: none; cursor: pointer; text-align: left;
  padding: 28px 32px; font-size: 19px; font-family: var(--font-sans); color: var(--ink);
}
.faq-icon { position: relative; width: 16px; height: 16px; flex-shrink: 0; }
.faq-icon::before, .faq-icon::after {
  content: ''; position: absolute; background: var(--ink); border-radius: 2px;
}
.faq-icon::before { top: 50%; left: 0; width: 100%; height: 2px; transform: translateY(-50%); }
.faq-icon::after {
  top: 0; left: 50%; width: 2px; height: 100%; transform: translateX(-50%);
  transition: transform .2s ease, opacity .2s ease;
}
.faq-item.is-open .faq-icon::after { opacity: 0; transform: translateX(-50%) rotate(90deg); }
.faq-answer { max-height: 0; overflow: hidden; padding: 0 32px; transition: max-height .3s ease, padding .3s ease; }
.faq-item.is-open .faq-answer { max-height: 400px; padding: 0 32px 28px; }
.faq-answer p { color: var(--muted); font-size: 16px; line-height: 1.7; margin: 0; }
@media (max-width: 700px) {
  .faq-question { padding: 20px 22px; font-size: 16px; }
  .faq-item.is-open .faq-answer { padding: 0 22px 20px; }
  .faq-answer { padding: 0 22px; }
}

/* ==========================================================================
   Stats bar (Studio page)
   ========================================================================== */
.stats-bar {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: 13px; overflow: hidden;
}
.stat-item { background: var(--paper-soft); padding: 34px 26px; text-align: center; }
.stat-number {
  display: block; font-size: clamp(30px, 3.6vw, 42px); font-weight: 700;
  line-height: 1; margin-bottom: 12px; letter-spacing: -0.01em;
}
.stat-label { display: block; font-size: 14.5px; font-weight: 600; color: var(--ink); margin-bottom: 6px; }
.stat-sub { display: block; font-size: 12.5px; color: var(--muted); line-height: 1.45; }
@media (max-width: 800px) { .stats-bar { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) {
  .stats-bar { grid-template-columns: 1fr; }
  .stat-item { padding: 26px 22px; }
}

/* ==========================================================================
   Rotating image carousel, portrait 3:4, auto-crossfades between however
   many <img> tags are placed inside. Add/remove <img> children to change
   the rotation; no JS or CSS edits needed (see HOW-TO-CHANGE-IMAGES.md).
   ========================================================================== */
.img-carousel {
  position: relative; width: 100%; aspect-ratio: 3 / 4;
  border-radius: 13px; overflow: hidden; background: #0d0d0f;
  transition: transform .3s ease;
}
.img-carousel:hover { transform: translateY(-4px); }
.img-carousel img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 1.4s ease;
}
.img-carousel img.is-active { opacity: 1; }

/* ==========================================================================
   Scroll reveal, subtle fade + rise, once per element, respects
   prefers-reduced-motion (see main.js).
   ========================================================================== */
.reveal-on-scroll { opacity: 0; transform: translateY(28px); transition: opacity .7s ease, transform .7s ease; }
.reveal-on-scroll.is-visible { opacity: 1; transform: translateY(0); }
.reveal-on-scroll.reveal-delay-1 { transition-delay: .12s; }
.reveal-on-scroll.reveal-delay-2 { transition-delay: .24s; }

/* ==========================================================================
   Case study page (project detail pages), editorial two-act layout:
   full-bleed/contained image cadence, galleries, pull-quotes.
   ========================================================================== */
.cs-hero {
  position: relative; width: 100%; min-height: 68vh;
  display: flex; align-items: flex-end;
  background: #000; overflow: hidden;
}
.cs-hero img, .cs-hero video {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
}
.cs-hero::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.78), rgba(0,0,0,0) 58%);
}
.cs-hero-content { position: relative; z-index: 2; padding: 56px var(--gutter); color: #fff; width: 100%; }
.cs-hero-content .eyebrow { color: rgba(255,255,255,.7); }
.cs-hero-content h1 { font-size: clamp(36px,7vw,80px); margin-bottom: 10px; color: #fff; }
.cs-hero-content p { color: rgba(255,255,255,.78); font-size: 18px; margin: 0; }
@media (max-width: 700px) { .cs-hero { min-height: 52vh; } }

/* Break an element out to full viewport width from inside a centered
   .container, for the alternating full-bleed/contained image cadence. */
.cs-full-bleed { width: 100vw; position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw; }
.cs-full-bleed img, .cs-full-bleed video { width: 100%; display: block; max-height: 760px; object-fit: cover; }

.cs-figure { margin: 0; }
.cs-figure img, .cs-figure video { width: 100%; border-radius: 6px; display: block; }
.cs-figcaption { margin-top: 14px; font-size: 14px; color: var(--muted); text-align: center; }

.cs-gallery-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.cs-gallery-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 24px; }
.cs-gallery-3 img, .cs-gallery-2 img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 6px; display: block; }
@media (max-width: 800px) { .cs-gallery-3, .cs-gallery-2 { grid-template-columns: 1fr; } }

.cs-pull-quote {
  font-family: var(--font-serif); font-style: italic; color: var(--ink);
  font-size: clamp(20px, 2.6vw, 28px); line-height: 1.5;
  margin: 28px 0; padding-left: 24px; border-left: 3px solid var(--line);
}
.section--dark .cs-pull-quote { border-left-color: rgba(255,255,255,.25); color: #fff; }

.cs-stat { font-size: clamp(32px, 4vw, 48px); font-weight: 700; line-height: 1; margin-bottom: 14px; display: block; }

/* ==========================================================================
   404 page
   ========================================================================== */
.error-404-hero {
  position: relative; width: 100%; min-height: 100vh;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden; background: #d9d6d0;
}
.error-404-hero img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  /* Anchor to the bottom of the source image: any cropping needed to fill
     a taller/narrower viewport eats into the empty space above the
     products, never the products or their floor shadow. */
  object-position: center bottom;
}
.error-404-hero::after {
  content: ''; position: absolute; inset: 0; background: rgba(255,255,255,.15);
}
/* Below 768px the transparent header falls back to a normal solid,
   sticky bar (see body.has-transparent-header rules), which pushes page
   content down instead of overlaying it, so the hero has to give back
   that height or the page ends up taller than the viewport. */
@media (max-width: 768px) {
  .error-404-hero { min-height: calc(100vh - 73px); }
}

.error-404-content { position: relative; z-index: 2; text-align: center; }
.error-404-content h1 {
  font-size: clamp(26px, 4.4vw, 51px); text-transform: uppercase;
  letter-spacing: .01em; margin-bottom: 28px; color: var(--ink);
}

/* ==========================================================================
   Services page, "How We Work" engagement models (3-col, reuses the
   belief-item border-top rhythm at a narrower column count).
   ========================================================================== */
.engagement-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; }
.engagement-item { padding: 28px 0; border-top: 1px solid var(--line); }
.engagement-letter {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 50%; background: var(--ink); color: var(--paper);
  font-size: 13px; font-weight: 700; margin-bottom: 16px;
}
@media (max-width: 800px) { .engagement-grid { grid-template-columns: 1fr; } }

/* Service cards, flat/light card (no photography), unlike the dark
   photo-based .discipline-card used on the Expertise page. */
.service-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.service-card {
  display: flex; flex-direction: column;
  padding: 32px; background: var(--paper-soft); border-radius: var(--radius);
}
.service-code {
  font-size: 12px; font-weight: 700; letter-spacing: .08em; color: var(--muted); margin-bottom: 10px;
}
.service-card h3 { font-size: 19px; margin-bottom: 6px; }
.service-headline {
  font-family: var(--font-serif); font-style: italic; color: var(--ink); font-size: 15px; margin-bottom: 12px;
}
.service-desc { font-size: 14px; line-height: 1.6; margin-bottom: 18px; }
.service-deliverables { list-style: none; margin: 0 0 20px; padding: 0; color: var(--muted); font-size: 13px; line-height: 1.9; }
.service-deliverables li::before { content: '\2022  '; }
.service-price { margin-top: auto; font-size: 15px; font-weight: 700; color: var(--ink); }
@media (max-width: 900px) { .service-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .service-grid { grid-template-columns: 1fr; } }

/* Featured Product Redline / Audit block */
.redline-feature {
  display: grid; grid-template-columns: 1.1fr .9fr;
  background: var(--paper-soft); border-radius: 13px; overflow: hidden;
}
.redline-feature-text { padding: clamp(28px, 4vw, 48px); }
.redline-feature-text p { font-size: 15px; line-height: 1.65; }
.redline-meta {
  display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 13px; color: var(--muted);
  margin-bottom: 24px; padding-top: 18px; border-top: 1px solid var(--line);
}
.redline-checklist {
  list-style: none; margin: 0; padding: clamp(28px, 4vw, 48px); background: #f5f5f3;
  font-size: 14px; line-height: 1.5;
}
.redline-checklist li { padding: 12px 0; border-bottom: 1px solid var(--line); }
.redline-checklist li:last-child { border-bottom: none; }
.redline-checklist strong { display: block; margin-bottom: 3px; color: var(--ink); }
@media (max-width: 800px) { .redline-feature { grid-template-columns: 1fr; } }

/* ==========================================================================
   Instant-quote configurator
   ========================================================================== */
.configurator { display: grid; grid-template-columns: 1.4fr 1fr; gap: 40px; align-items: start; }
.configurator-steps { display: flex; flex-direction: column; gap: 36px; }
.config-fieldset { border: none; padding: 0; margin: 0; }
.config-fieldset legend {
  padding: 0; margin-bottom: 16px; font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
}
.config-optional { text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--muted); }

.config-options { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.config-options--radio { grid-template-columns: repeat(3, 1fr); }

/* Accessible checkbox/radio "card": the real input sits on top, fully
   transparent and covering the whole card, so keyboard/SR semantics and
   native focus/checked state stay intact, only the sibling span is styled. */
.config-option { position: relative; display: block; cursor: pointer; }
.config-option input {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0;
  opacity: 0; cursor: pointer; z-index: 1;
}
.config-option-card {
  display: block; padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 13.5px; line-height: 1.4; transition: border-color .2s ease, background .2s ease;
}
.config-option-card strong { display: block; font-size: 14px; margin-bottom: 3px; }
.config-option-meta { display: block; color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.config-option input:checked + .config-option-card { border-color: var(--ink); background: var(--paper-soft); }
.config-option input:focus-visible + .config-option-card { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 700px) { .config-options { grid-template-columns: 1fr 1fr; } .config-options--radio { grid-template-columns: 1fr; } }
@media (max-width: 460px) { .config-options { grid-template-columns: 1fr; } }

.config-toggle { display: flex; gap: 10px; margin-bottom: 16px; flex-wrap: wrap; }
.config-toggle label { position: relative; flex: 1 1 auto; cursor: pointer; }
.config-toggle input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 1; }
.config-toggle span {
  display: block; text-align: center; padding: 12px 18px; border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 13px; font-weight: 600; transition: border-color .2s ease, background .2s ease, color .2s ease;
}
.config-toggle input:checked + span { border-color: var(--ink); background: var(--ink); color: var(--paper); }
.config-toggle input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }
.config-rush { margin-top: 4px; }
.config-rush .config-option-card { font-size: 13.5px; }

.configurator-estimate {
  position: sticky; top: 100px;
  background: var(--surface-dark); color: var(--paper);
  border-radius: 13px; padding: clamp(24px, 3vw, 32px);
}
.estimate-empty { color: rgba(255,255,255,.6); font-size: 14px; margin: 0; }
.estimate-line {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 13.5px; padding: 9px 0; border-bottom: 1px solid rgba(255,255,255,.1);
}
.estimate-line span:last-child { flex-shrink: 0; color: rgba(255,255,255,.75); }
.estimate-total {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: clamp(20px, 2.4vw, 26px); font-weight: 700; padding-top: 18px; margin-top: 10px;
  border-top: 1px solid rgba(255,255,255,.25);
}
.estimate-timeline { font-size: 13px; color: rgba(255,255,255,.6); margin: 10px 0 0; }
.estimate-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 26px; }
.configurator-estimate .btn { width: 100%; justify-content: center; background: var(--paper); color: var(--ink); border-color: var(--paper); }
.configurator-estimate .btn:hover { background: rgb(231,139,28); border-color: rgb(231,139,28); color: #fff; }
.configurator-estimate .btn--outline { background: transparent; color: var(--paper); border-color: rgba(255,255,255,.4); }
.configurator-estimate .btn--outline:hover { background: rgba(255,255,255,.12); color: var(--paper); }
.estimate-note { font-size: 11.5px; color: rgba(255,255,255,.45); margin: 14px 0 0; line-height: 1.5; }
@media (max-width: 900px) {
  .configurator { grid-template-columns: 1fr; }
  .configurator-estimate { position: static; }
}

/* ==========================================================================
   Get-a-Quote wizard (quote.html), one question per screen, auto-advance
   on single-select, results screen with two conversion paths.
   ========================================================================== */
.quiz-wrap { padding: clamp(48px, 6vw, 88px) 0; min-height: 70vh; }
/* Widened from 640px so the results screen's 3-card pricing grid has
   room to breathe; the single-question steps just get a bit more side
   margin, which doesn't hurt their centered layout. */
.quiz-container { max-width: 780px; }

.quiz-step { display: none; }
.quiz-step.is-active { display: block; animation: quiz-step-in .35s ease; }
@media (prefers-reduced-motion: reduce) { .quiz-step.is-active { animation: none; } }
@keyframes quiz-step-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

.quiz-intro-sub {
  font-family: var(--font-serif); font-style: italic; font-size: clamp(16px, 2vw, 19px);
  color: var(--muted); max-width: 480px; margin: 0 0 28px;
}

.quiz-progress-wrap { margin-bottom: 40px; }
.quiz-progress-track { height: 4px; border-radius: 4px; background: var(--line); overflow: hidden; }
.quiz-progress-fill { height: 100%; background: var(--ink); border-radius: 4px; transition: width .35s ease; width: 0%; }
.quiz-step-counter { display: block; margin-top: 10px; font-size: 12.5px; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }

.quiz-question { font-size: clamp(21px, 3vw, 30px); margin-bottom: 10px; }
.quiz-hint { color: var(--muted); font-size: 14px; margin-bottom: 24px; }

.quiz-options { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 28px; }
.quiz-option { position: relative; display: block; cursor: pointer; }
.quiz-option input {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; z-index: 1;
}
.quiz-option-card {
  display: block; padding: 16px 20px; border: 1px solid var(--line); border-radius: 8px;
  font-size: 14.5px; font-weight: 600; line-height: 1.4;
  transition: border-color .2s ease, background .2s ease;
}
.quiz-option-detail { display: block; font-weight: 400; color: var(--muted); font-size: 12.5px; margin-top: 4px; }
.quiz-option input:checked + .quiz-option-card { border-color: var(--ink); background: var(--paper-soft); }
.quiz-option input:focus-visible + .quiz-option-card { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 560px) { .quiz-options { grid-template-columns: 1fr; } }

/* "Something else, tell us" free-text box revealed under the materials
   grid when its escape-hatch checkbox is ticked (see quote.js). */
.quiz-other-input-wrap { margin: -18px 0 28px; }
.quiz-other-input-wrap .quiz-text-input { margin-bottom: 0; }

/* commission.html's "Something Else / Not Listed" category: a featured
   block (not a small aside) since it's the primary path once none of the
   fixed categories fit, the textarea feeds straight into the custom
   quote's product-idea question. */
.other-category-cta {
  max-width: 640px; margin: 32px auto 0; padding: clamp(24px, 4vw, 40px);
  border: 1px solid var(--ink); border-radius: 13px; background: var(--paper-soft);
  text-align: center;
}
.other-category-lead { font-size: 14px; margin-bottom: 22px; }
.other-category-cta label { text-align: left; }
.other-category-cta .quiz-textarea { text-align: left; margin-bottom: 20px; }
.other-category-cta .btn { width: 100%; justify-content: center; }

.quiz-textarea, .quiz-text-input {
  display: block; width: 100%; font-family: var(--font-sans); font-size: 15px;
  padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--paper); color: var(--ink); margin-bottom: 28px;
}
.quiz-textarea { resize: vertical; }
.quiz-textarea:focus, .quiz-text-input:focus { outline: none; border-color: var(--ink); }

.quiz-nav { display: flex; align-items: center; gap: 20px; }
.quiz-back {
  background: none; border: none; padding: 0; cursor: pointer;
  font-size: 13px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--muted); transition: color .2s ease;
}
.quiz-back:hover { color: var(--ink); }
.quiz-nav .btn:disabled { opacity: .4; cursor: not-allowed; transform: none; }

.quiz-result-card {
  background: var(--surface-dark); color: var(--paper); border-radius: 13px;
  padding: clamp(28px, 4vw, 40px); text-align: center; margin: 28px 0;
}
.quiz-result-label { display: block; font-size: 13px; color: rgba(255,255,255,.6); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 10px; }
.quiz-result-price { font-size: clamp(30px, 5vw, 44px); font-weight: 700; }
.quiz-result-timeline { color: rgba(255,255,255,.65); font-size: 14px; margin: 10px 0 0; }

/* Subgrid so each row (title / description / price / note / button) lines
   up across all three cards, regardless of one card's description being
   longer than another's; a plain flex column per card can't do that,
   since each card's content stacks independently. */
.quiz-cta-grid {
  display: grid; grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: auto auto auto auto auto;
  gap: 16px; margin-bottom: 20px;
}
.quiz-cta-card {
  position: relative; padding: 22px 20px; border: 1px solid var(--line); border-radius: 13px;
  display: grid; grid-template-rows: subgrid; grid-row: span 5;
}
.quiz-cta-card h3 { font-size: 18px; margin-bottom: 10px; align-self: start; }
.quiz-cta-card p { font-size: 14px; margin-bottom: 18px; align-self: start; }
.quiz-cta-price { font-size: 22px; font-weight: 700; margin-bottom: 4px; align-self: start; }
.quiz-cta-credit-note { font-size: 12px; color: var(--muted); margin-bottom: 18px; align-self: start; }
.quiz-cta-card .btn {
  align-self: end; justify-content: center;
  padding: 14px 10px; font-size: 11.5px; letter-spacing: .02em;
  white-space: nowrap;
}
.quiz-cta-card--highlight { border-color: var(--ink); background: var(--paper-soft); }
.quiz-cta-badge {
  position: absolute; top: -12px; left: 24px; background: var(--ink); color: var(--paper);
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: 4px 12px; border-radius: 20px;
}
@media (max-width: 700px) {
  .quiz-cta-grid { grid-template-columns: 1fr; }
  .quiz-cta-card { grid-template-rows: unset; }
}

.quiz-result-note { font-size: 12.5px; color: var(--muted); line-height: 1.6; }
.quiz-result-status { font-size: 14px; margin-top: 12px; }
.quiz-result-status.error { color: #b42318; }
.quiz-legal-note { font-size: 12px; color: var(--muted); margin-top: 18px; }
.quiz-legal-note a { text-decoration: underline; }

/* ==========================================================================
   Category picker (categories.html), clickable product-category cards
   that filter the fixed-price service grid below them.
   ========================================================================== */
.category-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }
.category-card {
  display: block; width: 100%; padding: 18px 14px; border: 1px solid var(--line); border-radius: 8px;
  background: var(--paper); font-family: inherit; font-size: 14px; font-weight: 600; color: var(--ink);
  cursor: pointer; text-align: center; line-height: 1.3;
  transition: border-color .2s ease, background .2s ease, transform .2s ease;
}
.category-card:hover { transform: translateY(-2px); }
.category-card.is-active { border-color: var(--ink); background: var(--paper-soft); }
.category-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 900px) { .category-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 560px) { .category-grid { grid-template-columns: repeat(2, 1fr); } }

/* Extra "Get Started" CTA appended to each filtered .service-card (the
   card itself and its price/deliverables styling are shared with
   services.html, see .service-card, .service-price above). */
.service-card .btn { margin-top: 14px; width: 100%; justify-content: center; }
.service-card .btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }
.service-deposit-note { font-size: 11.5px; color: var(--muted); margin: 6px 0 0; line-height: 1.4; }
.service-card-status { font-size: 12.5px; margin: 10px 0 0; }
.service-card-status.error { color: #b42318; }
.service-grid-empty { color: var(--muted); text-align: center; grid-column: 1 / -1; }

/* ==========================================================================
   Hidden client previews (/previews/ passcode gate + one-time /{slug}
   links). Deliberately its own set of classes rather than reusing
   .project-grid/.project-card: those are built around the curated
   real-projects page's alternating portrait/landscape video pairs,
   this is a plain uniform grid of PDF cover thumbnails. */

.preview-gate-form {
  display: flex; gap: 12px; max-width: 420px; margin: 0 auto;
}
.preview-gate-form input {
  flex: 1; font-family: var(--font-sans); font-size: 15px;
  padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--paper); color: var(--ink);
}
.preview-gate-form input:focus { outline: none; border-color: var(--ink); }
.preview-gate-error { color: #b42318; text-align: center; margin-top: 16px; font-size: 14px; }

.preview-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 24px;
}
.preview-grid-status { color: var(--muted); text-align: center; grid-column: 1 / -1; padding: 40px 0; }

.preview-card {
  display: block; width: 100%; padding: 0; margin: 0; border: 0;
  font-family: inherit; text-align: left; cursor: pointer;
  overflow: hidden; border-radius: 13px; background: #000;
  transition: transform .3s ease;
}
.preview-card:hover { transform: translateY(-4px) translateZ(0); }
.preview-card-media {
  position: relative; width: 100%; aspect-ratio: 3 / 4;
  background: #0d0d0f; display: flex; align-items: center; justify-content: center;
  border-radius: 13px 13px 0 0; overflow: hidden; transform: translateZ(0);
}
.preview-card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s ease; }
.preview-card:hover .preview-card-media img { transform: scale(1.04); }
.preview-card-media-placeholder::before {
  content: 'PDF'; color: rgba(255,255,255,.35); font-size: 13px; font-weight: 600; letter-spacing: .06em;
}
.preview-card-caption {
  padding: 14px 18px; background: #000; min-height: 50px;
  display: flex; flex-direction: column; justify-content: center;
}
.preview-card-caption .label {
  display: block; font-size: 12px; font-weight: 600; letter-spacing: .04em; color: #fff;
}

.preview-flipbook-overlay {
  display: none; position: fixed; inset: 0; z-index: 1000;
  background: rgba(10,10,10,.94); align-items: center; justify-content: center;
}
.preview-flipbook-overlay.is-open { display: flex; }
body.preview-flipbook-open { overflow: hidden; }
/* Exact width/height are set in JS once the book's own page proportions
   are known (previews-gallery.js sizeFlipContainer), these are just a
   sane fallback before that runs. */
.preview-flipbook-container { width: 90vw; height: 85vh; max-width: 1300px; }
.preview-flipbook-status {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  color: rgba(255,255,255,.7); font-size: 14px; letter-spacing: .02em;
  text-align: center;
}
.preview-flipbook-status-text { margin-bottom: 14px; }
.preview-flipbook-progress {
  width: 240px; height: 4px; border-radius: 2px; overflow: hidden;
  background: rgba(255,255,255,.15);
}
.preview-flipbook-progress-bar {
  height: 100%; width: 0%; background: #fff; border-radius: 2px;
  transition: width .2s ease;
}
.preview-flipbook-close {
  position: absolute; top: 20px; right: 20px; width: 40px; height: 40px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 8px; border: 1px solid rgba(255,255,255,.3); background: transparent;
  color: #fff; font-size: 22px; line-height: 1; cursor: pointer;
  transition: background .2s ease;
}
.preview-flipbook-close:hover { background: rgba(255,255,255,.12); }
@media (max-width: 700px) {
  .preview-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 16px; }
  .preview-gate-form { flex-direction: column; }
}
