/* ==========================================================================
   Gabriela Weinstein - Portfolio
   Design system: warm editorial. Bone paper, ink type, clay accent.
   Case-study pages override --accent to take on that brand's own colour.
   ========================================================================== */

:root{
  color-scheme: light;

  /* Surfaces */
  --bone:      #FBF8F3;
  --bone-2:    #F4EEE5;
  --bone-3:    #EDE5D9;
  --paper:     #FFFFFF;

  /* Ink */
  --ink:       #17130F;
  --ink-2:     #3D3630;
  --muted:     #756B60;
  --rule:      #E2D9CC;

  /* Accents */
  --clay:      #B4472C;
  --clay-deep: #8F3520;
  --sage:      #5F6B52;
  --gold:      #9E7E38;
  --accent:      var(--clay);
  --accent-deep: var(--clay-deep);
  --accent-wash: #F6E9E4;

  /* Type */
  --display: "Fraunces", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Space */
  --gut: clamp(1.25rem, 4vw, 2.5rem);
  --page: 1180px;
  --section: clamp(4.5rem, 9vw, 8rem);

  --shadow-sm: 0 1px 2px rgba(23,19,15,.05), 0 6px 18px -10px rgba(23,19,15,.18);
  --shadow-md: 0 2px 4px rgba(23,19,15,.05), 0 22px 48px -24px rgba(23,19,15,.32);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce){ html { scroll-behavior: auto; } }

