/* ==========================================================================
   TCDESIGN — Todd Crawford
   Hand-built design system. Replaces the 450KB Webflow cascade.
   Dark canvas by default, light via [data-theme="light"].
   ========================================================================== */

/* ---------- fonts (self-hosted, no third-party CDN) ---------------------- */
@font-face {
  font-family: 'Schibsted Grotesk';
  src: url('/fonts/schibsted-grotesk-var-latin.woff2') format('woff2-variations');
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Inconsolata';
  src: url('/fonts/inconsolata-var-latin.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- tokens ------------------------------------------------------- */
:root {
  --bg:        #0A0A0A;
  --surface:   #141414;
  --surface-2: #1C1C1C;
  --text:      #F5F5F3;
  --muted:     #8A8A85;
  --rule:      #262626;
  --accent:    #5FA4EC;
  --accent-ink:#0A0A0A;
  /* Todd's mark in its native colour, from his original Webflow SVG. Only the
     light canvas uses it; on the dark canvas the mark stays white (--text). */
  --brand:     #0288D1;

  --sans: 'Schibsted Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  --mono: 'Inconsolata', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* fluid type scale */
  --t-display: clamp(2.75rem, 7.2vw, 7rem);
  --t-h1:      clamp(2.25rem, 5.2vw, 4.5rem);
  --t-h2:      clamp(1.75rem, 3.2vw, 3rem);
  --t-h3:      clamp(1.25rem, 1.9vw, 1.75rem);
  --t-lead:    clamp(1.125rem, 1.6vw, 1.5rem);
  --t-body:    clamp(1rem, 1.05vw, 1.0625rem);
  --t-meta:    0.75rem;

  --rail: 220px;
  --gut: clamp(1.25rem, 4vw, 4rem);
  --measure: 64ch;

  --sec: clamp(5rem, 12vh, 10rem);   /* vertical section rhythm */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

[data-theme='light'] {
  --bg:        #FAFAF8;
  --surface:   #FFFFFF;
  --surface-2: #F1F1EE;
  --text:      #111111;
  --muted:     #6B6B66;
  --rule:      #E4E4E0;
  --accent:    #1F6FC4;   /* darkened for AA contrast on the light canvas */
  --accent-ink:#FFFFFF;
}

/* ---------- reset -------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
/* Lenis drives scrolling; native smooth would fight it */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-stopped { overflow: hidden; }

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  transition: background-color .4s var(--ease), color .4s var(--ease);
}

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

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; padding: 0; }

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

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

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

.skip-link {
  position: absolute; top: -100%; left: var(--gut); z-index: 200;
  background: var(--accent); color: var(--accent-ink);
  padding: .75rem 1.25rem; font-family: var(--mono);
  text-transform: uppercase; letter-spacing: .08em; font-size: var(--t-meta);
}
.skip-link:focus { top: 1rem; }

/* ---------- typography --------------------------------------------------- */
.display, h1, h2, h3 {
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 0.98;
  text-wrap: balance;
}
.display { font-size: var(--t-display); line-height: 0.95; letter-spacing: -0.04em; }
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); line-height: 1.15; letter-spacing: -0.02em; }

.lead {
  font-size: var(--t-lead);
  line-height: 1.4;
  letter-spacing: -0.015em;
  color: var(--text);
  max-width: 34ch;
}

.prose { max-width: var(--measure); }
.prose p + p { margin-top: 1.1em; }
.prose strong { font-weight: 600; }
.prose a { border-bottom: 1px solid var(--accent); }

.meta {
  font-family: var(--mono);
  font-size: var(--t-meta);
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--muted);
}

.muted { color: var(--muted); }

/* section label + rule */
.sec-head {
  display: flex; align-items: baseline; gap: 1.5rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--rule);
  margin-bottom: clamp(2rem, 5vh, 4rem);
}
.sec-head .rule-grow {
  flex: 1; height: 1px; background: var(--rule);
  transform-origin: left center;
}

/* ---------- layout ------------------------------------------------------- */
.shell { display: block; }

.wrap {
  max-width: 1240px;
  margin-inline: auto;
  padding-inline: var(--gut);
}

main { padding-bottom: var(--sec); }

section { scroll-margin-top: 6rem; }
.section { padding-block: var(--sec); }

/* ---------- rail nav ----------------------------------------------------- */
.rail {
  position: fixed;
  inset-block: 0;
  left: 0;
  width: var(--rail);
  padding: 2rem 0 2rem var(--gut);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  z-index: 90;
  pointer-events: none;
}
.rail > * { pointer-events: auto; }

.brand {
  font-weight: 700;
  font-size: 1.1rem;
  letter-spacing: -0.04em;
  display: inline-flex;
  align-items: center;
  gap: .5rem;
}
/* Todd's own TDC mark, inlined as SVG with fill="currentColor".
   Client request (2026-09-04): it is the brand blue on the light canvas and
   stays white on the dark one. Before this it inherited the theme ink, so it
   went black in light mode. --brand is the mark's own native colour, taken
   from his original Webflow SVG. */
.brand-mark { height: 1.15rem; width: auto; display: block; color: var(--text); }
[data-theme='light'] .brand-mark { color: var(--brand); }
@media (max-width: 900px) { .brand-mark { height: 1.05rem; } }

.rail-nav { display: flex; flex-direction: column; gap: .35rem; }
.rail-nav a {
  font-size: .9375rem;
  color: var(--muted);
  width: max-content;
  position: relative;
  transition: color .25s var(--ease);
}
.rail-nav a::before {
  content: '';
  position: absolute;
  left: -0.85rem; top: 50%;
  width: .35rem; height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform .3s var(--ease);
}
.rail-nav a:hover,
.rail-nav a[aria-current='true'] { color: var(--text); }
.rail-nav a[aria-current='true']::before { transform: scaleX(1); }

.rail-foot { display: flex; flex-direction: column; gap: .75rem; }

.theme-toggle {
  width: 2.25rem; height: 2.25rem;
  border: 1px solid var(--rule);
  border-radius: 50%;
  display: grid; place-items: center;
  color: var(--muted);
  transition: color .25s var(--ease), border-color .25s var(--ease), transform .25s var(--ease);
}
.theme-toggle:hover { color: var(--text); border-color: var(--text); transform: rotate(15deg); }
.theme-toggle svg { width: 1rem; height: 1rem; }
.icon-sun { display: none; }
[data-theme='light'] .icon-sun { display: block; }
[data-theme='light'] .icon-moon { display: none; }

/* content sits to the right of the rail on wide screens */
@media (min-width: 1024px) {
  .wrap { padding-left: calc(var(--rail) + var(--gut)); padding-right: var(--gut); max-width: 1440px; }
  .topbar { display: none; }
}

/* ---------- topbar (mobile) ---------------------------------------------- */
@media (max-width: 1023px) {
  .rail { display: none; }
  .topbar {
    position: sticky; top: 0; z-index: 90;
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem;
    padding: .9rem var(--gut);
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--rule);
  }
  .topbar { position: sticky; }
  .topbar-actions { display: flex; align-items: center; gap: .5rem; }

  /* the hamburger matches the theme toggle so the pair reads as one control */
  .topbar-toggle {
    width: 2.25rem; height: 2.25rem;
    border: 1px solid var(--rule);
    border-radius: 50%;
    display: grid; place-items: center;
    color: var(--muted);
    transition: color .25s var(--ease), border-color .25s var(--ease);
  }
  .topbar-toggle:hover { color: var(--text); border-color: var(--text); }
  .topbar-toggle svg { width: 1.05rem; height: 1.05rem; }
  .icon-close { display: none; }
  [data-nav='open'] .icon-close { display: block; }
  [data-nav='open'] .icon-bars { display: none; }

  /* the panel drops out of the bar and covers nothing else */
  .topbar-nav {
    position: absolute; top: 100%; left: 0; right: 0;
    display: flex; flex-direction: column; gap: 0;
    padding: .5rem var(--gut) 1rem;
    /* opaque on purpose: a translucent panel let the hero read through the links */
    background: var(--bg);
    border-bottom: 1px solid var(--rule);
    box-shadow: 0 18px 40px -24px rgb(0 0 0 / .8);
  }
  .topbar-nav a {
    font-size: 1rem; color: var(--muted);
    padding: .8rem 0;
    border-top: 1px solid var(--rule);
  }
  .topbar-nav a:first-child { border-top: 0; }
  .topbar-nav a[aria-current='true'] { color: var(--text); }

  /* closed is the default once JS has run; with JS off the links just stack */
  [data-nav='closed'] .topbar-nav { display: none; }
}

/* ---------- hero --------------------------------------------------------- */
.hero {
  min-height: min(92vh, 900px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(4rem, 14vh, 9rem) var(--sec);
}
.hero .display { max-width: 16ch; margin-block: 1.75rem 2.5rem; }
.hero-sub { max-width: 46ch; color: var(--muted); font-size: var(--t-lead); line-height: 1.45; }

.hero-scroll {
  margin-top: clamp(3rem, 8vh, 6rem);
  display: inline-flex; align-items: center; gap: .6rem;
}
.hero-scroll .bar {
  display: block; width: 3rem; height: 1px; background: var(--rule); position: relative; overflow: hidden;
}
.hero-scroll .bar::after {
  content: ''; position: absolute; inset: 0; background: var(--accent);
  transform: translateX(-100%);
  animation: sweep 2.4s var(--ease) infinite;
}
@keyframes sweep {
  0% { transform: translateX(-100%); }
  60%,100% { transform: translateX(100%); }
}

/* ---------- work tiles --------------------------------------------------- */
.work-list { display: flex; flex-direction: column; gap: clamp(3rem, 8vh, 7rem); }

.tile { display: block; position: relative; }
/* these are <span>s inside an <a>, so they must be told to behave as blocks */
.tile-frame, .tile-title, .tile-sub, .tile-bar > span { display: block; }
.tile-frame {
  position: relative;
  overflow: hidden;
  will-change: clip-path;
  background: var(--surface);
  border: 1px solid var(--rule);
  aspect-ratio: 16 / 9;
}
.tile-frame img {
  width: 100%; height: 100%;
  object-fit: cover;
  will-change: transform;
  transition: filter .6s var(--ease);
}
.tile:hover .tile-frame img { filter: brightness(1.06); }

/* hover: lift, warm the border, and float a highlight that follows the cursor */
.tile-frame {
  transition: box-shadow .45s var(--ease), border-color .45s var(--ease);
}
.tile:hover .tile-frame {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--rule));
  box-shadow:
    0 34px 90px -28px rgba(0, 0, 0, .75),
    0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
}
[data-theme='light'] .tile:hover .tile-frame {
  box-shadow:
    0 34px 90px -34px rgba(0, 0, 0, .35),
    0 0 0 1px color-mix(in srgb, var(--accent) 28%, transparent);
}
.tile-frame::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: plus-lighter;
  background: radial-gradient(360px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--accent) 18%, transparent), transparent 72%);
  transition: opacity .45s var(--ease);
}
.tile:hover .tile-frame::after { opacity: 1; }