body{
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img{ max-width: 100%; display: block; }
a{ color: inherit; }

::selection{ background: var(--accent); color: #fff; }

/* ---------- Type ---------- */

h1,h2,h3,h4{
  font-family: var(--display);
  font-weight: 500;
  line-height: 1.05;
  letter-spacing: -0.018em;
  margin: 0;
  font-variation-settings: "opsz" 100;
}
h1{ font-size: clamp(2.9rem, 7.2vw, 5.4rem); }
h2{ font-size: clamp(2.1rem, 4.4vw, 3.35rem); }
h3{ font-size: clamp(1.35rem, 2.2vw, 1.75rem); line-height: 1.18; letter-spacing: -0.012em; font-variation-settings: "opsz" 40; }
h4{ font-size: 1.1rem; line-height: 1.3; font-variation-settings: "opsz" 20; }

p{ margin: 0 0 1.15em; }
p:last-child{ margin-bottom: 0; }

.eyebrow{
  font-family: var(--sans);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 1.15rem;
  display: flex;
  align-items: center;
  gap: .7rem;
}
.eyebrow::before{
  content:"";
  width: 26px; height: 1px;
  background: var(--accent);
  flex: none;
}
.eyebrow.plain::before{ display:none; }

.lede{
  font-size: clamp(1.1rem, 1.75vw, 1.32rem);
  line-height: 1.62;
  color: var(--ink-2);
}
.big-quote{
  font-family: var(--display);
  font-size: clamp(1.5rem, 3vw, 2.35rem);
  line-height: 1.28;
  letter-spacing: -0.015em;
  font-variation-settings: "opsz" 60;
  color: var(--ink);
}
.muted{ color: var(--muted); }
.serif{ font-family: var(--display); }

/* ---------- Layout ---------- */

.wrap{
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: var(--gut);
}
.wrap-narrow{ max-width: 780px; }

section{ position: relative; }
.section{ padding-block: var(--section); }
.section-tight{ padding-block: clamp(3rem, 6vw, 5rem); }

.band{ background: var(--bone-2); }
.band-ink{ background: var(--ink); color: #F3EDE4; }
.band-ink .muted{ color: #A79C8E; }
.band-ink .eyebrow{ color: #A79C8E; }
.band-ink h2, .band-ink h3{ color: #FBF8F3; }

hr.rule{ border: 0; border-top: 1px solid var(--rule); margin: 0; }

.grid{ display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); }
.g-2{ grid-template-columns: repeat(2, minmax(0,1fr)); }
.g-3{ grid-template-columns: repeat(3, minmax(0,1fr)); }
.g-4{ grid-template-columns: repeat(4, minmax(0,1fr)); }
@media (max-width: 860px){
  .g-3, .g-4{ grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (max-width: 620px){
  .g-2, .g-3, .g-4{ grid-template-columns: minmax(0,1fr); }
}

.section-head{
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(1.5rem, 4vw, 4rem);
  align-items: end;
  margin-bottom: clamp(2.25rem, 4vw, 3.5rem);
}
@media (max-width: 800px){ .section-head{ grid-template-columns: 1fr; align-items: start; } }

/* ---------- Nav ---------- */

.nav{
  position: sticky; top: 0; z-index: 60;
  background: rgba(251,248,243,.86);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color .25s ease, background .25s ease;
}
.nav.scrolled{ border-bottom-color: var(--rule); }
.nav-inner{
  max-width: var(--page); margin-inline: auto;
  padding: .85rem var(--gut);
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.brand{
  display: inline-flex; align-items: center; gap: .55rem;
  text-decoration: none; font-family: var(--display);
  font-size: 1.12rem; letter-spacing: -0.01em; font-weight: 600;
  font-variation-settings: "opsz" 20;
}
.brand .mark{
  width: 30px; height: 30px; border-radius: 50%;
  object-fit: cover;
  flex: none;
  background: var(--bone-3);
  box-shadow: 0 0 0 1px rgba(23,19,15,.10);
  transition: transform .45s var(--ease), box-shadow .3s ease;
}
.brand:hover .mark{
  transform: scale(1.08);
  box-shadow: 0 0 0 1px var(--accent);
}
.nav-links{ display: flex; align-items: center; gap: clamp(.9rem, 2vw, 1.9rem); }
.nav-links a{
  text-decoration: none;
  font-size: .87rem; font-weight: 500; letter-spacing: .005em;
  color: var(--ink-2);
  padding: .35rem 0;
  position: relative;
  white-space: nowrap;
  transition: color .2s ease;
}
.nav-links a::after{
  content:""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 1.5px; background: var(--accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform .28s cubic-bezier(.2,.7,.3,1);
}
.nav-links a:hover{ color: var(--ink); }
.nav-links a:hover::after, .nav-links a[aria-current="page"]::after{ transform: scaleX(1); }
.nav-links a[aria-current="page"]{ color: var(--ink); }

/* Only ever shown inside the open mobile menu */
.nav-foot{ display: none; }

.nav-toggle{
  display: none; background: none; border: 0; cursor: pointer;
  padding: .45rem; margin-right: -.45rem; color: var(--ink);
}
.nav-toggle svg{ display: block; }

/* Two bars that fold into a cross */
.nav-toggle .bars{ display: block; position: relative; width: 24px; height: 13px; }
.nav-toggle .bars i{
  position: absolute; left: 0; right: 0; height: 1.5px;
  background: currentColor; border-radius: 2px;
  transition: transform .5s var(--ease), top .4s var(--ease), width .4s var(--ease);
}
.nav-toggle .bars i:nth-child(1){ top: 1px; }
.nav-toggle .bars i:nth-child(2){ top: 10px; width: 68%; }
.nav[data-menu="open"] .nav-toggle .bars i{ width: 100%; top: 6px; }
.nav[data-menu="open"] .nav-toggle .bars i:nth-child(1){ transform: rotate(45deg); }
.nav[data-menu="open"] .nav-toggle .bars i:nth-child(2){ transform: rotate(-45deg); }

@media (max-width: 760px){
  .nav-toggle{ display: block; }

  /* backdrop-filter would make .nav a containing block for its fixed
     descendants, which would trap the panel inside the 56px bar. */
  .nav{ backdrop-filter: none; -webkit-backdrop-filter: none; }
  .nav[data-menu="open"]{ background: var(--bone); border-bottom-color: transparent; }

  /* The panel is a child of .nav-inner, not a sibling, so the bar's own
     contents have to be lifted above it rather than the wrapper. */
  .nav-inner{ position: relative; }
  .nav-inner > .brand,
  .nav-inner > .nav-toggle{ position: relative; z-index: 2; }

  .nav-links{
    position: fixed; inset: 0;
    z-index: 1;
    counter-reset: navitem;
    flex-direction: column; align-items: stretch; justify-content: flex-start;
    gap: 0;
    padding: calc(56px + clamp(1.5rem, 6vh, 3rem)) var(--gut) 2rem;
    background: var(--bone);
    overflow-y: auto;
    overscroll-behavior: contain;
    opacity: 0; visibility: hidden;
    transition: opacity .4s var(--ease), visibility .4s;
  }
  .nav-links.open{ opacity: 1; visibility: visible; }

  .nav-links a{
    display: flex; align-items: baseline; gap: .95rem;
    font-family: var(--display);
    font-size: clamp(1.85rem, 8.5vw, 2.6rem);
    font-weight: 500; letter-spacing: -.022em; line-height: 1.1;
    font-variation-settings: "opsz" 60;
    color: var(--ink);
    padding: .62em 0;
    border-bottom: 1px solid var(--rule);
    opacity: 0; transform: translateY(16px);
    transition: opacity .55s var(--ease), transform .6s var(--ease), color .3s ease;
    transition-delay: calc(var(--i, 0) * 55ms + 90ms);
  }
  .nav-links.open a{ opacity: 1; transform: none; }
  .nav-links a:nth-child(1){ --i: 1; }
  .nav-links a:nth-child(2){ --i: 2; }
  .nav-links a:nth-child(3){ --i: 3; }
  .nav-links a:nth-child(4){ --i: 4; }
  .nav-links a:nth-child(5){ --i: 5; }

  .nav-links a::before{
    counter-increment: navitem;
    content: "0" counter(navitem);
    font-family: var(--sans); font-size: .68rem; font-weight: 600;
    letter-spacing: .12em; color: var(--muted);
    transition: color .3s ease;
  }
  .nav-links a::after{ display: none; }

  .nav-links a[aria-current="page"]{ color: var(--accent); font-style: italic; }
  .nav-links a[aria-current="page"]::before{ color: var(--accent); }
  .nav-links a:active{ color: var(--accent); }

  /* Contact block, appended by the script */
  .nav-foot{
    display: block;
    margin-top: auto; padding-top: 2rem;
    opacity: 0; transform: translateY(16px);
    transition: opacity .55s var(--ease) .42s, transform .6s var(--ease) .42s;
  }
  .nav-links.open .nav-foot{ opacity: 1; transform: none; }
  .nav-foot .fh{
    font-size: .66rem; font-weight: 600; letter-spacing: .14em;
    text-transform: uppercase; color: var(--muted); margin: 0 0 .7rem;
  }
  .nav-foot a{
    display: block; font-family: var(--sans); font-size: .95rem;
    font-style: normal; letter-spacing: 0;
    color: var(--ink-2); padding: .3rem 0; border: 0;
    opacity: 1; transform: none; transition: color .25s ease;
  }
  .nav-foot a::before{ content: none; }
  .nav-foot a:hover{ color: var(--accent); }
}

@media (max-width: 760px) and (prefers-reduced-motion: reduce){
  .nav-links, .nav-links a, .nav-foot{ transition: none; }
  .nav-links a, .nav-foot{ opacity: 1; transform: none; }
  .nav-toggle .bars i{ transition: none; }
}

/* ---------- Buttons ---------- */

.btn{
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: inline-flex; align-items: center; gap: .5rem;
  font-family: var(--sans); font-size: .9rem; font-weight: 500;
  letter-spacing: .005em;
  padding: .78rem 1.35rem;
  border-radius: 999px;
  text-decoration: none;
  border: 1px solid var(--ink);
  background: var(--ink); color: var(--bone);
  transition: transform .35s cubic-bezier(.16,1,.3,1), color .3s ease,
              border-color .3s ease, box-shadow .35s ease;
  cursor: pointer;
}
/* Colour sweeps up from the bottom edge rather than cross-fading */
.btn::before{
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--accent);
  transform: translateY(101%);
  transition: transform .55s cubic-bezier(.16,1,.3,1);
}
.btn:hover::before, .btn:focus-visible::before{ transform: translateY(0); }
.btn:hover{ transform: translateY(-2px); box-shadow: var(--shadow-sm); border-color: var(--accent); color: #fff; }

.btn-ghost{ background: transparent; color: var(--ink); border-color: var(--rule); }
.btn-ghost::before{ background: var(--ink); }
.btn-ghost:hover{ border-color: var(--ink); color: var(--bone); }

/* On the dark bands */
.btn-light{ background: var(--bone); color: var(--ink); border-color: var(--bone); }
.btn-light::before{ background: var(--accent); }
.btn-light:hover{ color: #fff; border-color: var(--accent); }

.btn-ghost-light{ background: transparent; color: #FBF8F3; border-color: rgba(255,255,255,.32); }
.btn-ghost-light::before{ background: var(--bone); }
.btn-ghost-light:hover{ color: var(--ink); border-color: var(--bone); }

.btn-sm{ padding: .55rem 1.05rem; font-size: .82rem; }
.btn .arr{ transition: transform .35s cubic-bezier(.16,1,.3,1); }
.btn:hover .arr{ transform: translateX(4px); }

.btn-row{ display: flex; flex-wrap: wrap; gap: .7rem; }

.textlink{
  display: inline-flex; align-items: center; gap: .45rem;
  text-decoration: none; font-weight: 500; font-size: .95rem;
  color: var(--ink);
  border-bottom: 1.5px solid var(--accent);
  padding-bottom: 2px;
  transition: gap .25s ease, color .2s ease;
}
.textlink:hover{ gap: .75rem; color: var(--accent-deep); }

/* ---------- Images ---------- */

.frame{
  position: relative;
  overflow: hidden;
  border-radius: 4px;
  background: var(--bone-3);
  box-shadow: var(--shadow-sm);
}
/* Images are never cropped. Each frame takes the picture's own proportions,
   so what you see on the page is the whole photograph - no cover-crop, and
   no letterbox bars either. */
.frame img{
  width: 100%; height: auto; display: block;
  object-fit: contain;
}
/* Hover lifts the frame rather than scaling the picture inside it -
   scaling would push the edges out of a frame that fits exactly. */
.frame-zoom{ transition: transform .5s var(--ease), box-shadow .5s var(--ease); }
.frame-zoom:hover{ transform: translateY(-4px); box-shadow: var(--shadow-md); }

.caption{
  font-size: .78rem; color: var(--muted);
  margin-top: .6rem; line-height: 1.45;
  letter-spacing: .005em;
}

/* Placeholder shown when an image file has not been added to the folder yet */
.frame.img-missing{
  background:
    repeating-linear-gradient(45deg, var(--bone-2) 0 10px, var(--bone-3) 10px 20px);
  box-shadow: inset 0 0 0 1px var(--rule);
  display: grid; place-items: center;
  min-height: 180px;
}
.frame.img-missing img{ display: none; }
.frame.img-missing::after{
  content: "Add " attr(data-file);
  font-family: var(--sans); font-size: .72rem; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase;
  color: var(--muted);
  background: var(--bone);
  padding: .5rem .85rem; border-radius: 999px;
  box-shadow: var(--shadow-sm);
  text-align: center;
  max-width: 88%;
  line-height: 1.4;
}

/* ---------- Hero ---------- */

.hero{
  padding-top: clamp(2.5rem, 6vw, 5rem);
  padding-bottom: clamp(3rem, 7vw, 6rem);
  position: relative;
}
.hero-grid{
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, .82fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
@media (max-width: 900px){
  .hero-grid{ grid-template-columns: 1fr; gap: 2.5rem; }
  .hero-portrait{ order: -1; max-width: 340px; margin-inline: auto; }
}
@media (max-width: 620px){
  /* Decorative offset blocks read as stray shapes at phone width */
  .hero-portrait::before, .hero-portrait::after{ display: none; }
}
.hero h1{ margin-bottom: .55rem; }
.hero h1 .lastname{
  display: block;
  font-style: italic;
  font-variation-settings: "opsz" 144;
  color: var(--accent);
}
.hero-role{
  font-family: var(--sans);
  font-size: clamp(.92rem, 1.5vw, 1.02rem);
  font-weight: 500;
  color: var(--ink-2);
  line-height: 1.55;
  margin: 1.1rem 0 1.5rem;
  max-width: 36ch;
}
.hero-role .sep{ color: var(--rule); margin: 0 .45rem; }
.hero-intro{ max-width: 46ch; margin-bottom: 2rem; }

.hero-portrait{ position: relative; }
.hero-portrait .frame{ border-radius: 6px; box-shadow: var(--shadow-md); }
.hero-portrait::before{
  content:"";
  position: absolute; inset: auto -18px -18px auto;
  width: 62%; height: 58%;
  background: var(--accent-wash);
  border-radius: 6px;
  z-index: -1;
}
.hero-portrait::after{
  content:"";
  position: absolute; inset: -16px auto auto -16px;
  width: 46%; height: 40%;
  border: 1px solid var(--rule);
  border-radius: 6px;
  z-index: -1;
}

/* Three words */
.words{
  display: grid; grid-template-columns: repeat(3, minmax(0,1fr));
  gap: 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
  margin: 0;
}
.words div{
  padding: clamp(1.4rem, 3vw, 2.1rem) clamp(1rem, 2.5vw, 2rem);
  border-right: 1px solid var(--rule);
}
.words div:last-child{ border-right: 0; }
.words dt{
  font-family: var(--display);
  font-size: clamp(1.3rem, 2.4vw, 1.85rem);
  font-variation-settings: "opsz" 40;
  letter-spacing: -0.015em;
  margin-bottom: .45rem;
}
.words dd{ margin: 0; font-size: .92rem; color: var(--muted); line-height: 1.55; }
@media (max-width: 720px){
  .words{ grid-template-columns: 1fr; }
  .words div{ border-right: 0; border-bottom: 1px solid var(--rule); }
  .words div:last-child{ border-bottom: 0; }
}

/* ---------- Work cards ---------- */

.work-card{
  display: block; text-decoration: none;
  position: relative;
  transition: transform .35s cubic-bezier(.2,.7,.3,1);
}
.work-card:hover{ transform: translateY(-5px); }
.work-card .frame{ margin-bottom: 1.15rem; }
.work-card .tagline{
  font-size: .72rem; font-weight: 600; letter-spacing: .13em; text-transform: uppercase;
  color: var(--accent); margin-bottom: .5rem;
}
.work-card h3{ margin-bottom: .5rem; }
.work-card p{ color: var(--muted); font-size: .95rem; }
.work-card .go{
  margin-top: .9rem; display: inline-flex; align-items: center; gap: .4rem;
  font-size: .85rem; font-weight: 500; color: var(--ink);
}
.work-card .go .arr{ transition: transform .25s ease; }
.work-card:hover .go .arr{ transform: translateX(4px); }

/* Big index rows on the Work page */
.work-row{
  display: grid;
  grid-template-columns: minmax(0, .95fr) minmax(0, 1.05fr);
  gap: clamp(1.75rem, 5vw, 4rem);
  align-items: center;
  padding-block: clamp(2.5rem, 5vw, 4rem);
  border-top: 1px solid var(--rule);
  text-decoration: none;
}
.work-row:last-of-type{ border-bottom: 1px solid var(--rule); }
.work-row .frame{ transition: transform .5s cubic-bezier(.2,.7,.3,1); }
.work-row:hover .frame{ transform: translateY(-4px); }
.work-row .num{
  font-family: var(--display); font-size: .95rem; color: var(--muted);
  font-variation-settings: "opsz" 20;
  margin-bottom: .8rem; display: block;
}
@media (max-width: 820px){
  .work-row{ grid-template-columns: 1fr; }
  .work-row .frame{ order: -1; }
}

/* ---------- Case study ---------- */

.case-hero{
  padding-top: clamp(2.5rem, 5vw, 4rem);
  padding-bottom: clamp(2rem, 4vw, 3rem);
  background: linear-gradient(180deg, var(--accent-wash) 0%, var(--bone) 100%);
}
.case-hero h1{ font-size: clamp(2.4rem, 5.6vw, 4.2rem); max-width: 16ch; }
.case-kicker{
  font-family: var(--display); font-style: italic;
  font-size: clamp(1.15rem, 2.2vw, 1.55rem);
  font-variation-settings: "opsz" 60;
  color: var(--accent-deep);
  margin-top: 1.1rem; max-width: 32ch;
  line-height: 1.35;
}
.case-meta{
  display: grid; grid-template-columns: repeat(4, minmax(0,1fr));
  gap: 1.5rem; margin-top: clamp(2rem, 4vw, 3rem);
  padding-top: 1.75rem; border-top: 1px solid var(--rule);
}
.case-meta dt{
  font-size: .68rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); margin-bottom: .4rem;
}
.case-meta dd{ margin: 0; font-size: .93rem; font-weight: 500; line-height: 1.45; }
@media (max-width: 720px){ .case-meta{ grid-template-columns: repeat(2, minmax(0,1fr)); gap: 1.25rem; } }

.approach{ counter-reset: step; }
.approach .item{
  display: grid; grid-template-columns: 3.2rem minmax(0,1fr);
  gap: 1.25rem;
  padding-block: 1.6rem;
  border-top: 1px solid var(--rule);
}
.approach .item:last-child{ border-bottom: 1px solid var(--rule); }
.approach .item::before{
  counter-increment: step;
  content: "0" counter(step);
  font-family: var(--display); font-size: 1rem; color: var(--accent);
  font-variation-settings: "opsz" 20;
  padding-top: .2rem;
}
.approach h4{ margin-bottom: .35rem; }
.approach p{ color: var(--muted); font-size: .96rem; }
@media (max-width: 560px){
  .approach .item{ grid-template-columns: 2.4rem minmax(0,1fr); gap: .9rem; }
}

.flow{
  display: flex; flex-wrap: wrap; align-items: center; gap: .55rem;
  padding: clamp(1.25rem, 3vw, 1.9rem);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 6px;
}
.flow span{
  font-family: var(--sans); font-size: .84rem; font-weight: 600;
  letter-spacing: .02em;
  padding: .5rem .85rem;
  background: var(--accent-wash); color: var(--accent-deep);
  border-radius: 999px;
  white-space: nowrap;
}
.flow em{ color: var(--rule); font-style: normal; font-size: 1.1rem; line-height: 1; }

.pull{
  border-left: 2px solid var(--accent);
  padding: .35rem 0 .35rem 1.5rem;
  margin: clamp(2rem, 4vw, 3rem) 0;
}

.compare{
  display: grid; grid-template-columns: repeat(3, minmax(0,1fr));
  gap: 1px; background: var(--rule);
  border: 1px solid var(--rule); border-radius: 6px; overflow: hidden;
}
.compare > div{ background: var(--paper); padding: clamp(1.15rem, 2.5vw, 1.6rem); }
.compare h4{ margin-bottom: .3rem; font-family: var(--sans); font-size: .98rem; font-weight: 600; letter-spacing: 0; }
.compare .where{
  font-size: .68rem; font-weight: 600; letter-spacing: .13em; text-transform: uppercase;
  color: var(--accent); margin-bottom: .75rem;
}
.compare ul{ margin: 0; padding-left: 1.05rem; font-size: .89rem; color: var(--muted); line-height: 1.6; }
@media (max-width: 700px){ .compare{ grid-template-columns: 1fr; } }

.split-list{
  display: grid; grid-template-columns: repeat(2, minmax(0,1fr));
  gap: clamp(1.5rem, 4vw, 3rem);
}
@media (max-width: 700px){ .split-list{ grid-template-columns: 1fr; } }
.checks{ list-style: none; margin: 0; padding: 0; }
.checks li{
  position: relative; padding-left: 1.6rem; margin-bottom: .7rem;
  font-size: .95rem; color: var(--ink-2);
}
.checks li::before{
  content: ""; position: absolute; left: 0; top: .55em;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
}

.tags{ display: flex; flex-wrap: wrap; gap: .5rem; }
.tag{
  font-size: .78rem; font-weight: 500; letter-spacing: .01em;
  padding: .42rem .85rem; border-radius: 999px;
  border: 1px solid var(--rule); color: var(--ink-2);
  background: var(--paper);
}

/* Slide gallery */
.slides{ display: grid; gap: 1rem; grid-template-columns: repeat(2, minmax(0,1fr)); }
.slides .frame{ box-shadow: var(--shadow-sm); border: 1px solid var(--rule); background: var(--paper); }
.slides .frame img{ object-fit: contain; }
.slides .wide{ grid-column: 1 / -1; }
@media (max-width: 640px){ .slides{ grid-template-columns: 1fr; } }

/* Next project */
.next-case{
  display: grid; grid-template-columns: minmax(0,1fr) auto;
  gap: 2rem; align-items: center;
  padding-block: clamp(2.5rem, 5vw, 4rem);
  text-decoration: none;
  border-top: 1px solid var(--rule);
}
.next-case:hover h3{ color: var(--accent); }
.next-case h3{ transition: color .2s ease; }
@media (max-width: 620px){ .next-case{ grid-template-columns: 1fr; gap: 1.25rem; } }

/* ---------- Timeline / experience ---------- */

/* Timeline with a drawn spine.
   The line lives in its own grid column so it never needs absolute maths,
   and each segment draws itself downward as its entry comes into view -
   so scrolling the page literally draws the timeline. */

.tl{ list-style: none; margin: 0; padding: 0; }

.tl-item{
  display: grid;
  grid-template-columns: minmax(0, .24fr) 2.25rem minmax(0, 1fr);
  gap: 0 clamp(.5rem, 1.6vw, 1.25rem);
}

.tl-when{
  padding-block: clamp(1.9rem, 3.5vw, 2.9rem) clamp(1.6rem, 3vw, 2.4rem);
  font-size: .82rem; font-weight: 500; color: var(--muted);
  letter-spacing: .01em;
}
.tl-when .place{ display: block; margin-top: .3rem; font-size: .78rem; }

/* Spine column */
.tl-mark{ position: relative; }
.tl-mark::before,
.tl-mark::after{
  content: "";
  position: absolute; top: 0; bottom: 0; left: 50%;
  width: 1px; margin-left: -.5px;
}
.tl-mark::before{ background: var(--rule); }
.tl-mark::after{
  background: var(--accent);
  transform: scaleY(0); transform-origin: top;
  transition: transform 1.1s var(--ease);
}
.tl-item.in .tl-mark::after{ transform: scaleY(1); }

.tl-mark .dot{
  position: absolute; left: 50%; top: clamp(2.05rem, 3.6vw, 3rem);
  width: 9px; height: 9px; margin-left: -4.5px;
  border-radius: 50%;
  background: var(--bone); border: 1.5px solid var(--rule);
  transform: scale(.5); opacity: 0;
  transition: transform .6s var(--ease) .25s, opacity .5s var(--ease) .25s,
              background .4s ease .25s, border-color .4s ease .25s;
  z-index: 1;
}
.tl-item.in .tl-mark .dot{
  transform: scale(1); opacity: 1;
  background: var(--accent); border-color: var(--accent);
}
.tl-item.is-now .tl-mark .dot{ box-shadow: 0 0 0 5px var(--accent-wash); }

.tl-body{
  padding-block: clamp(1.9rem, 3.5vw, 2.9rem) clamp(1.6rem, 3vw, 2.4rem);
  min-width: 0;
}

.tl-role{
  font-family: var(--sans); font-size: .78rem; font-weight: 600;
  letter-spacing: .1em; text-transform: uppercase; color: var(--accent);
  margin-bottom: .55rem;
}
.tl-item h3{ margin-bottom: .7rem; }
.tl-item ul{ margin: .9rem 0 0; padding-left: 1.1rem; color: var(--ink-2); font-size: .96rem; }
.tl-item li{ margin-bottom: .5rem; }
.tl-item li::marker{ color: var(--accent); }

/* "Now" badge for ongoing roles */
.now{
  display: inline-flex; align-items: center; gap: .4rem;
  font-size: .6rem; font-weight: 600; letter-spacing: .13em; text-transform: uppercase;
  color: var(--accent-deep); background: var(--accent-wash);
  padding: .25rem .6rem .25rem .5rem; border-radius: 999px;
  margin-left: .55rem; vertical-align: middle;
}
.now::before{
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent);
  animation: nowpulse 2.6s ease-in-out infinite;
}
@keyframes nowpulse{
  0%, 100%{ opacity: 1; transform: scale(1); }
  50%     { opacity: .3; transform: scale(.75); }
}

.tags-sm .tag{ font-size: .72rem; padding: .3rem .68rem; }
.tl-figure{ margin: 1.5rem 0 0; max-width: 460px; }
.tl-figure figcaption{
  font-size: .78rem; color: var(--muted); margin-top: .6rem; line-height: 1.45;
}

@media (max-width: 760px){
  .tl-item{ grid-template-columns: 1.5rem minmax(0,1fr); }
  .tl-when{
    grid-column: 2; padding-block: clamp(1.6rem,4vw,2rem) 0;
    order: -1;
  }
  .tl-mark{ grid-column: 1; grid-row: 1 / span 2; }
  .tl-body{ grid-column: 2; padding-top: .6rem; }
  .tl-mark .dot{ top: 1.85rem; }
  .tl-figure{ max-width: none; }
}

/* ---- Section rail (Experience page) ---- */

.rail{
  position: fixed; right: clamp(1rem, 2.2vw, 2rem); top: 50%;
  transform: translateY(-50%);
  z-index: 55;
  display: grid; gap: 1rem;
}
.rail a{
  display: flex; align-items: center; justify-content: flex-end; gap: .65rem;
  text-decoration: none; color: var(--muted);
  font-size: .68rem; font-weight: 600; letter-spacing: .11em; text-transform: uppercase;
  transition: color .3s ease;
}
.rail .lbl{
  opacity: 0; transform: translateX(6px);
  transition: opacity .4s var(--ease), transform .4s var(--ease);
  white-space: nowrap;
}
.rail a:hover .lbl, .rail a.active .lbl{ opacity: 1; transform: none; }
.rail i{
  display: block; width: 20px; height: 2px; flex: none;
  background: var(--rule);
  transition: width .45s var(--ease), background .3s ease;
}
.rail a:hover{ color: var(--ink-2); }
.rail a:hover i{ background: var(--ink-2); }
.rail a.active{ color: var(--ink); }
.rail a.active i{ width: 38px; background: var(--accent); }

@media (max-width: 1220px){ .rail{ display: none; } }
@media (prefers-reduced-motion: reduce){
  .rail .lbl{ opacity: 1; transform: none; }
  .now::before{ animation: none; }
  .tl-mark::after{ transition: none; }
  .tl-mark .dot{ transition: none; }
}

.stat-row{
  display: grid; grid-template-columns: repeat(4, minmax(0,1fr));
  gap: 1px; background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 6px; overflow: hidden;
}
.stat-row > div{ background: var(--bone); padding: clamp(1.25rem, 3vw, 1.9rem); }
.stat-row .n{
  font-family: var(--display); font-size: clamp(1.9rem, 4vw, 2.9rem);
  font-variation-settings: "opsz" 100;
  line-height: 1; letter-spacing: -0.02em; color: var(--ink);
  margin-bottom: .5rem;
}
.stat-row .l{ font-size: .84rem; color: var(--muted); line-height: 1.45; }
@media (max-width: 760px){ .stat-row{ grid-template-columns: repeat(2, minmax(0,1fr)); } }

/* ---------- About ---------- */

/* Mosaic sized to the photos it holds: a wide feature, a portrait beside it,
   then a band of three. Row height drives the geometry, so every edge lines up. */
/* Masonry via CSS columns. Because every photo now keeps its own
   proportions, a fixed-row grid would either crop or leave gaps -
   columns simply flow around the differing heights. */
.photo-strip{
  columns: 3;
  column-gap: clamp(.6rem, 1.4vw, 1rem);
}
.photo-strip > *{
  break-inside: avoid;
  margin-bottom: clamp(.6rem, 1.4vw, 1rem);
}
.photo-strip .frame{ border-radius: 4px; }

@media (max-width: 820px){ .photo-strip{ columns: 2; } }
@media (max-width: 520px){ .photo-strip{ columns: 1; } }

.beyond{
  display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 1px; background: var(--rule);
  border: 1px solid var(--rule); border-radius: 6px; overflow: hidden;
}
.beyond > div{ background: var(--bone); padding: 1.3rem 1.4rem; }
.beyond h4{
  font-family: var(--sans); font-size: .93rem; font-weight: 600;
  letter-spacing: 0; margin-bottom: .3rem;
}
.beyond p{ font-size: .86rem; color: var(--muted); line-height: 1.5; }

/* ---------- Resume page ---------- */

/* ---------- Résumé page ----------
   The PDF is shown as a rendered page image rather than an <object> embed:
   embedded PDFs simply don't render on iOS Safari and several Android
   browsers, which is exactly where a recruiter opens a link. The image
   works everywhere, and the real PDF is one click away. */

.doc{
  max-width: 860px; margin-inline: auto;
  background: var(--paper);
  border: 1px solid var(--rule);
  box-shadow: 0 1px 2px rgba(23,19,15,.06), 0 34px 70px -34px rgba(23,19,15,.5);
}
.doc .frame{ box-shadow: none; background: var(--paper); border-radius: 0; }
.doc .frame img{ width: 100%; height: auto; }

.facts{
  display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 1px; background: var(--rule);
  border: 1px solid var(--rule); border-radius: 6px; overflow: hidden;
}
.facts > div{ background: var(--bone); padding: 1.1rem 1.3rem; }
.facts dt{
  font-size: .66rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); margin-bottom: .35rem;
}
.facts dd{ margin: 0; font-size: .95rem; font-weight: 500; line-height: 1.4; }

/* Text résumé - label column beside the entries */
.rsec{
  display: grid;
  grid-template-columns: minmax(0, .22fr) minmax(0, 1fr);
  gap: clamp(.75rem, 3vw, 3rem);
  padding-block: clamp(1.75rem, 3vw, 2.6rem);
  border-top: 1px solid var(--rule);
}
.rsec-label{
  font-family: var(--sans); font-size: .68rem; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
  margin: 0; padding-top: .25rem;
}
.rentry{ margin-bottom: 1.75rem; }
.rentry:last-child{ margin-bottom: 0; }
.rhead{
  display: grid; grid-template-columns: minmax(0,1fr) auto;
  gap: .2rem 1.5rem; align-items: baseline;
}
.rhead .org{ font-weight: 600; font-size: 1.02rem; }
.rhead .meta{ font-size: .8rem; color: var(--muted); white-space: nowrap; text-align: right; }
.rrole{
  font-size: .84rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--accent); margin: .3rem 0 0;
}
.rentry ul{
  margin: .65rem 0 0; padding-left: 1.05rem;
  color: var(--ink-2); font-size: .93rem; line-height: 1.6;
}
.rentry li{ margin-bottom: .35rem; }
.rentry li::marker{ color: var(--accent); }
.rnote{ font-size: .9rem; color: var(--muted); margin: .4rem 0 0; }

@media (max-width: 700px){
  .rsec{ grid-template-columns: 1fr; gap: .9rem; }
  .rhead{ grid-template-columns: 1fr; }
  .rhead .meta{ text-align: left; white-space: normal; }
}

/* ---------- Contact ---------- */

/* ---------- Contact page ---------- */

.contact-hero{
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .7fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
@media (max-width: 860px){
  .contact-hero{ grid-template-columns: 1fr; }
  .contact-portrait{ max-width: 320px; }
}
.contact-portrait{ margin: 0; }
.contact-portrait .frame{ border-radius: 6px; box-shadow: var(--shadow-md); }
.contact-portrait figcaption{ margin-top: .7rem; }

.avail{
  display: flex; align-items: center; gap: .55rem;
  margin: 1.25rem 0 0;
  font-size: .84rem; font-weight: 500; color: var(--ink-2);
}
.avail .now{ margin-left: 0; }

.mega-mail{
  display: inline-block;
  font-family: var(--display);
  font-size: clamp(1.6rem, 5.5vw, 3.4rem);
  font-variation-settings: "opsz" 100;
  letter-spacing: -.02em; line-height: 1.1;
  color: #FBF8F3; text-decoration: none;
  word-break: break-word;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 2px;
  transition: background-size .6s var(--ease), color .3s ease;
  padding-bottom: .12em;
}
.mega-mail:hover{ background-size: 100% 2px; }

.contact-links{ display: grid; gap: 0; border-top: 1px solid rgba(255,255,255,.16); }
.contact-links a{
  display: grid; grid-template-columns: minmax(0, .3fr) minmax(0,1fr) auto;
  gap: 1rem; align-items: center;
  padding-block: 1.5rem;
  border-bottom: 1px solid rgba(255,255,255,.16);
  text-decoration: none;
  transition: padding-inline .3s cubic-bezier(.2,.7,.3,1), background .3s ease;
}
.contact-links a:hover{ background: rgba(255,255,255,.05); padding-inline: .9rem; }
.contact-links .k{
  font-size: .72rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: #A79C8E;
}
.contact-links .v{
  font-family: var(--display); font-size: clamp(1.1rem, 2.4vw, 1.7rem);
  font-variation-settings: "opsz" 40; letter-spacing: -0.01em;
  color: #FBF8F3; word-break: break-word;
}
.contact-links .arr{ color: #A79C8E; transition: transform .25s ease; }
.contact-links a:hover .arr{ transform: translateX(5px); }
@media (max-width: 700px){
  .contact-links a{ grid-template-columns: minmax(0,1fr) auto; }
  .contact-links .k{ grid-column: 1 / -1; }
}

/* ---------- Footer ---------- */

.footer{
  background: var(--ink); color: #A79C8E;
  padding-block: clamp(3rem, 6vw, 4.5rem) 2rem;
}
.footer a{ color: #F3EDE4; text-decoration: none; }
.footer a:hover{ color: #fff; text-decoration: underline; text-underline-offset: 3px; }
.footer-top{
  display: grid; grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, .8fr));
  gap: 2rem;
  padding-bottom: 2.5rem;
  border-bottom: 1px solid rgba(255,255,255,.14);
}
@media (max-width: 760px){ .footer-top{ grid-template-columns: 1fr; gap: 2rem; } }
.footer h3{ color: #FBF8F3; margin-bottom: .8rem; }
.footer .fh{
  font-size: .72rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: #7D7267; margin-bottom: .9rem;
}
.footer ul{ list-style: none; margin: 0; padding: 0; }
.footer li{ margin-bottom: .55rem; font-size: .92rem; }
.footer-bot{
  padding-top: 1.75rem;
  display: flex; flex-wrap: wrap; gap: .75rem 1.5rem; justify-content: space-between;
  font-size: .8rem;
}

/* ==========================================================================
   MOTION
   One easing curve does most of the work: --ease is an expo-out, which
   starts fast and settles slowly. That's what makes movement read as
   "considered" rather than "animated".
   ========================================================================== */

:root{
  --ease: cubic-bezier(.16, 1, .3, 1);
  --ease-soft: cubic-bezier(.33, 1, .68, 1);
}

/* ---- Block reveal ---- */

[data-rise]{
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .9s var(--ease), transform .9s var(--ease);
  transition-delay: var(--d, 0ms);
}
[data-rise].in{ opacity: 1; transform: none; }
/* Containers whose headings do their own line-wipe shouldn't also slide */
[data-rise].has-lines{ transform: none; }

/* ---- Heading line wipe ----
   Headings are split on their authored line breaks; each line sits in an
   overflow-hidden box and rises out of it, one after another. */

.ln{
  display: block;
  overflow: hidden;
  padding: 0 .08em .12em;
  margin: 0 -.08em -.12em;
}
.ln-i{
  display: block;
  transform: translateY(120%);
  transition: transform 1.05s var(--ease);
  transition-delay: calc(var(--d, 0ms) + var(--i, 0) * 105ms);
}
.split.lines-in .ln-i{ transform: none; }

/* ---- Image reveal ----
   The frame unmasks upward while the photo inside settles back from a
   slight scale — the photo appears to arrive rather than pop. */

.frame{ clip-path: inset(0 0 0 0); }
.frame.will-reveal{ clip-path: inset(0 0 101% 0); }
.frame.revealed{
  clip-path: inset(0 0 0 0);
  transition: clip-path 1.15s var(--ease);
  transition-delay: var(--d, 0ms);
}

/* ---- Scroll progress ---- */

.scroll-progress{
  position: fixed; top: 0; left: 0; right: 0;
  height: 2px; z-index: 90;
  pointer-events: none;
  background: transparent;
}
.scroll-progress span{
  display: block; height: 100%; width: 100%;
  background: var(--accent);
  transform: scaleX(0); transform-origin: 0 50%;
  transition: transform .12s linear;
}

/* ---- Nav retract ---- */

.nav{ transition: transform .55s var(--ease), border-color .25s ease, background .25s ease; }
.nav.retract{ transform: translateY(-102%); }

/* ---- Page transition ---- */

@view-transition{ navigation: auto; }
::view-transition-old(root){ animation: vt-out .28s var(--ease-soft) both; }
::view-transition-new(root){ animation: vt-in .5s var(--ease) both; }
@keyframes vt-out{ to{ opacity: 0; transform: translateY(-8px); } }
@keyframes vt-in{ from{ opacity: 0; transform: translateY(14px); } }

/* Fallback for browsers without view transitions */
.page-veil{
  position: fixed; inset: 0; z-index: 200;
  background: var(--bone);
  opacity: 0; pointer-events: none;
  transition: opacity .32s var(--ease-soft);
}
.page-veil.on{ opacity: 1; pointer-events: all; }

/* ---- Hero scroll cue ---- */

.scroll-cue{
  display: inline-flex; align-items: center; gap: .7rem;
  margin-top: clamp(2rem, 4vw, 3rem);
  font-size: .7rem; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted);
}
.scroll-cue i{
  display: block; width: 44px; height: 1px;
  background: var(--rule); position: relative; overflow: hidden;
}
.scroll-cue i::after{
  content: ""; position: absolute; inset: 0;
  background: var(--accent);
  transform-origin: 0 50%;
  animation: cue 2.4s var(--ease-soft) infinite;
}
@keyframes cue{
  0%   { transform: scaleX(0); transform-origin: 0 50%; }
  45%  { transform: scaleX(1); transform-origin: 0 50%; }
  55%  { transform: scaleX(1); transform-origin: 100% 50%; }
  100% { transform: scaleX(0); transform-origin: 100% 50%; }
}

/* ---- Paper grain ----
   A very low-opacity noise layer. Invisible as an effect; it just stops
   the flat cream from looking like flat cream. */

body::after{
  content: "";
  position: fixed; inset: 0; z-index: 1;
  pointer-events: none;
  opacity: .028;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* Content sits above the grain. The nav is deliberately NOT in this list -
   it keeps position:sticky and z-index:60 from its own rule, and listing it
   here would override both (equal specificity, later in the file). */
main, .footer{ position: relative; z-index: 2; }

/* ---- Reduced motion: everything above becomes instant ---- */

@media (prefers-reduced-motion: reduce){
  [data-rise]{ opacity: 1; transform: none; transition: none; }
  .ln-i{ transform: none; transition: none; }
  .frame, .frame.will-reveal{ clip-path: none; }
  .frame.will-reveal img, .frame img{ transform: none; transition: none; }
  .frame img, .work-card, .work-row .frame{ transition: none !important; }
  .nav.retract{ transform: none; }
  .scroll-cue i::after{ animation: none; transform: scaleX(1); }
  .page-veil{ display: none; }
  ::view-transition-old(root), ::view-transition-new(root){ animation: none; }
}

/* ==========================================================================
   POLISH
   Small stuff: the difference between a page that works and one that feels
   made. Every hover here moves toward the accent and settles on the same
   curve as everything else.
   ========================================================================== */

/* Typography niceties */
h3, h4, .lede{ text-wrap: balance; }
p, li, dd{ text-wrap: pretty; }
html{ scroll-padding-top: 90px; }

/* The eyebrow rule draws itself in with its block */
.eyebrow::before{
  transform: scaleX(1);
  transform-origin: left;
  transition: transform .9s var(--ease) .12s;
}
[data-rise]:not(.in) .eyebrow::before{ transform: scaleX(0); }

/* Three words */
.words div{ transition: background .45s var(--ease); }
.words div:hover{ background: var(--bone-2); }
.words dt{ transition: color .35s ease; }
.words div:hover dt{ color: var(--accent); }

/* Work cards - the title picks up a rule on hover */
.work-card h3{
  width: fit-content;                 /* so the rule matches the text, not the column */
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0% 1.5px;
  transition: background-size .55s var(--ease);
  padding-bottom: 2px;
}
.work-card:hover h3{ background-size: 100% 1.5px; }
.work-card .tagline{ transition: letter-spacing .5s var(--ease); }
.work-card:hover .tagline{ letter-spacing: .16em; }

/* Work rows */
.work-row .num{ transition: color .35s ease; }
.work-row:hover .num{ color: var(--accent); }

/* Approach steps */
.approach .item{ transition: background .4s var(--ease); }
.approach .item:hover{ background: var(--bone-2); }
.approach .item::before{ transition: color .35s ease, transform .45s var(--ease); }
.approach .item:hover::before{ transform: translateX(3px); color: var(--accent-deep); }

/* Comparison + beyond cells */
.compare > div, .beyond > div, .stat-row > div{
  transition: background .45s var(--ease);
}
.compare > div:hover, .beyond > div:hover, .stat-row > div:hover{
  background: var(--bone-2);
}

/* Timeline - the marker reacts, the row stays calm */
.tl-item .tl-body, .tl-item .tl-when{ transition: color .3s ease; }
.tl-item.in:hover .tl-mark .dot{ transform: scale(1.45); }
.tl-item:hover .tl-when{ color: var(--ink-2); }
.tl-role{ transition: letter-spacing .5s var(--ease); }
.tl-item:hover .tl-role{ letter-spacing: .13em; }

/* Tags */
.tag{ transition: border-color .3s ease, color .3s ease, transform .35s var(--ease); }
.tag:hover{ border-color: var(--accent); color: var(--accent-deep); transform: translateY(-1px); }

/* Slides sit up slightly on hover */
.slides .frame{ transition: transform .55s var(--ease), box-shadow .55s var(--ease); }
.slides .frame:hover{ transform: translateY(-4px); box-shadow: var(--shadow-md); }

/* Footer links */
.footer a{ transition: color .25s ease; }

/* Skip link */
.skip{
  position: absolute; left: -9999px; top: 0; z-index: 300;
  background: var(--ink); color: var(--bone);
  padding: .75rem 1.25rem; border-radius: 0 0 6px 0;
  font-size: .88rem; font-weight: 500; text-decoration: none;
}
.skip:focus{ left: 0; }
#main:focus{ outline: none; }

/* ==========================================================================
   LIGHTBOX
   The infographic and the deck slides carry real detail. Being able to open
   them full-size is the difference between showing work and showing a
   thumbnail of work.
   ========================================================================== */

.frame.zoomable{ cursor: zoom-in; }
.frame.zoomable::after{
  content: "View";
  position: absolute; right: .75rem; bottom: .75rem;
  font-family: var(--sans); font-size: .68rem; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink); background: rgba(251,248,243,.94);
  padding: .4rem .7rem; border-radius: 999px;
  box-shadow: var(--shadow-sm);
  opacity: 0; transform: translateY(6px);
  transition: opacity .35s var(--ease), transform .35s var(--ease);
  pointer-events: none;
}
.frame.zoomable:hover::after,
.frame.zoomable:focus-visible::after{ opacity: 1; transform: none; }
.frame.zoomable.img-missing::after{ content: "Add " attr(data-file); opacity: 1; transform: none; }

.lb{
  position: fixed; inset: 0; z-index: 250;
  display: grid; grid-template-rows: auto 1fr auto;
  background: rgba(16,13,10,.94);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden;
  transition: opacity .4s var(--ease), visibility .4s;
}
.lb.open{ opacity: 1; visibility: visible; }

.lb-bar{
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 1rem clamp(1rem, 3vw, 2rem);
  color: #CFC5B8; font-size: .8rem; letter-spacing: .06em;
}
/* The image is absolutely positioned inside the stage rather than centred as
   a grid item. A percentage max-height on a grid item does not reliably
   resolve against a 1fr track, so tall images kept their natural height and
   were clipped; an inset-positioned box is always definite, so both
   max-width and max-height bind and the whole picture fits. */
.lb-stage{
  position: relative;
  min-height: 0;
  overflow: hidden;
}
.lb-stage img{
  position: absolute;
  inset: 0;
  margin: auto;                 /* centres both ways */
  /* The gutter lives in max-width, not in `inset`: percentages on an
     absolutely positioned box resolve against the containing block, so an
     inset gutter would not be subtracted and the image would overflow it. */
  max-width: calc(100% - 2 * clamp(.75rem, 3vw, 2.5rem));
  max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
  border-radius: 3px;
  box-shadow: 0 30px 80px -30px rgba(0,0,0,.7);
  opacity: 0; transform: scale(.985);
  transition: opacity .4s var(--ease), transform .5s var(--ease);
  cursor: zoom-in;
}
.lb-stage img.ready{ opacity: 1; transform: none; }

/* Fit-to-screen is right for seeing the whole thing, but the résumé and the
   infographics carry small text. Clicking the picture switches to actual
   size and lets the stage scroll. */
.lb-stage.zoomed{ overflow: auto; overscroll-behavior: contain; }
.lb-stage.zoomed img{
  position: static;
  margin: auto;
  max-width: none; max-height: none;
  width: auto; height: auto;
  cursor: zoom-out;
  transform: none;
}
.lb-zoomhint{
  position: absolute; left: 50%; bottom: .75rem;
  transform: translateX(-50%);
  font-size: .68rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: #CFC5B8; background: rgba(16,13,10,.72);
  padding: .35rem .75rem; border-radius: 999px;
  pointer-events: none;
  opacity: 0; transition: opacity .35s var(--ease);
}
.lb-stage:hover .lb-zoomhint{ opacity: 1; }

.lb-cap{
  padding: 1rem clamp(1rem, 3vw, 2rem) 1.75rem;
  color: #A79C8E; font-size: .85rem; line-height: 1.5;
  text-align: center; max-width: 70ch; margin-inline: auto;
}

.lb button{
  background: transparent; border: 1px solid rgba(255,255,255,.22);
  color: #F3EDE4; cursor: pointer;
  width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 1.1rem; line-height: 1;
  transition: background .3s ease, border-color .3s ease, transform .3s var(--ease);
}
.lb button:hover{ background: rgba(255,255,255,.12); border-color: rgba(255,255,255,.5); }
.lb button:disabled{ opacity: .3; cursor: default; }
.lb button:not(:disabled):hover{ transform: scale(1.06); }
.lb-nav{ display: flex; gap: .6rem; }

@media (prefers-reduced-motion: reduce){
  .lb, .lb-stage img, .frame.zoomable::after{ transition: none; }
  .lb-stage img{ opacity: 1; transform: none; }
}

/* Focus */
:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

@media (prefers-reduced-motion: reduce){
  .eyebrow::before, [data-rise]:not(.in) .eyebrow::before{ transform: scaleX(1); transition: none; }
  .work-card h3{ transition: none; }
  .words div, .approach .item, .tl-item, .compare > div,
  .beyond > div, .stat-row > div, .slides .frame, .tag{ transition: none; }
}

/* ---------- Print ----------
   Ctrl+P on the résumé page should produce a clean document, not a
   screenshot of a website. */
@media print{
  .nav, .footer, .rail, .scroll-progress, .lb, .page-veil, .skip,
  .no-print, .btn-row, .scroll-cue{ display: none !important; }

  [data-rise], .split, .frame{
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }
  .ln-i{ transform: none !important; }

  html, body{ background: #fff !important; color: #000; font-size: 10.5pt; }
  body::after{ display: none; }                 /* no grain on paper */

  .band, .band-ink, .facts > div, .stat-row > div{
    background: #fff !important; color: #000 !important;
  }
  .band-ink h2, .band-ink h3, .band-ink .lede{ color: #000 !important; }

  .section, .section-tight{ padding-block: .5rem !important; }
  .wrap, .wrap-narrow{ max-width: none; padding-inline: 0; }

  .rsec{ break-inside: avoid; padding-block: .75rem; }
  .rentry{ break-inside: avoid; margin-bottom: .9rem; }
  .rrole{ color: #000 !important; }
  .rentry li::marker{ color: #000; }

  a{ color: #000; text-decoration: none; }
  h1{ font-size: 20pt; }
  h2{ font-size: 14pt; }

  @page{ margin: 14mm; }
}

/* ==========================================================================
   EDITOR
   Only ever visible to a signed-in editor — the Worker injects editor.js
   solely when a valid session cookie is present, so none of this reaches a
   normal visitor.
   ========================================================================== */

.gw-bar{
  position: fixed; left: 50%; bottom: 1.25rem;
  transform: translateX(-50%);
  z-index: 400;
  display: flex; align-items: center; gap: .7rem;
  padding: .45rem .5rem .45rem .95rem;
  background: rgba(23,19,15,.9);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  color: #F3EDE4;
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 999px;
  box-shadow: 0 10px 30px -14px rgba(0,0,0,.55);
  font-family: var(--sans); font-size: .82rem;
  max-width: calc(100vw - 1.5rem);
}
.gw-dot{
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); flex: none;
  animation: nowpulse 2.6s ease-in-out infinite;
}
.gw-state{ display: flex; align-items: center; gap: .5rem; flex: none; }
.gw-label{ font-weight: 600; letter-spacing: .1em; text-transform: uppercase; font-size: .68rem; }

/* The status line is the only elastic part of the bar: it takes what space is
   left and truncates, so a long message can never push the buttons onto a
   second row. The full text stays available on hover via title. */
.gw-status{
  color: #A79C8E; font-size: .78rem;
  flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gw-status:empty{ display: none; }
.gw-status.gw-ok{ color: #8FBF8F; }
.gw-status.gw-warn{ color: #E8927C; }
/* A hint describes the mode rather than reporting an event, so it is the first
   thing dropped when space is short. */
.gw-status.gw-hint{ color: #8C8175; }
.gw-actions{ display: flex; gap: .35rem; flex: none; }
.gw-btn{
  font: inherit; font-size: .78rem; font-weight: 500;
  padding: .45rem .85rem; border-radius: 999px; cursor: pointer;
  white-space: nowrap;
  background: #F3EDE4; color: var(--ink); border: 1px solid #F3EDE4;
  transition: background .2s ease, color .2s ease, opacity .2s ease;
}
.gw-mini{ display: none; }
.gw-btn:hover:not(:disabled){ background: var(--accent); border-color: var(--accent); color: #fff; }
/* A disabled button must not be the loudest thing on the bar. Fading the
   filled style leaves a muddy grey block, so drop to the ghost outline
   instead — nothing to act on reads as nothing to look at. */
.gw-btn:disabled{
  background: transparent; color: rgba(243,237,228,.38);
  border-color: rgba(255,255,255,.14);
  cursor: default;
}
.gw-ghost{ background: transparent; color: #F3EDE4; border-color: rgba(255,255,255,.3); }

/* Sortable items */
.gw-item{ position: relative; outline: 1px dashed transparent; transition: outline-color .2s ease; }
.gw-item:hover{ outline-color: var(--rule); outline-offset: 6px; }
.gw-tools{
  position: absolute; top: .4rem; right: .4rem; z-index: 5;
  display: flex; gap: .25rem;
  opacity: 0; transition: opacity .2s ease;
}
.gw-item:hover .gw-tools, .gw-item:focus-within .gw-tools{ opacity: 1; }
.gw-grip, .gw-eye{
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--rule); background: var(--bone); color: var(--ink);
  cursor: grab; font-size: .85rem; line-height: 1; display: grid; place-items: center;
  box-shadow: var(--shadow-sm);
}
.gw-grip:active{ cursor: grabbing; }
.gw-hidden{ opacity: .32; }
.gw-hidden::after{
  content: "Hidden"; position: absolute; top: .5rem; left: .5rem;
  font-size: .62rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  background: var(--ink); color: var(--bone); padding: .25rem .55rem; border-radius: 999px;
}
.gw-placeholder{
  border: 1px dashed var(--accent);
  border-radius: 6px; background: var(--accent-wash);
}
.gw-drag{
  position: fixed !important; z-index: 401;
  pointer-events: none; opacity: .95;
  box-shadow: 0 26px 60px -20px rgba(0,0,0,.5);
  border-radius: 6px; overflow: hidden;
}
body.gw-dragging{ user-select: none; cursor: grabbing; }

/* Editable text */
.gw-text{ cursor: text; border-radius: 3px; transition: box-shadow .2s ease; }
.gw-text:hover{ box-shadow: 0 0 0 2px var(--accent-wash); }
.gw-editing{ box-shadow: 0 0 0 2px var(--accent) !important; outline: none; }

/* On a phone the bar stops pretending to be a floating pill and becomes a
   proper action bar: one row of equal buttons, short labels, and no standing
   chrome. Only messages that report something appear, on their own line. */
@media (max-width: 620px){
  .gw-bar{
    left: .5rem; right: .5rem; bottom: .5rem;
    transform: none; max-width: none;
    border-radius: 16px;
    padding: .45rem .5rem;
    gap: .4rem;
    flex-wrap: wrap; justify-content: center;
  }
  .gw-state{ order: -1; padding-top: .15rem; }
  .gw-status{
    order: -1; flex: 0 1 auto;
    text-align: center; font-size: .72rem; padding: .15rem .25rem 0;
  }
  .gw-status.gw-hint{ display: none; }
  .gw-actions{ width: 100%; gap: .35rem; }
  .gw-btn{ flex: 1 1 0; font-size: .72rem; padding: .55rem .4rem; }
  .gw-full{ display: none; }
  .gw-mini{ display: inline; }
}
@media print{ .gw-bar, .gw-tools{ display: none !important; } }

/* Image controls */
.gw-img-tools{
  position: absolute; left: .5rem; bottom: .5rem; z-index: 6;
  opacity: 0; transition: opacity .2s ease;
}
.frame:hover .gw-img-tools, .gw-img-tools:focus-within{ opacity: 1; }
.gw-mini{ font-size: .7rem !important; padding: .35rem .7rem !important; }
.gw-add{
  display: inline-flex; align-items: center; gap: .5rem;
  margin-top: 1rem; padding: .6rem 1.1rem;
  font: inherit; font-size: .82rem; font-weight: 500;
  border: 1px dashed var(--accent); border-radius: 999px;
  background: var(--accent-wash); color: var(--accent-deep);
  cursor: pointer;
  transition: background .25s ease, transform .25s var(--ease);
}
.gw-add:hover{ background: var(--bone-2); transform: translateY(-1px); }
.gw-add span{ font-size: 1.1rem; line-height: 1; }
.gw-del{
  width: 30px; height: 30px; border-radius: 50%;
  border: 1px solid var(--rule); background: var(--bone); color: var(--clay);
  cursor: pointer; font-size: .8rem; line-height: 1;
  display: grid; place-items: center; box-shadow: var(--shadow-sm);
}
.gw-del:hover{ background: var(--clay); color: #fff; border-color: var(--clay); }
@media print{ .gw-img-tools, .gw-add{ display: none !important; } }

/* ---------- Section / block editing ---------- */

.gw-section{ position: relative; outline: 1px dashed transparent; transition: outline-color .2s ease; }
.gw-section:hover{ outline-color: var(--rule); outline-offset: 4px; }
.gw-sec-hidden{ opacity: .34; }

.gw-sec-bar{
  position: absolute; top: .5rem; left: .5rem; z-index: 20;
  display: flex; align-items: center; gap: .5rem;
  padding: .3rem .4rem .3rem .5rem;
  background: var(--ink); color: #F3EDE4;
  border-radius: 999px; box-shadow: var(--shadow-sm);
  font-size: .7rem;
  opacity: 0; transform: translateY(-4px);
  transition: opacity .2s ease, transform .2s ease;
}
.gw-section:hover > .gw-sec-bar,
.gw-sec-bar:focus-within{ opacity: 1; transform: none; }
.gw-sec-name{ letter-spacing: .1em; text-transform: uppercase; font-weight: 600; opacity: .75; }
.gw-sec-grip{
  background: none; border: 0; color: inherit; cursor: grab;
  font-size: .95rem; line-height: 1; padding: .15rem .1rem;
}
.gw-sec-grip:active{ cursor: grabbing; }
.gw-sec-acts{ display: flex; gap: .15rem; }
.gw-sec-acts button{
  background: rgba(255,255,255,.12); border: 0; color: #F3EDE4;
  width: 22px; height: 22px; border-radius: 50%;
  cursor: pointer; font-size: .7rem; line-height: 1;
  display: grid; place-items: center;
  transition: background .2s ease;
}
.gw-sec-acts button:hover{ background: var(--accent); color: #fff; }

.gw-sec-dragging{ opacity: .5; }
.gw-sec-placeholder{
  border: 2px dashed var(--accent);
  background: var(--accent-wash);
  border-radius: 8px; margin: .5rem 0;
}

.gw-sec-add{
  display: block; width: calc(100% - 2rem); margin: 0 auto;
  padding: .55rem 1rem;
  font: inherit; font-size: .78rem; font-weight: 500;
  border: 1px dashed var(--rule); border-radius: 999px;
  background: transparent; color: var(--muted);
  cursor: pointer; opacity: 0;
  transition: opacity .2s ease, border-color .25s ease, color .25s ease, background .25s ease;
}
.gw-section:hover > .gw-sec-add{ opacity: 1; }
.gw-sec-add:hover{ border-color: var(--accent); color: var(--accent-deep); background: var(--accent-wash); }
.gw-sec-add span{ font-size: 1rem; line-height: 1; }
.gw-sec-add-tail{ opacity: 1; margin-block: 2rem 5rem; }

/* Block picker */
.gw-picker{
  position: fixed; inset: 0; z-index: 420;
  background: rgba(16,13,10,.55);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  display: grid; place-items: center; padding: 1.5rem;
  opacity: 0; visibility: hidden;
  transition: opacity .3s var(--ease), visibility .3s;
}
.gw-picker.open{ opacity: 1; visibility: visible; }
.gw-picker-inner{
  background: var(--bone); border-radius: 10px;
  padding: clamp(1.25rem, 3vw, 2rem);
  width: min(760px, 100%); max-height: 85vh; overflow-y: auto;
  box-shadow: var(--shadow-md);
}
.gw-picker-head{ display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1.25rem; }
.gw-picker-head .eyebrow{ margin: 0; }
.gw-cards{ display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: .75rem; }
.gw-card{
  text-align: left; font: inherit; cursor: pointer;
  padding: 1rem 1.1rem; border-radius: 8px;
  border: 1px solid var(--rule); background: var(--paper);
  transition: border-color .25s ease, transform .3s var(--ease), background .25s ease;
}
.gw-card:hover{ border-color: var(--accent); transform: translateY(-2px); background: var(--accent-wash); }
.gw-card strong{ display: block; font-size: .95rem; margin-bottom: .25rem; }
.gw-card span{ font-size: .82rem; color: var(--muted); line-height: 1.45; }

@media print{ .gw-sec-bar, .gw-sec-add, .gw-picker{ display: none !important; } }

/* ---------- View mode ----------
   Still signed in, but every editing affordance is out of the way so the
   page can be judged exactly as a visitor sees it. Only the toolbar stays,
   so there is always a way back. */

body.gw-viewing .gw-sec-bar,
body.gw-viewing .gw-sec-add,
body.gw-viewing .gw-tools,
body.gw-viewing .gw-img-tools{
  display: none !important;
}
body.gw-viewing .gw-section,
body.gw-viewing .gw-item{ outline: none !important; }
body.gw-viewing .gw-text{ cursor: inherit; }
body.gw-viewing .gw-text:hover{ box-shadow: none; }

/* Hidden things stay hidden in view mode, exactly as a visitor gets them */
body.gw-viewing .gw-sec-hidden,
body.gw-viewing .gw-hidden{ display: none !important; }

/* The toolbar shrinks back and loses the "live" pulse while viewing */
body.gw-viewing .gw-dot{ animation: none; background: var(--muted); }
.gw-mode{ background: transparent; color: #F3EDE4; border-color: rgba(255,255,255,.45); }
.gw-mode:hover{ color: var(--ink); border-color: #F3EDE4; }
body.gw-viewing .gw-mode{ background: var(--accent); border-color: var(--accent); color: #fff; }
body.gw-viewing .gw-mode:hover{ color: var(--ink); }