.tile-bar {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  margin-top: 1.25rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--rule);
}
.tile-title { font-size: var(--t-h2); }
.tile-sub { color: var(--muted); margin-top: .35rem; }
.tile-go {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--mono); font-size: var(--t-meta);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--muted);
  transition: color .25s var(--ease), gap .25s var(--ease);
}
.tile:hover .tile-go { color: var(--accent); gap: .9rem; }

/* Client request (2026-09-04): the tiles were offset every other one for an
   asymmetric rhythm. Todd wants them uniformly stacked, so they now all run
   full width. The scroll-in reveal is untouched — it lives on
   `.motion-ready .work-list .tile` below and in js/tcd.js, not here. */

.all-work {
  margin-top: clamp(2.5rem, 6vh, 4rem);
  display: inline-flex; align-items: center; gap: .75rem;
  font-size: var(--t-h3);
  border-bottom: 1px solid var(--rule);
  padding-bottom: .4rem;
  transition: gap .3s var(--ease), border-color .3s var(--ease);
}
.all-work:hover { gap: 1.4rem; border-color: var(--accent); }

/* ---------- statement ---------------------------------------------------- */
.statement {
  font-size: clamp(1.5rem, 3.4vw, 3rem);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.15;
  max-width: 22ch;
}

/* ---------- impact figures ----------------------------------------------- */
.impact {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}
.impact-cell { background: var(--bg); padding: clamp(1.5rem, 3vw, 2.5rem); }
.impact-num {
  font-variant-numeric: tabular-nums;
  font-size: clamp(2.5rem, 5vw, 4rem);
  font-weight: 500;
  letter-spacing: -0.045em;
  line-height: 1;
  color: var(--text);
}
.impact-label { margin-top: .75rem; color: var(--muted); font-size: .9375rem; line-height: 1.4; }
.impact-src { margin-top: .5rem; }

/* ---------- roster marquee ----------------------------------------------- */
.marquee {
  overflow: hidden;
  border-block: 1px solid var(--rule);
  padding-block: clamp(1.5rem, 3vw, 2.5rem);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-track { display: flex; align-items: center; gap: clamp(2.5rem, 6vw, 5rem); width: max-content; will-change: transform; }
.marquee-track img {
  /* cap BOTH axes: these are a mix of square lockups and very wide wordmarks,
     so height alone lets a wordmark like Tommy Hilfiger dwarf the rest */
  height: auto;
  width: auto;
  max-height: clamp(20px, 2.6vw, 30px);
  max-width: clamp(96px, 11vw, 158px);
  object-fit: contain;
  opacity: .55;
  filter: grayscale(1);
  transition: opacity .3s var(--ease), filter .3s var(--ease);
}
.marquee:hover img { opacity: .9; filter: grayscale(0); }
/* the dark canvas needs pale logos inverted to read at all */
:root .marquee-track img.invert { filter: grayscale(1) invert(1) brightness(1.6); }
:root .marquee:hover img.invert { filter: grayscale(0) invert(1) brightness(1.6); }
[data-theme='light'] .marquee-track img.invert { filter: grayscale(1); }
[data-theme='light'] .marquee:hover img.invert { filter: grayscale(0); }

/* ---------- quotes ------------------------------------------------------- */
.quotes { display: grid; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
@media (min-width: 900px) { .quotes { grid-template-columns: repeat(3, 1fr); } }

.quote {
  background: var(--bg);
  padding: clamp(1.75rem, 3vw, 2.75rem);
  display: flex; flex-direction: column; gap: 1.5rem;
  transition: background-color .4s var(--ease);
}
.quote:hover { background: var(--surface); }
.quote blockquote { font-size: 1.0625rem; line-height: 1.55; letter-spacing: -0.01em; }
.quote figcaption { margin-top: auto; padding-top: 1.25rem; border-top: 1px solid var(--rule); }
.quote-name { font-weight: 600; letter-spacing: -0.02em; }
.quote-role { margin-top: .15rem; }

/* ---------- contact / footer --------------------------------------------- */
.contact { padding-block: var(--sec); border-top: 1px solid var(--rule); }
.contact-mail {
  display: inline-block;
  font-size: clamp(1.5rem, 4.5vw, 3.25rem);
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.05;
  word-break: break-word;
  border-bottom: 2px solid var(--rule);
  padding-bottom: .15em;
  transition: border-color .3s var(--ease), color .3s var(--ease);
}
.contact-mail:hover { border-color: var(--accent); color: var(--accent); }

.contact-links { display: flex; flex-wrap: wrap; gap: 1.75rem; margin-top: clamp(2rem, 5vh, 3rem); }
.contact-links a {
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--mono); font-size: var(--t-meta);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--muted);
  border-bottom: 1px solid transparent;
  padding-bottom: .25rem;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.contact-links a:hover { color: var(--text); border-color: var(--accent); }

.site-foot {
  border-top: 1px solid var(--rule);
  padding-block: 2rem;
  display: flex; flex-wrap: wrap; gap: 1rem 2rem;
  align-items: center; justify-content: space-between;
}
.foot-nav { display: flex; flex-wrap: wrap; gap: 1.25rem; }

/* ==========================================================================
   CASE STUDY
   ========================================================================== */
.cs-masthead { padding-block: clamp(4rem, 12vh, 8rem) clamp(2.5rem, 6vh, 4rem); }
.cs-back { display: inline-flex; align-items: center; gap: .5rem; margin-bottom: 2.5rem; }
.cs-back:hover { color: var(--accent); }

.cs-title { font-size: var(--t-h1); max-width: 18ch; }
.cs-tagline { margin-top: 1rem; font-size: var(--t-lead); color: var(--muted); max-width: 40ch; }

.cs-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(160px, 100%), 1fr));
  gap: 1.5rem 2rem;
  margin-top: clamp(2.5rem, 6vh, 4rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule);
}
.cs-fact dt { margin-bottom: .4rem; }
.cs-fact dd { margin: 0; font-weight: 500; letter-spacing: -0.01em; }

.cs-hero {
  margin-top: clamp(2.5rem, 6vh, 4rem);
  overflow: hidden;
  border: 1px solid var(--rule);
  background: var(--surface);
}
.cs-hero img { width: 100%; will-change: transform; }

/* narrative body */
.cs-section { padding-block: clamp(3rem, 8vh, 6rem); border-top: 1px solid var(--rule); }
.cs-section > .sec-head { border-bottom: 0; padding-bottom: 0; margin-bottom: 2rem; }
.cs-grid { display: grid; gap: clamp(1.5rem, 4vw, 3.5rem); }
@media (min-width: 900px) { .cs-grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); } }

.hmw {
  display: grid; gap: 1px; background: var(--rule);
  border: 1px solid var(--rule);
}
.hmw li { background: var(--bg); padding: 1.5rem; display: flex; gap: 1rem; align-items: flex-start; }
.hmw .n { font-family: var(--mono); font-size: var(--t-meta); color: var(--accent); padding-top: .3em; flex: none; }

.pillars { display: grid; gap: 1.5rem; }
@media (min-width: 760px) { .pillars { grid-template-columns: repeat(2, 1fr); } }
.pillar { border-top: 1px solid var(--rule); padding-top: 1.25rem; }
.pillar h3 { margin-bottom: .6rem; }
.pillar ul { display: flex; flex-direction: column; gap: .5rem; color: var(--muted); }
.pillar li { padding-left: 1rem; position: relative; }
.pillar li::before {
  content: ''; position: absolute; left: 0; top: .7em;
  width: .35rem; height: 1px; background: var(--accent);
}

.outputs { display: grid; gap: 1.5rem; }
@media (min-width: 760px) { .outputs { grid-template-columns: repeat(2, 1fr); } }
.output {
  overflow: hidden; border: 1px solid var(--rule); background: var(--surface);
}
.output img { width: 100%; }
.output.wide { grid-column: 1 / -1; }
.output figcaption { padding: .9rem 1.1rem; border-top: 1px solid var(--rule); }

.embed { position: relative; aspect-ratio: 16 / 9; background: var(--surface-2); }
.embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* reading progress on case studies */
.progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left center;
  z-index: 120;
}

.cs-next { border-top: 1px solid var(--rule); padding-block: clamp(3rem, 8vh, 5rem); }
.cs-next-link { display: flex; align-items: baseline; justify-content: space-between; gap: 2rem; flex-wrap: wrap; }
.cs-next-link h3 { font-size: var(--t-h2); transition: color .3s var(--ease); }
.cs-next-link:hover h3 { color: var(--accent); }

/* ==========================================================================
   MOTION — base states. JS adds .motion-ready once GSAP takes over.
   Without JS (or with reduced motion) everything stays visible.
   ========================================================================== */
.motion-ready [data-reveal] { opacity: 0; transform: translateY(24px); }
.motion-ready [data-reveal-children] > * { opacity: 0; transform: translateY(24px); }
.motion-ready [data-rule] { transform: scaleX(0); transform-origin: left center; }
.motion-ready .work-list .tile { opacity: 0; }

/* view transitions between pages */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: vt-out .28s var(--ease) both; }
::view-transition-new(root) { animation: vt-in  .38s var(--ease) both; }
@keyframes vt-out { to { opacity: 0; transform: translateY(-8px); } }
@keyframes vt-in  { from { opacity: 0; transform: translateY(12px); } }

/* ---------- the accessibility gate --------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .motion-ready [data-reveal],
  .motion-ready [data-reveal-children] > *,
  .motion-ready [data-rule],
  .motion-ready .work-list .tile,
  .motion-ready .tile-frame img { opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important; }
  .tile-frame::after { display: none; }
  .hero-scroll .bar::after { animation: none; transform: translateX(0); }
  @view-transition { navigation: none; }
}

/* ==========================================================================
   FILM — natively hosted case-study video
   Client request (2026-09-04): the Vimeo embeds Todd had inside his Webflow
   rich text are now served from /media, and the FIRST film of a case study
   replaces its hero photo.

   Accessibility: the hero plays on its own, so WCAG 2.2.2 (Pause, Stop, Hide)
   applies. The markup ships with native `controls` and no `autoplay`; the JS
   only takes the controls away once it has installed the custom pause button
   in their place. Reduced motion, data-saver and JS-off therefore all land on
   a still poster the viewer starts themselves.
   ========================================================================== */
.cs-hero-film { position: relative; }
.cs-hero-film video {
  display: block;
  width: 100%; height: auto;
  background: var(--surface-2);
}
/* The caption doubles as the film's text alternative, so it is real text on the
   page rather than an attribute only some readers reach. */
.cs-hero-cap {
  padding: clamp(.9rem, 1.6vw, 1.2rem);
  border-top: 1px solid var(--rule);
  color: var(--muted);
  text-transform: none; letter-spacing: 0;
  line-height: 1.5;
}

/* the pause/play control the JS installs over an autoplaying hero */
.vid-toggle {
  position: absolute; top: 1rem; right: 1rem; z-index: 3;
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .55rem .85rem;
  font-family: var(--mono); font-size: var(--t-meta);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--text);
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  border: 1px solid var(--rule);
  backdrop-filter: blur(6px);
  cursor: pointer;
  transition: border-color .25s var(--ease), color .25s var(--ease);
}
.vid-toggle:hover { color: var(--accent); border-color: var(--accent); }
.vid-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.vid-toggle svg { width: 14px; height: 14px; }

/* films inside the carousel share the walkthrough slide furniture */
.film-frame {
  position: relative;
  background: var(--surface-2);
  padding: clamp(.6rem, 1.4vw, 1.1rem);
  height: clamp(300px, 56vh, 620px);
  display: grid; place-items: center;
  overflow: hidden;
}
.film-frame video {
  display: block;
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
}
.film-title { color: var(--text); }
.film-single .slide { flex: 1 1 auto; }
.film-fallback { padding: 1rem; color: var(--muted); }

@media (prefers-reduced-motion: reduce) {
  /* belt and braces: even if the JS has already started one, stop asking for it */
  .cs-hero-film video { animation: none !important; }
}

/* ---------- live prototype in the hero slot ----------------------------- */
/* A launch card by default: the Lovable host's frame-ancestors excludes this
   origin, so an inline frame would render blank. `inline=True` on the case dict
   swaps in the iframe once a published URL permits it. */
.cs-hero-proto { position: relative; }
.proto-poster { display: block; position: relative; overflow: hidden; }
.proto-poster img { display: block; width: 100%; height: auto; transition: transform .8s var(--ease); }
.proto-poster:hover img { transform: scale(1.02); }
.proto-poster::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(to top, color-mix(in srgb, var(--bg) 55%, transparent), transparent 45%);
  opacity: 0; transition: opacity .45s var(--ease);
}
.proto-poster:hover::after { opacity: 1; }
.proto-poster:focus-visible { outline: 2px solid var(--accent); outline-offset: -3px; }

.proto-badge {
  position: absolute; top: 1rem; left: 1rem; z-index: 2;
  display: inline-flex; align-items: center; gap: .5rem;
  padding: .45rem .75rem;
  font-family: var(--mono); font-size: var(--t-meta);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--accent-ink); background: var(--accent);
}

.proto-frame { position: relative; aspect-ratio: 16 / 10; background: var(--surface-2); }
.proto-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.proto-bar {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  border-top: 1px solid var(--rule);
}
.proto-bar .cs-hero-cap { border-top: 0; flex: 1 1 24ch; }
.proto-launch {
  padding: clamp(.9rem, 1.6vw, 1.2rem);
  display: inline-flex; align-items: center; gap: .6rem;
  font-family: var(--mono); font-size: var(--t-meta);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--accent);
  white-space: nowrap;
  transition: gap .25s var(--ease);
}
.proto-launch:hover { gap: 1rem; }

/* ==========================================================================
   BENTO GRID
   Modelled on seansmithdesign.com's feed: a 12-column lattice with a fixed
   row unit, every cell given an explicit column x row span, and alternate
   cells nudged vertically so the pattern reads as deliberate-but-irregular
   rather than as a tidy card grid.
   Rows are minmax(unit, auto) rather than a hard unit so text cells can grow
   instead of clipping - the one place we deviate from the reference.
   ========================================================================== */
.bento {
  --bento-row: clamp(72px, 7.5vw, 108px);
  --bento-gap: clamp(10px, 1.1vw, 16px);
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-auto-rows: minmax(var(--bento-row), auto);
  gap: var(--bento-gap);
}

/* span vocabulary - columns 4/6/8/12, rows 2/3/4/6, as the reference uses */
.c4  { grid-column: span 4;  }
.c6  { grid-column: span 6;  }
.c8  { grid-column: span 8;  }
.c12 { grid-column: span 12; }
.r2 { grid-row: span 2; }
.r3 { grid-row: span 3; }
.r4 { grid-row: span 4; }
.r5 { grid-row: span 5; }
.r6 { grid-row: span 6; }

/* NO vertical stagger. The reference declares translateY(var(--feed-stagger, 0px))
   but never sets the variable, so it resolves to 0 - the cells sit flush. The
   irregularity there comes entirely from the SPANS, and the spans are chosen so
   the lattice tiles with no holes. Offsetting cells is what produces the ragged
   gaps this was meant to avoid, so the span sequences below are hand-tiled and
   every band sums to exactly 12 columns. */

/* Below the desktop breakpoint the lattice stops earning its keep. A 6-column
   fallback left half-width cells stranded beside empty gaps, and neighbouring
   cells of different row spans put their titles on different baselines - it read
   as broken rather than irregular. One column, each cell sized by its content,
   from the same width where the rail gives way to the topbar. */
@media (max-width: 1023px) {
  .bento { grid-template-columns: 1fr; }
  .c4, .c6, .c8, .c12 { grid-column: span 1; }
  .r2, .r3, .r4, .r5, .r6 { grid-row: auto; }

  /* With the row spans gone the cells have no definite height, so the image has
     nothing to resolve height:100% against. Rather than force every card into
     one box - which letterboxed the very wide composites into thin strips - let
     each image keep its own aspect and size the media to it. The cap stops a
     tall diagram taking the whole screen. */
  .bento-media { flex: none; }
  .bento-media img { height: auto; max-height: 70vh; }
}

/* ---------- cell ---------- */
.bento-cell {
  position: relative;
  display: block;
  min-width: 0;
  perspective: 900px;   /* gives the tilt somewhere to happen */
}

.bento-tilt {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  background: var(--surface);
  border: 1px solid var(--rule);
  overflow: hidden;
  transform-style: preserve-3d;
  will-change: transform;
  transition: border-color .35s var(--ease), background-color .35s var(--ease);
}
a.bento-cell:hover .bento-tilt,
figure.bento-cell:hover .bento-tilt { border-color: color-mix(in srgb, var(--accent) 55%, var(--rule)); }

/* the glow that tracks the pointer, as on the reference. plus-lighter so it
   adds light rather than washing the panel out. */
.bento-tilt::after {
  content: '';
  position: absolute;
  inset: -1px;
  pointer-events: none;
  opacity: 0;
  z-index: 3;
  mix-blend-mode: plus-lighter;
  background: radial-gradient(280px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--accent) 22%, transparent), transparent 70%);
  transition: opacity .4s var(--ease);
}
a.bento-cell:hover .bento-tilt::after,
figure.bento-cell:hover .bento-tilt::after { opacity: 1; }

.bento-media {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
  background:
    radial-gradient(120% 100% at 50% 0%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 60%),
    var(--surface-2);
}
.bento-media img {
  width: 100%;
  height: 100%;
  /* contain, not cover. These are wide UI composites, not photography - cover
     crops them into unreadable fragments. The reference does the same: product
     shots float centred on a tinted panel with real room around them, and that
     breathing space is the look rather than wasted space. */
  object-fit: contain;
  object-position: center;
  padding: clamp(.85rem, 2.2vw, 2rem);
  transition: transform .8s var(--ease), filter .5s var(--ease);
  will-change: transform;
}
/* the satisfying part: media scales inside a fixed frame */
a.bento-cell:hover .bento-media img,
figure.bento-cell:hover .bento-media img { transform: scale(1.045); }
.bento-media.cover img { object-fit: cover; padding: 0; }

.bento-body {
  padding: clamp(1rem, 1.6vw, 1.6rem);
  display: flex;
  flex-direction: column;
  gap: .55rem;
}
.bento-media + .bento-body { border-top: 1px solid var(--rule); }
.bento-title { font-size: var(--t-h3); letter-spacing: -0.02em; line-height: 1.12; }
.bento-cell .pillar-list { display: flex; flex-direction: column; gap: .45rem; color: var(--muted); font-size: .9375rem; }
.bento-cell .pillar-list li { padding-left: 1rem; position: relative; }
.bento-cell .pillar-list li::before {
  content: ''; position: absolute; left: 0; top: .72em;
  width: .35rem; height: 1px; background: var(--accent);
}

/* accent cell, the reference's pink panel */
.bento-tilt.accent {
  background: var(--accent);
  border-color: var(--accent);
}
.bento-tilt.accent, .bento-tilt.accent .bento-title { color: var(--accent-ink); }
.bento-tilt.accent .meta { color: color-mix(in srgb, var(--accent-ink) 72%, transparent); }

/* a figure cell's caption sits flush at the bottom */
figure.bento-cell { margin: 0; }

/* reveal: opacity only. Transform on these is owned by the stagger and the
   tilt, so animating y here would fight both. */
.motion-ready .bento > * { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .motion-ready .bento > * { opacity: 1 !important; }
  .bento-tilt::after { display: none; }
  .bento-media img { transition: none; }
}

/* ==========================================================================
   ABOUT
   ========================================================================== */
.about-hero .display { max-width: 18ch; }

.about-grid { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
@media (min-width: 900px) { .about-grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); } }

/* PORTRAIT SLOT — fixed 4:5 frame, object-fit:cover. Any photo dimensions drop
   in without changing the layout around it. */
.portrait { margin: 0; position: sticky; top: 3rem; }
.portrait-frame {
  overflow: hidden;
  border: 1px solid var(--rule);
  background: var(--surface-2);
  aspect-ratio: 4 / 5;
}
.portrait-frame img { width: 100%; height: 100%; object-fit: cover; object-position: center 20%; }
.portrait figcaption { margin-top: .9rem; }
@media (max-width: 899px) { .portrait { position: static; max-width: 380px; } }

.about-prose p + p { margin-top: 1.2em; }

/* ---------- experience ---------- */
.roles { display: flex; flex-direction: column; }
.role { border-top: 1px solid var(--rule); padding-block: clamp(2rem, 4vw, 3rem); }
.role:last-child { border-bottom: 1px solid var(--rule); }

.role-head {
  display: grid; gap: 1rem 1.25rem; align-items: start;
  grid-template-columns: auto 1fr auto;
  margin-bottom: 1.5rem;
}
.role-mark {
  width: 52px; height: 52px; flex: none;
  border: 1px solid var(--rule);
  background: var(--surface);
  display: grid; place-items: center; overflow: hidden;
}
.role-mark img { max-width: 74%; max-height: 74%; object-fit: contain; }
/* most employer marks are dark artwork on transparent — invert on the dark canvas */
:root .role-mark img { filter: invert(1) brightness(1.7) grayscale(1); }
[data-theme='light'] .role-mark img { filter: grayscale(1); }

.role-company { font-size: var(--t-h3); letter-spacing: -0.02em; }
.role-title { margin-top: .2rem; }
.role-meta { margin-top: .45rem; }
.role-index { align-self: start; }

.role-body { display: grid; gap: 1rem; }
@media (min-width: 900px) { .role-body { padding-left: calc(52px + 1.25rem); max-width: 78ch; } }
.role-tagline { font-size: var(--t-lead); letter-spacing: -0.015em; line-height: 1.35; }
.role-body p { color: var(--muted); }
.role-tagline { color: var(--text) !important; }

.role-kit { display: grid; gap: 1rem; margin-top: .5rem; }
@media (min-width: 700px) { .role-kit { grid-template-columns: 1fr 1fr; } }
.role-kit dt { margin-bottom: .35rem; }
.role-kit dd { margin: 0; font-size: .9375rem; color: var(--muted); }
.role .tile-go { margin-top: .5rem; }
.role:hover .tile-go { color: var(--accent); gap: .9rem; }

/* ---------- about: at-a-glance, pull-quote, role chips ------------------- */
.about-meta { margin-top: clamp(2.5rem, 6vh, 4rem); }
.about-pull {
  margin-bottom: clamp(2.5rem, 6vh, 4rem);
  max-width: 26ch;
  color: var(--text);
}

/* the skills and tools lists were comma-separated grey text; chips are
   scannable and give the role blocks texture without new copy */
.chips { display: flex; flex-wrap: wrap; gap: .4rem; list-style: none; margin: 0; padding: 0; }
.chip {
  font-family: var(--mono); font-size: .7rem;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: .32rem .62rem;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.role:hover .chip { border-color: color-mix(in srgb, var(--accent) 30%, var(--rule)); }
.role-kit dd { color: inherit; }

/* the separator between roles is drawn on scroll rather than just being there */
.role { position: relative; border-top: 0; }
.roles > .role:last-child { border-bottom: 0; }
.role-rule {
  position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: var(--rule);
  transform-origin: left center;
}
.role { transition: background .4s var(--ease); }
.role:hover { background: color-mix(in srgb, var(--surface) 55%, transparent); }

.mini-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }
.mini-list li { border-bottom: 1px solid var(--rule); }
.mini-list a {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: .85rem 0;
  color: var(--muted);
  transition: color .25s var(--ease), padding-left .25s var(--ease);
}
.mini-list a:hover { color: var(--text); padding-left: .35rem; }
.mini-title { letter-spacing: -0.01em; }

/* ---------- contact: copy button and local clock ------------------------ */
.mail-row { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.copy-btn {
  font-family: var(--mono); font-size: var(--t-meta);
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--muted);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: .35rem .7rem;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}
.copy-btn:hover { color: var(--text); border-color: var(--text); }
.copy-btn[data-copied='true'] { color: var(--accent); border-color: var(--accent); }
.local-time { margin-top: .75rem; }
.local-time::before {
  content: ''; display: inline-block;
  width: .4rem; height: .4rem; border-radius: 50%;
  background: var(--accent);
  margin-right: .5rem; vertical-align: .05em;
}

/* ==========================================================================
   CAROUSEL — screen-by-screen walkthroughs
   A board of twenty artboards exported as one image is unreadable at any size a
   page can give it. These are the individual screens, one at a time, in a
   bounded slider rather than an endless column. The track is a native
   scroll-snap area, so with JS off it is still swipeable and keyboard
   scrollable - the buttons are the enhancement, not the mechanism.
   ========================================================================== */
.carousel { position: relative; }
.carousel-track {
  display: flex;
  gap: var(--bento-gap, 14px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.carousel-track::-webkit-scrollbar { display: none; }
.carousel-track:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  margin: 0;
  border: 1px solid var(--rule);
  background: var(--surface);
  display: flex; flex-direction: column;
  min-width: 0;
}
/* one card per slide at every width: two-up halved the screens and undid the point
   of extracting them individually in the first place */

/* Every card is the same height whatever shape the screenshot is. Letting the
   image set the height meant a portrait capture ran to twice the viewport and the
   strip became a scrolling mess; the full detail is one click away in the
   lightbox, so the thumbnail only has to be legible and consistent. */
.slide-media {
  background:
    radial-gradient(120% 100% at 50% 0%, color-mix(in srgb, var(--accent) 7%, transparent), transparent 60%),
    var(--surface-2);
  padding: clamp(.6rem, 1.4vw, 1.1rem);
  height: clamp(300px, 56vh, 620px);
  display: grid;
  place-items: center;
  overflow: hidden;
}
.slide-media img {
  display: block;
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
}
.slide-cap {
  padding: clamp(.9rem, 1.6vw, 1.2rem);
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: .9375rem;
  display: flex; gap: .75rem; align-items: baseline;
}
.slide-cap .meta { flex: none; color: var(--accent); }

.carousel-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-top: 1.25rem;
}
.carousel-btns { display: flex; gap: .5rem; }
.carousel-btn {
  width: 2.5rem; height: 2.5rem;
  border: 1px solid var(--rule); border-radius: 50%;
  display: grid; place-items: center;
  color: var(--muted);
  transition: color .25s var(--ease), border-color .25s var(--ease), opacity .25s var(--ease);
}
.carousel-btn:hover:not(:disabled) { color: var(--text); border-color: var(--text); }
.carousel-btn:disabled { opacity: .3; cursor: default; }
.carousel-btn svg { width: 1.05rem; height: 1.05rem; }
/* the controls only do something once JS is bound */
.carousel:not([data-carousel-ready]) .carousel-btns { display: none; }

/* the whole thumbnail is the control that opens the viewer */
.slide-media { display: block; width: 100%; text-align: inherit; cursor: zoom-in; }
.slide-media:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.slide-media img { transition: transform .5s var(--ease); }
.slide-media:hover img { transform: scale(1.015); }

/* ---------- lightbox ---------- */
.lightbox {
  width: 100vw; max-width: 100vw; height: 100vh; max-height: 100vh;
  margin: 0; padding: 0; border: 0;
  background: color-mix(in srgb, var(--bg) 97%, transparent);
  color: var(--text);
  display: none;
  overflow: hidden;
}
.lightbox[open] { display: flex; flex-direction: column; }
.lightbox::backdrop { background: rgb(0 0 0 / .8); }
.lightbox-stage {
  flex: 1 1 auto; min-height: 0;
  display: grid; place-items: center;
  padding: clamp(1rem, 3vw, 2.5rem);
}
.lightbox-stage img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
  border: 1px solid var(--rule);
}
.lightbox-bar {
  flex: none;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  padding: clamp(.9rem, 2vw, 1.25rem) clamp(1rem, 3vw, 2.5rem);
  border-top: 1px solid var(--rule);
  background: var(--surface);
}
.lightbox-cap { display: flex; gap: .75rem; align-items: baseline; min-width: 0; }
.lightbox-cap .meta { flex: none; color: var(--accent); }
.lightbox-cap span:last-child { color: var(--muted); font-size: .9375rem; }
@media (prefers-reduced-motion: reduce) { .slide-media img { transition: none; } }

/* ==========================================================================
   CASE STUDY INDEX
   ========================================================================== */
.case-index-hero .display { max-width: 14ch; }
.bento-year { margin-top: .35rem; }
a.bento-cell:hover .bento-year { color: var(--accent); }

/* ==========================================================================
   CONTACT
   ========================================================================== */
.contact-hero .display { max-width: 16ch; }
.contact-grid { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
@media (min-width: 900px) { .contact-grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); } }

.form-card { border: 1px solid var(--rule); background: var(--surface); padding: clamp(1.5rem, 3vw, 2.5rem); }
.field { display: flex; flex-direction: column; gap: .5rem; margin-bottom: 1.25rem; }
.field label { font-family: var(--mono); font-size: var(--t-meta); text-transform: uppercase; letter-spacing: .12em; color: var(--muted); }
.field input, .field textarea, .field select {
  font: inherit; color: var(--text);
  background: var(--bg);
  border: 1px solid var(--rule);
  padding: .85rem 1rem;
  width: 100%;
  transition: border-color .25s var(--ease);
}
.field textarea { resize: vertical; min-height: 8rem; }
.field input::placeholder, .field textarea::placeholder { color: color-mix(in srgb, var(--muted) 70%, transparent); }
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--accent); }

/* Two fields on a line above 640px, stacked below - the contact form only. */
.field-row { display: grid; gap: 0 1.25rem; }
@media (min-width: 640px) { .field-row { grid-template-columns: 1fr 1fr; } }

/* The native arrow is drawn in the UA colour, which reads wrong on the dark canvas,
   so it is replaced with a chevron that follows the theme ink. */
.field select {
  appearance: none;
  padding-right: 2.5rem;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 1.15rem) calc(50% + 2px), calc(100% - .8rem) calc(50% + 2px);
  background-size: .35rem .35rem, .35rem .35rem;
  background-repeat: no-repeat;
}
.field select option { background: var(--bg); color: var(--text); }

.form-fine { margin-top: 1.25rem; font-size: .875rem; max-width: 46ch; }
.contact-facts { margin-top: clamp(2rem, 5vh, 3rem); }
@media (min-width: 900px) { .contact-facts { grid-template-columns: 1fr; } }
.bento-body > p { color: var(--muted); font-size: .9375rem; line-height: 1.55; }

.btn {
  display: inline-flex; align-items: center; gap: .6rem;
  background: var(--accent); color: var(--accent-ink);
  padding: .9rem 1.5rem;
  font-weight: 600; letter-spacing: -0.01em;
  transition: gap .25s var(--ease), filter .25s var(--ease);
}
.btn:hover { gap: 1.1rem; filter: brightness(1.08); }
.btn[disabled] { opacity: .6; cursor: progress; }

/* Webflow's success/failure blocks are hidden until forms.js reveals them */
.form-note { display: none; margin-top: 1.25rem; padding: 1rem 1.25rem; border: 1px solid var(--rule); }
.form-note.ok { border-color: color-mix(in srgb, var(--accent) 50%, var(--rule)); }
.form-note.bad { border-color: color-mix(in srgb, #e5484d 50%, var(--rule)); }

/* ==========================================================================
   INSIGHTS
   ========================================================================== */
.post-list { border-top: 1px solid var(--rule); }
.post-row {
  display: grid; gap: .5rem 2rem; align-items: baseline;
  grid-template-columns: 1fr auto;
  padding-block: clamp(1.25rem, 2.5vw, 2rem);
  border-bottom: 1px solid var(--rule);
  transition: background-color .35s var(--ease), padding-inline .35s var(--ease);
}
.post-row:hover { background: var(--surface); padding-inline: 1.25rem; }
.post-row-title { display: block; font-size: var(--t-h3); letter-spacing: -0.02em; }
.post-row-ex { display: block; margin-top: .35rem; max-width: 62ch; }
.post-row:hover .post-row-date { color: var(--accent); }
@media (max-width: 599px) { .post-row { grid-template-columns: 1fr; } }

.post-body h2 { font-size: var(--t-h3); margin-top: 2em; margin-bottom: .6em; }
.post-body h3 { font-size: 1.125rem; margin-top: 1.6em; margin-bottom: .5em; }
.post-body p { margin-bottom: 1em; color: var(--muted); }
.post-body blockquote {
  margin: 1.5em 0; padding-left: 1.25rem;
  border-left: 2px solid var(--accent);
  font-size: var(--t-lead); line-height: 1.4; letter-spacing: -0.015em; color: var(--text);
}
