:root{
    --ink:#0A0A0A;
    --white:#FFFFFF;
    --gray-1:#D9D9D9;
    --gray-2:#C4C4C4;
    --gray-3:#EDEDED;
    --stone:#70706C;   /* was #8C8C88 — darkened to pass WCAG AA contrast (4.97:1 on white) */
    --line: rgba(10,10,10,0.12);
    --ease-1: cubic-bezier(.22,1,.36,1);
    --gap-section: clamp(80px, 12vh, 160px);
  }

  *{margin:0;padding:0;box-sizing:border-box;}
  html{background:var(--white);}
  body{
    background:transparent;
    color:var(--ink);
    font-family:'Space Grotesk', sans-serif;
    overflow-x:hidden;
    cursor:none;
    -webkit-tap-highlight-color:transparent;
  }
  /* cursor:none so links/buttons show our custom cursor, not the native finger.
     The browser's UA sheet sets a{cursor:pointer}, which beats the body's
     inherited cursor:none — so it must be overridden explicitly here. Touch
     devices get the native cursor back via the pointer:coarse block above. */
  a, button{ touch-action:manipulation; cursor:none; }
  /* animated full-page background layer (white <-> black around the gallery) */
  .page-bg{
    position:fixed; inset:0;
    background:var(--white);
    z-index:-1;
    pointer-events:none;
  }
  /* faint full-site column grid overlay — 12 columns on desktop, reducing on
     smaller screens. Built from real flex children (JS) rather than a
     percentage-based gradient, so the columns are always distributed exactly
     evenly by the browser — no subpixel-rounding drift toward one edge.
     Spans full-bleed (no side margin) so the lines reach both viewport edges. */
  .col-grid{
    position:fixed; inset:0;
    z-index:-1;
    display:flex;
    pointer-events:none;
    transition:opacity .4s var(--ease-1);
  }
  .col-grid span{
    flex:1 1 0%;
    height:100%;
    border-right:1px solid rgba(10,10,10,0.035);
  }
  .col-grid span:first-child{ border-left:1px solid rgba(10,10,10,0.035); }
  body.dark .col-grid span{ border-color:rgba(255,255,255,0.045); }
  /* About page only, slightly dimmer than the general dark-mode value above —
     needs the .about-page class too (not just .dark) to outrank that rule's
     specificity */
  body.dark.about-page .col-grid span{ border-color:rgba(255,255,255,0.028); }

  /* ---------- loading screen ---------- */
  .loading-screen{
    position:fixed; inset:0;
    z-index:2000;
    background:var(--white);
    overflow:hidden;
    transition:opacity .7s var(--ease-1), visibility .7s;
  }
  .loading-screen.ls-hidden{ opacity:0; visibility:hidden; pointer-events:none; }
  .loading-screen .ls-grid{ z-index:0; }
  body.ls-lock{ overflow:hidden; }

  /* Lenis smooth scroll — required base styles (from Lenis docs) */
  html.lenis, html.lenis body{ height:auto; }
  .lenis.lenis-smooth{ scroll-behavior:auto !important; }
  .lenis.lenis-smooth [data-lenis-prevent]{ overscroll-behavior:contain; }
  .lenis.lenis-stopped{ overflow:hidden; }
  .lenis.lenis-smooth iframe{ pointer-events:none; }

  /* editorial corner metadata */
  .ls-meta{
    position:absolute; z-index:2;
    display:flex; flex-direction:column; gap:3px;
    font-family:'JetBrains Mono', monospace;
    font-size:0.66rem;
    letter-spacing:0.08em;
    text-transform:uppercase;
    color:var(--stone);
    padding:clamp(20px,5vw,64px);
  }
  .ls-meta span:first-child{ color:var(--ink); }
  .ls-tl{ top:0; left:0; align-items:flex-start; text-align:left; }
  .ls-tr{ top:0; right:0; align-items:flex-end; text-align:right; }
  .ls-bl{ bottom:0; left:0; align-items:flex-start; text-align:left; }
  .ls-br{ bottom:0; right:0; align-items:flex-end; text-align:right; }
  .ls-pct{ font-size:0.9rem; color:var(--ink) !important; letter-spacing:0.04em; }

  .ls-frame{
    position:absolute;
    top:50%; left:50%;
    transform:translate(-50%,-50%);
    z-index:1;
    width:min(620px, 74vw);
    aspect-ratio:16/9;
    display:flex; flex-direction:column; align-items:center; justify-content:center;
    gap:4px;
  }

  /* "Severance"-style number field — a quiet grid of digits that react to
     the cursor: the ones near it swap to a word from the site's own
     vocabulary and light up, everything else stays as dim, idle digits */
  .ls-numfield{
    position:absolute; inset:0;
    z-index:0;
    display:grid;
    pointer-events:none;
    overflow:hidden;
  }
  .ls-num{
    display:flex; align-items:center; justify-content:center;
    font-family:'JetBrains Mono', monospace;
    font-size:0.62rem;
    color:var(--ink);
    opacity:0;
    transition:opacity .55s var(--ease-1), color .55s var(--ease-1);
    user-select:none;
    white-space:nowrap;
  }
  .ls-num.is-near{
    opacity:0.55;
    color:var(--ink);
  }
  .ls-num.is-featured{
    opacity:1;
    color:var(--ink);
    font-weight:600;
  }
  @media (max-width:700px){
    .ls-numfield{ display:none; }
  }
  .ls-index{
    font-family:'JetBrains Mono', monospace;
    font-size:0.68rem;
    letter-spacing:0.2em;
    text-transform:uppercase;
    color:var(--stone);
    margin-bottom:6px;
  }
  .ls-word{
    font-family:'Playfair Display', serif;
    font-size:clamp(2.6rem,7vw,5rem);
    line-height:1;
    color:var(--ink);
    letter-spacing:-0.01em;
    text-align:center;
    font-weight:500;
  }
  /* progress bar — track + animated fill, tied to the real loading percentage */
  .ls-rule{
    width:min(420px, 62vw);
    height:2px;
    background:rgba(10,10,10,0.14);
    margin:1.1em auto 0;
    position:relative;
    overflow:hidden;
  }
  .ls-rule-fill{
    position:absolute; top:0; left:0; bottom:0;
    width:0%;
    background:var(--ink);
    transition:width .6s cubic-bezier(.4,0,.2,1);
  }
  .ls-sub{
    font-family:'JetBrains Mono', monospace;
    font-size:0.66rem;
    letter-spacing:0.16em;
    text-transform:uppercase;
    color:var(--stone);
    margin-top:28px;
  }
  @media (max-width:520px){
    .ls-meta{ font-size:0.56rem; padding:16px; }
    .ls-tr, .ls-bl{ display:none; }
  }

  @media (pointer: coarse){
    body{cursor:auto;}
    /* the custom cursor is hidden on touch (.cursor{display:none}); restore the
       native cursor on interactive elements so a touch+mouse hybrid isn't left
       with no cursor at all where we set cursor:none for the custom-cursor UI */
    a, button, .index-row, .we-title, .we-img, .rw-row a, .sg-item,
    .contact-submit, .pv-close, .hobby-item{ cursor:auto; }
  }
  ::selection{ background:var(--ink); color:var(--white); }

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

  .eyebrow, .mono{
    font-family:'JetBrains Mono', monospace;
    letter-spacing:0.1em;
    text-transform:uppercase;
    font-size:0.72rem;
    color:var(--stone);
  }

  h1,h2,h3{
    font-family:'Fraunces', serif;
    font-weight:500;
    line-height:0.98;
    letter-spacing:-0.01em;
  }

  /* ---------- grain overlay ---------- */
  .grain{
    position:fixed; inset:0; z-index:9998;
    pointer-events:none;
    opacity:0.05;
    mix-blend-mode:multiply;
  }

  /* ---------- custom cursor ---------- */
  .cursor{
    position:fixed; top:0; left:0;
    width:14px; height:14px;
    border-radius:50%;
    background:var(--ink);
    border:1.5px solid transparent;
    pointer-events:none;
    z-index:9999;
    transform:translate(-50%,-50%);
    transition: width .3s var(--ease-1), height .3s var(--ease-1), background-color .3s, border-color .3s;
    will-change:transform;
  }
  @media (pointer: coarse){ .cursor{display:none;} }

  /* ---------- nav ---------- */
  .nav{
    position:fixed; top:0; left:0; right:0;
    z-index:500;
    display:flex; align-items:center; justify-content:space-between;
    padding:26px clamp(20px,5vw,64px);
    padding-top:max(26px, env(safe-area-inset-top));
    padding-left:max(clamp(20px,5vw,64px), env(safe-area-inset-left));
    padding-right:max(clamp(20px,5vw,64px), env(safe-area-inset-right));
    background:transparent;
    transition:
      transform .5s var(--ease-1),
      background-color .45s var(--ease-1),
      padding .4s var(--ease-1);
  }
  /* scrolled past the hero: compact, edge-to-edge, opaque bar so it stays
     legible over whatever section (light or dark) happens to sit beneath it */
  .nav.nav-scrolled{
    padding-top:14px; padding-bottom:14px;
    padding-left:20px; padding-right:20px;
    background:rgba(255,255,255,0.92);
    backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px);
  }
  body.dark .nav.nav-scrolled{ background:rgba(10,10,10,0.92); }
  /* hidden while actively scrolling down; slides back in on scroll up */
  .nav.nav-hidden{ transform:translateY(-100%); }
  /* the divider line: inset to the content margins in the hero state, but
     full-width (edge to edge) once the nav is in its compact scrolled state */
  .nav::after{
    content:'';
    position:absolute;
    left:max(clamp(20px,5vw,64px), env(safe-area-inset-left));
    right:max(clamp(20px,5vw,64px), env(safe-area-inset-right));
    bottom:0;
    height:1.5px;
    background:var(--ink);
    transition:background-color .5s var(--ease-1), left .4s var(--ease-1), right .4s var(--ease-1);
  }
  .nav.nav-scrolled::after{ left:0; right:0; }
  body.dark .nav::after{ background:rgba(255,255,255,0.3); }
  body.dark .nav.nav-scrolled::after{ background:rgba(255,255,255,0.3); }
  .nav-logo{
    color:var(--ink);
    display:flex;
    align-items:center;
  }
  /* blackletter "L" logo — inline SVG, fill:currentColor so it inherits the
     nav color (ink on light pages, white on the dark About page / scrolled) */
  .nav-logo-mark{
    height:1.9rem;
    width:auto;
    display:block;
  }
  .nav-right{ display:flex; align-items:center; gap:clamp(24px,4vw,48px); }
  .nav-links{ display:flex; gap:clamp(18px,3vw,40px); list-style:none; }
  .nav-links a{
    font-family:Verdana, sans-serif;
    font-weight:500;
    font-size:0.72rem;
    letter-spacing:0.1em;
    text-transform:uppercase;
    color:var(--stone);
    position:relative;
    padding-bottom:3px;
  }
  .nav-links a::after{
    content:'';
    position:absolute; left:0; bottom:0;
    width:0; height:1px;
    background:var(--ink);
    transition:width .4s var(--ease-1);
  }
  .nav-links a:hover{ color:var(--ink); }
  .nav-links a:hover::after{ width:100%; }
  .nav-links li.active a{ color:var(--ink); }
  .nav-links li.active a::after{ width:100%; }

  /* Contact stands out from the other plain text links — a filled pill,
     like a small CTA button, instead of just another underline-on-hover
     link. */
  .nav-links li.nav-cta a{
    color:var(--white);
    background:var(--ink);
    padding:7px 20px;
    border-radius:0;
    transition:background-color .3s var(--ease-1), color .3s var(--ease-1);
  }
  .nav-links li.nav-cta a::after{ display:none; }
  .nav-links li.nav-cta a:hover{ background:#2b2b27; color:var(--white); }
  body.dark .nav-links li.nav-cta a{ background:var(--white); color:var(--ink); }
  body.dark .nav-links li.nav-cta a:hover{ background:#e9e9e6; color:var(--ink); }

  /* ---------- language switch (ES / EN) ----------
     Sits before .nav-links inside .nav-right; kept visually separate with
     extra gap plus its own divider line on the right (between it and the
     links) rather than sitting flush against them. */
  .lang-switch{
    display:flex; align-items:center; gap:6px;
    padding-right:clamp(18px,3vw,32px);
    border-right:1px solid rgba(10,10,10,0.14);
  }
  body.dark .lang-switch{ border-right-color:rgba(255,255,255,0.18); }
  .lang-opt{
    font-family:Verdana, sans-serif;
    font-weight:500;
    font-size:0.78rem;
    letter-spacing:0.02em;
    color:var(--stone);
    background:none;
    border:none;
    padding:0;
    cursor:none;
    transition:color .3s var(--ease-1);
  }
  .lang-opt:hover{ color:var(--ink); }
  .lang-opt.is-active{ color:var(--ink); text-decoration:underline; text-underline-offset:3px; }
  .lang-sep{ font-family:Verdana, sans-serif; font-size:0.78rem; color:var(--stone); }
  body.dark .lang-opt{ color:rgba(255,255,255,0.55); }
  body.dark .lang-opt:hover,
  body.dark .lang-opt.is-active{ color:var(--white); }
  body.dark .lang-sep{ color:rgba(255,255,255,0.4); }

  /* dark mode (while the gallery's black background is active) */
  .nav-logo, .nav-links a{ transition:color .5s var(--ease-1); }
  body.dark .nav-logo{ color:var(--white); }
  body.dark .nav-links a{ color:rgba(255,255,255,0.55); }
  body.dark .nav-links a:hover,
  body.dark .nav-links li.active a{ color:var(--white); }
  body.dark .nav-links a::after{ background:var(--white); }

  /* the scrolled bar is always an opaque white pill, so its text always
     stays dark for contrast — regardless of the page's light/dark section */
  body.dark .nav.nav-scrolled .nav-logo{ color:var(--white); }
  body.dark .nav.nav-scrolled .nav-links a{ color:rgba(255,255,255,0.55); }
  body.dark .nav.nav-scrolled .nav-links a:hover,
  body.dark .nav.nav-scrolled .nav-links li.active a{ color:var(--white); }
  body.dark .nav.nav-scrolled .nav-links a::after{ background:var(--white); }
  /* the CTA pill keeps its own ink-on-white colors even when scrolled — the
     generic scrolled-link rule above would otherwise turn its text near-white
     on its already-white background, making it unreadable */
  body.dark .nav.nav-scrolled .nav-links li.nav-cta a{ color:var(--ink); }
  body.dark .nav.nav-scrolled .nav-links li.nav-cta a:hover{ color:var(--ink); }

  /* dark styling for the logos + footer sections, active once the page
     has turned black after the gallery */
  .logos-section, .logos-section *, footer, footer *{
    transition:color .5s var(--ease-1), border-color .5s var(--ease-1), background-color .5s var(--ease-1);
  }
  body.dark .logos-section{ border-top-color:rgba(255,255,255,0.14); }
  body.dark .logos-head .eyebrow{ color:rgba(255,255,255,0.5); }
  body.dark .logos-head h2{ color:var(--white); }
  body.dark .logo-item{ color:var(--white); }
  body.dark footer{ border-top-color:rgba(255,255,255,0.14); }
  body.dark footer .eyebrow{ color:rgba(255,255,255,0.5); }
  body.dark footer h2{ color:var(--white); }
  body.dark .foot-email{ color:var(--white); border-bottom-color:var(--white); }
  body.dark .foot-bottom{ border-top-color:rgba(255,255,255,0.14); }
  body.dark .foot-bottom .mono{ color:rgba(255,255,255,0.5); }
  body.dark .foot-links a{ color:rgba(255,255,255,0.55); }
  body.dark .foot-links a:hover{ color:var(--white); }

  /* dark styling for everything else on the page — so the manual theme
     toggle can darken the WHOLE site, not just the gallery-and-after zone */
  .hero, .hero *,
  .work-grid, .work-grid *,
  .case-study, .case-study *,
  .related-work, .related-work *,
  .scroll-cue, .caption-row, .caption-row *{
    transition:color .5s var(--ease-1), border-color .5s var(--ease-1), background-color .5s var(--ease-1);
  }
  /* hero */
  body.dark .hero-eyebrow{ color:rgba(255,255,255,0.6); }
  body.dark .hero-name{ color:var(--white); }
  body.dark .hero-divider{ background:rgba(255,255,255,0.3); }
  body.dark .hero-role{ color:var(--white); }
  body.dark .hero-bio{ color:rgba(255,255,255,0.55); }
  body.dark .hero-meta-item dt{ color:var(--white); }
  body.dark .hero-meta-item dd{ color:rgba(255,255,255,0.5); }
  body.dark .scroll-cue{ color:rgba(255,255,255,0.28); }
  /* hero quickview index */
  body.dark .index-head{ color:rgba(255,255,255,0.5); }
  body.dark .index-row .ix-num{ color:rgba(255,255,255,0.5); }
  body.dark .index-row .ix-name{ color:var(--white); }
  body.dark .index-row .ix-type{ color:rgba(255,255,255,0.5); }
  /* the hover sweep inverts too: white highlight, dark text, on a dark page */
  body.dark .ix-cell .ix-bg{ background:var(--white); }
  body.dark .index-row:hover .ix-txt{ color:var(--ink); }
  /* case-study banner */
  body.dark .case-media{ background:#232320; }
  /* the 3 project slides */
  body.dark .we-num, body.dark .we-title{ color:var(--white); }
  body.dark .we-meta{ color:rgba(255,255,255,0.5); }
  body.dark .we-divider{ background:rgba(255,255,255,0.3); }
  body.dark .we-img{ background:#232320; }
  body.dark .we-tag{ color:var(--white); }
  /* caption row under the banner */
  body.dark .caption-row .mono{ color:rgba(255,255,255,0.5); }
  /* related work list */
  body.dark .rw-eyebrow{ color:rgba(255,255,255,0.5); }
  body.dark .rw-list{ border-top-color:rgba(255,255,255,0.14); }
  body.dark .rw-row{ border-bottom-color:rgba(255,255,255,0.14); }
  body.dark .rw-title{ color:var(--white); }
  body.dark .rw-type-txt{ color:rgba(255,255,255,0.5); }
  body.dark .rw-icon{ color:rgba(255,255,255,0.5); }
  body.dark .rw-row a:hover .rw-icon{ color:var(--white); }
  /* the type-label sweep also inverts on a dark page */
  body.dark .rw-type-bg{ background:var(--white); }
  body.dark .rw-row:hover .rw-type-txt{ color:var(--ink); }

  /* ---------- hero ---------- */
  .hero{
    position:relative;
    min-height:66vh;
    min-height:66dvh;
    display:flex;
    flex-direction:column;
    justify-content:center;
    padding:104px clamp(20px,5vw,64px) 0;
  }
  .hero-inner{
    display:grid;
    grid-template-columns: 1fr 1fr;
    gap:clamp(24px,5vw,60px);
    align-items:start;
  }
  .eyebrow.hero-eyebrow{
    font-family:'JetBrains Mono', monospace;
    color:var(--ink);
    margin-bottom:26px;
    letter-spacing:0.16em;
  }
  .hero-name{
    font-family:'Playfair Display', serif;
    font-weight:500;
    line-height:1.08;
    letter-spacing:-0.005em;
    font-size:clamp(2.5rem, 7vw, 5.7rem);
    color:var(--ink);
    display:inline-block;
  }
  .hero-name .line{ display:block; overflow:hidden; padding-bottom:0.1em; margin-bottom:-0.1em; }
  .hero-name .line span{ display:inline-block; will-change:transform; }
  .hero-divider{
    height:1px;
    width:0;
    background:var(--ink);
    margin:clamp(28px,4vw,44px) 0 clamp(24px,3vw,34px);
    transform-origin:left center;
  }
  .hero-role{
    font-family:Verdana, sans-serif;
    font-weight:400;
    font-size:clamp(0.78rem,1.1vw,0.88rem);
    color:var(--ink);
    letter-spacing:0.08em;
    text-transform:uppercase;
  }
  .hero-bio{
    font-family:Verdana, sans-serif;
    font-weight:400;
    margin-top:16px;
    max-width:44ch;
    font-size:clamp(0.98rem,1.2vw,1.05rem);
    line-height:1.55;
    color:var(--stone);
  }
  .hero-meta{
    margin-top:clamp(34px,5vw,52px);
    display:flex;
    gap:clamp(40px,8vw,90px);
  }
  .hero-meta-item dt{
    font-family:'JetBrains Mono', monospace;
    font-size:0.7rem;
    letter-spacing:0.14em;
    text-transform:uppercase;
    color:var(--ink);
    margin-bottom:8px;
  }
  .hero-meta-item dd{
    font-family:'JetBrains Mono', monospace;
    font-size:0.7rem;
    letter-spacing:0.14em;
    text-transform:uppercase;
    color:var(--stone);
  }

  /* ---------- hero right: project index ---------- */
  .hero-right{ position:relative; align-self:stretch; display:flex; flex-direction:column; margin-top:clamp(40px,6vw,90px); }
  .index-head{
    font-family:'JetBrains Mono', monospace;
    font-size:0.7rem;
    letter-spacing:0.16em;
    text-transform:uppercase;
    color:var(--stone);
    text-align:right;
    margin-bottom:22px;
  }
  .index-list{ list-style:none; display:flex; flex-direction:column; }
  .index-row{
    display:grid;
    grid-template-columns: auto minmax(0,14ch) minmax(0,24ch);
    justify-content:end;
    align-items:center;
    column-gap:20px;
    padding:clamp(9px,1.1vw,13px) 0;
    cursor:none;
    position:relative;
  }
  /* full-row link (see buildIndex in script.js) */
  .index-row .ix-hit{ position:absolute; inset:0; z-index:2; cursor:none; }
  .index-row .ix-hit:focus-visible{ outline:1px solid currentColor; outline-offset:4px; }
  .index-row .ix-num,
  .index-row .ix-name,
  .index-row .ix-type{
    font-family:Verdana, sans-serif;
    font-size:clamp(0.72rem,0.95vw,0.82rem);
    letter-spacing:0.14em;
    text-transform:uppercase;
    white-space:nowrap;
  }
  /* the highlight only spans the text: an inline box that wipes in L→R.
     Uses left:0 + width (not scaleX) so the reveal is unambiguously anchored
     to the cell's own left edge, regardless of how the cell itself is aligned
     within its column (e.g. right-aligned name/type columns). */
  .ix-cell{ position:relative; display:inline-block; padding:3px 7px; margin:-3px -7px; }
  .ix-cell .ix-bg{
    position:absolute; top:0; bottom:0; left:0;
    width:0%;
    background:var(--ink);
    transition:width .4s var(--ease-1);
    z-index:0;
  }
  .ix-cell .ix-txt{ position:relative; z-index:1; transition:color .3s var(--ease-1); }
  .index-row .ix-num{ color:var(--stone); }
  .index-row .ix-name{ color:var(--ink); }
  .index-row .ix-type{ color:var(--stone); }
  .ix-num{ justify-self:start; }
  .ix-name{ justify-self:end; text-align:right; }
  .ix-type{ justify-self:end; text-align:right; }
  /* hover: each column's highlight sweeps in L→R, staggered per column,
     and its text turns white in sync with its own sweep */
  .index-row:hover .ix-cell .ix-bg{ width:100%; }
  .index-row:hover .ix-txt{ color:var(--white); }
  .index-row .ix-num .ix-bg,  .index-row .ix-num .ix-txt{ transition-delay:0s; }
  .index-row .ix-name .ix-bg, .index-row .ix-name .ix-txt{ transition-delay:.09s; }
  .index-row .ix-type .ix-bg, .index-row .ix-type .ix-txt{ transition-delay:.18s; }

  /* floating preview image that follows the cursor over the index */
  .index-float{
    position:fixed; top:0; left:0;
    width:clamp(230px,22vw,320px);
    aspect-ratio:3/4;
    z-index:600;
    pointer-events:none;
    opacity:0;
    transform:translate(-50%,-50%) scale(0.9);
    will-change:transform, opacity;
  }
  .index-float img{
    width:100%; height:100%;
    object-fit:cover;
    filter:contrast(1.03);
    display:block;
    border-radius:2px;
  }
  /* the quickview index is a hover-driven feature (each row reveals a floating
     preview). Hide it — and its preview — on touch devices AND on mobile-width
     viewports, so it's gone both on real phones/tablets and when a desktop
     window is narrowed down to mobile size. */
  @media (pointer:coarse), (max-width:640px){ .index-float{ display:none; } }
  @media (pointer:coarse), (max-width:640px){ .hero-right{ display:none; } }

  .scroll-cue{
    margin-top:calc(var(--gap-section) * 0.5);
    margin-bottom:20px;
    padding:0 clamp(20px,5vw,64px);
    font-size:clamp(1.3rem,2.6vw,1.7rem);
    color:var(--gray-2);
    text-transform:uppercase;
    letter-spacing:0.01em;
  }

  /* ---------- section shell ---------- */
  section{ position:relative; }

  /* ---------- caption row ---------- */
  .caption-row{
    display:flex; align-items:flex-start;
    padding:16px clamp(20px,5vw,64px) 28px;
  }
  .caption-row .mono{ color:var(--stone); padding-top:1px; }

  /* ---------- work grid ---------- */
  .work-grid{
    position:relative;
    margin-top:clamp(16px,2.5vh,32px);
  }
  .work-item{
    width:100%;
    display:flex;
    margin-top:clamp(36px,6vh,72px);
  }
  .work-item:first-child{ margin-top:0; }

  /* ---------- editorial project slide (white version) ---------- */
  .work-editorial{
    flex-direction:column;
    padding:clamp(28px,4vw,56px) clamp(20px,5vw,64px);
  }
  .we-top{
    display:grid;
    grid-template-columns: auto 1fr auto;
    align-items:end;
    gap:clamp(16px,3vw,32px);
    padding-bottom:clamp(16px,2.4vw,26px);
  }
  .we-num-col{ display:flex; align-items:flex-end; }
  .we-num{
    font-family:'Playfair Display', serif;
    font-weight:700;
    font-size:clamp(1.6rem,3vw,2.3rem);
    line-height:0.9;
    color:var(--ink);
  }
  .we-title{
    font-family:'Playfair Display', serif;
    font-weight:500;
    font-size:clamp(1.8rem,3.6vw,3rem);
    line-height:0.95;
    color:var(--ink);
    cursor:none;
  }
  /* small country flag shown inline next to a project title (New Balance = Chile) */
  .we-flag{
    display:inline-block;
    width:0.51em;
    height:auto;
    aspect-ratio:3/2;
    margin-left:0.5em;
    vertical-align:baseline;
    border:1px solid rgba(10,10,10,0.15);
    border-radius:1px;
  }
  body.dark .we-flag{ border-color:rgba(255,255,255,0.25); }
  .we-meta{
    font-size:0.7rem;
    letter-spacing:0.14em;
    color:var(--stone);
    white-space:nowrap;
  }
  .we-divider{ height:1.5px; background:var(--ink); }
  .we-grid{
    display:grid;
    grid-template-columns:repeat(3,1fr);
    gap:2px;
    align-items:start;
    padding-top:clamp(24px,3.2vw,40px);
  }
  .we-grid-2col{ grid-template-columns:repeat(2,1fr); }
  .we-img{
    position:relative;
    display:block;
    overflow:hidden;
    background:var(--gray-1);
    cursor:none;
    aspect-ratio:4/3;
  }
  .we-grid-2col .we-img{ aspect-ratio:2/1; }
  .we-img img,
  .we-img video{
    width:100%; height:100%;
    object-fit:cover;
    display:block;
    transition:transform .6s var(--ease-1);
    filter:contrast(1.03);
  }
  .we-img:hover img,
  .we-img:hover video{ transform:scale(1.05); }

  /* floating callout on thumbnail hover: a dot at the cursor + leader line to
     a small dark card (annotation style). Lives on <body>, fixed to the
     viewport, follows the pointer via JS, never intercepts clicks. */
  .work-callout{
    position:fixed;
    inset:0;
    z-index:60;
    pointer-events:none;
    opacity:0;
    transition:opacity .3s var(--ease-1);
  }
  .work-callout.is-visible{ opacity:1; }
  .wc-svg{
    position:absolute;
    inset:0;
    width:100%; height:100%;
    overflow:visible;
  }
  .wc-line{ stroke:var(--ink); stroke-width:1; }
  .wc-dot{
    position:absolute;
    width:11px; height:11px;
    margin:-5.5px 0 0 -5.5px;
    border-radius:50%;
    background:var(--ink);
  }
  /* no container box anymore — each wrapped text line is painted on its
     own (see .wc-tline below), like a highlighter marker. */
  .wc-card{
    position:absolute;
    width:clamp(240px,22vw,320px);
    display:flex;
    flex-direction:column;
    gap:8px;
  }
  .wc-desc, .wc-cta{ margin:0; }
  .wc-mark{
    display:block;
    font-family:Verdana, sans-serif;
    font-weight:300;
    font-size:0.9rem;
    line-height:1.15;
  }
  .wc-mark-cta{
    font-family:'JetBrains Mono', monospace;
    font-size:0.64rem;
    letter-spacing:0.14em;
    line-height:1.15;
  }
  /* reveal: replicates the hero quick-index's hover sweep (.ix-cell/.ix-bg
     — a solid background wiping in left-to-right while the text flips to
     white), applied per wrapped text line instead of per column. Each
     line's .wc-tline-bg/.wc-tline-txt get the same transition-delay (set
     inline in JS, LINE_STEP ms apart) so the lines sweep in one after
     another, same stagger idea as .index-row's 0 / .09s / .18s.
     (named wc-tline, not wc-line, to avoid colliding with the SVG leader
     line's existing .wc-line class) */
  .wc-tline{
    position:relative;
    display:block;
    width:max-content;
    max-width:100%;
    padding:0.2em 0.4em;
  }
  .wc-mark-cta .wc-tline{ padding:0.4em 0.5em; }
  .wc-tline-bg{
    position:absolute; top:0; bottom:0; left:0;
    width:0%;
    background:var(--ink);
    transition:width .4s var(--ease-1);
    z-index:0;
  }
  .wc-tline-txt{
    position:relative; z-index:1;
    color:var(--ink);
    transition:color .3s var(--ease-1);
  }
  .wc-tline.v .wc-tline-bg{ width:100%; }
  .wc-tline.v .wc-tline-txt{ color:#fff; }
  .we-foot{
    display:flex; align-items:center; justify-content:space-between;
    padding-top:clamp(16px,2.4vw,26px);
    gap:20px;
  }
  .we-tags{ display:flex; align-items:center; gap:20px; flex-wrap:wrap; }
  .we-tag{ font-size:0.62rem; letter-spacing:0.12em; text-transform:uppercase; color:var(--ink); border:none; border-radius:0; padding:4px 0; }
    @media (max-width:860px){
    .we-top{ grid-template-columns:1fr; gap:10px; }
    .we-num-col{ order:1; }
    .we-title{ order:2; font-size:clamp(2.2rem,9vw,3rem); }
    .we-meta{ order:3; }
    .we-grid{ grid-template-columns:1fr; }
    .we-grid-2col .we-img{ aspect-ratio:4/3; }
  }

  /* transition overlay: darkens the outgoing project right before the next
     one slides up and covers it (driven by scroll, see JS) */
  .tile-fade{
    position:absolute; inset:0;
    background:var(--ink);
    opacity:0;
    z-index:2;
    pointer-events:none;
  }
  .tile-wipe{
    position:absolute; inset:0;
    background:var(--ink);
    transform-origin:bottom;
    z-index:5;
  }

  /* ---------- case study panel ---------- */
  .case-study{
    margin-top:0;
  }
  .case-media{
    position:relative;
    display:block;
    /* fixed cinematic banner ratio at every viewport width (≈2.67:1), instead
       of a viewport-height that turned the banner too tall on tablet/portrait */
    aspect-ratio:8 / 3;
    background:var(--gray-1);
    overflow:hidden;
  }
  .case-media .noise-shape{
    position:absolute; inset:-15%;
    background:
      radial-gradient(38% 46% at 25% 30%, rgba(255,255,255,0.35), transparent 70%),
      radial-gradient(34% 42% at 78% 72%, rgba(0,0,0,0.10), transparent 70%);
    z-index:2;
    pointer-events:none;
  }
  .case-media img{
    position:absolute; inset:0;
    width:100%; height:100%;
    object-fit:cover;
    object-position:center;
    filter:contrast(1.03);
    z-index:1;
  }
  .case-media video{
    position:absolute; inset:0;
    width:100%; height:100%;
    object-fit:cover;
    object-position:center;
    filter:contrast(1.03);
    z-index:1;
  }
  /* mobile: New Era cover switches to the 4:5 video (see index.html) */
  @media (max-width:700px){
    .case-study:not(.case-study-b2b) .case-media{ aspect-ratio:4 / 5; }
  }

  /* ---------- B2B case study cover (live HTML, from Figma "Frame 41" +
     "Cover · Mobile"). Whole card is one link to case-study-b2b.html; the
     CTA is a visual span inside it (no nested links). Fonts: Playfair
     Display (title), JetBrains Mono (eyebrow / labels / CTA), Verdana
     (description + values) — no Inter / Space Grotesk. ---------- */
  /* more air between the 1st project (New Era) and the 2nd (B2B cover) */
  .case-study-b2b{ margin-top:clamp(56px,9vw,140px); margin-bottom:clamp(48px,7vw,112px); }
  /* quickview rows that open a project: keyboard focus ring */
  .index-row.is-link:focus-visible{ outline:1px solid currentColor; outline-offset:4px; }

  .hcv{
    display:block;
    position:relative;
    background:#f0f0f0;
    color:#0a0a0a;
    overflow:hidden;
  }
  .hcv-inner{ position:relative; min-height:calc(clamp(540px,54vw,1120px) * 0.72); container-type:inline-size; display:flex; align-items:center; }
  .hcv-text{
    position:relative; z-index:2;
    max-width:min(49vw,760px);
    padding:clamp(48px,6vw,88px) 24px clamp(48px,6vw,88px) clamp(20px,5vw,64px);
    width:100%;
    container-type:inline-size;
  }
  .hcv-eyebrow{ display:flex; align-items:center; gap:10px; }
  .hcv-dot{ width:6px; height:6px; border-radius:50%; background:#3355f0; flex:none; }
  /* same type size as the project captions (.mono: 0.72rem / 0.1em) */
  .hcv-eyebrow-txt{
    font-family:'JetBrains Mono', monospace;
    font-size:0.72rem; letter-spacing:0.1em; text-transform:uppercase;
    color:#5a5a5a; white-space:nowrap;
  }
  .hcv-eyebrow-mobile{ display:none; }
  .hcv-title{
    margin-top:36px;
    font-family:'Playfair Display', serif;
    font-weight:500;
    font-size:clamp(40px,4vw,66px);          /* fallback (no container units) */
    font-size:min(66px, 9.6cqw);             /* longest line = 9.91em → ~95% of the column */
    line-height:1.04;
    letter-spacing:-0.8px;
    color:#0a0a0a;
  }
  /* the three lines are fixed: "De la planilla de Excel" / "a un portal de
     pedidos" / "mayoristas" — never re-wrapped at any width */
  .hcv-l{ display:block; white-space:nowrap; }
  .hcv-title em{ font-style:italic; color:#8a8a8a; }
  .hcv-desc{
    margin-top:32px;
    font-family:Verdana, Geneva, sans-serif;
    font-size:clamp(15px,1.3vw,18px);
    line-height:1.5;
    color:#4a4a4a;
    max-width:520px;
  }
  .hcv-cta{
    margin-top:48px;
    display:inline-flex; align-items:center; gap:8px;
    background:#0a0a0a; color:#fff;
    padding:12px 20px; border-radius:999px;
    font-family:'JetBrains Mono', monospace; font-weight:500; font-size:12px;
    transition:background-color .25s ease;
  }
  .hcv-cta-label{ letter-spacing:1.2px; text-transform:uppercase; }
  .hcv-arrow{ transition:transform .25s ease; }
  .hcv:hover .hcv-cta{ background:#1f1f1f; }
  .hcv:hover .hcv-arrow{ transform:translateX(4px); }
  .hcv-visual{
    position:absolute; z-index:1;
    bottom:0; right:0;
    width:clamp(540px,54vw,1120px);
    /* the image's last ~2% of rows are fully transparent, so the base
       appeared to fade out; pushing it down 3.5% lets .hcv's overflow:hidden
       cut straight through the solid base — a clean edge at the bottom */
    transform:translateY(3.5%);
    pointer-events:none;
  }
  .hcv-visual img{ display:block; width:100%; max-width:none; height:auto; }

  @media (max-width:880px){
    /* stacked: eyebrow, title, description, then the monitor flush with the
       bottom edge. The CTA sits ON TOP of the image (same grid cell), in the
       empty top-left corner the tilted monitor leaves free. display:contents
       turns the text column's children into grid items of .hcv-inner. */
    .hcv-inner{ display:grid; grid-template-columns:minmax(0,1fr); padding:28px clamp(20px,5vw,64px) 0; min-height:0; }
    .hcv-text{ display:contents; }
    .hcv-eyebrow{ grid-row:1; gap:10px; }
    .hcv-title{ grid-row:2; }
    .hcv-desc{ grid-row:3; }
    .hcv-visual{ grid-row:4; grid-column:1; }
    .hcv-cta{ grid-row:4; grid-column:1; align-self:start; justify-self:start; position:relative; z-index:3; }

    .hcv-eyebrow-desktop{ display:none; }
    .hcv-eyebrow-mobile{ display:inline; }
    .hcv-title{ margin-top:20px; font-size:clamp(28px,9vw,44px); font-size:min(44px, 9.6cqw); line-height:1.06; letter-spacing:-0.6px; }
    .hcv-desc{ margin-top:16px; font-size:16px; max-width:none; }
    .hcv-visual{
      position:relative; bottom:auto; right:auto;
      width:100%; margin-top:20px;
      transform:translateY(3.5%);
    }
    .hcv-visual img{ width:152%; margin-left:-15%; }
    .hcv-cta{
      margin-top:20px;
      padding:12px 18px; gap:8px; font-size:12px;
    }
    .hcv-cta-label{ letter-spacing:1.1px; }
    .hcv-arrow{ font-size:13px; }
  }

  /* ---------- split grid ---------- */
  /* ---------- related work: external links list with hover preview ---------- */
  .related-work{
    position:relative;
    margin-top:var(--gap-section);
    padding:0 clamp(20px,5vw,64px) var(--gap-section);
  }
  .rw-eyebrow{ margin-bottom:26px; }
  .rw-list{
    list-style:none;
    border-top:1px solid var(--line);
  }
  .rw-row{ border-bottom:1px solid var(--line); }
  .rw-row a{
    display:flex;
    align-items:center;
    justify-content:space-between;
    gap:24px;
    padding:clamp(18px,2.6vw,30px) 2px;
    color:var(--ink);
    transition:opacity .35s var(--ease-1), padding-left .35s var(--ease-1);
    cursor:none;
  }
  .rw-row a:hover{ padding-left:14px; }
  .rw-title-group{
    display:flex;
    align-items:baseline;
    flex-wrap:wrap;
    gap:clamp(10px,1.6vw,20px);
    min-width:0;
  }
  .rw-title{
    font-family:'Playfair Display', serif;
    font-weight:500;
    font-size:clamp(1.8rem,4.4vw,3.2rem);
    line-height:1;
  }
  /* small "type" label — same black-sweep-to-white-text hover effect used in
     the hero's quickview index, but scoped to just this small text */
  .rw-type{
    position:relative;
    display:inline-block;
    padding:3px 7px;
    margin:-3px -7px;
    white-space:nowrap;
  }
  .rw-type-bg{
    position:absolute; top:0; bottom:0; left:0;
    width:0%;
    background:var(--ink);
    transition:width .4s var(--ease-1);
    z-index:0;
  }
  .rw-type-txt{
    position:relative; z-index:1;
    font-family:'JetBrains Mono', monospace;
    font-size:0.68rem;
    letter-spacing:0.14em;
    text-transform:uppercase;
    color:var(--stone);
    transition:color .3s var(--ease-1);
  }
  .rw-row:hover .rw-type-bg{ width:100%; }
  .rw-row:hover .rw-type-txt{ color:var(--white); }
  .rw-icon{
    width:22px; height:22px;
    flex-shrink:0;
    color:var(--stone);
    transition:transform .35s var(--ease-1), color .35s var(--ease-1);
  }
  .rw-row a:hover .rw-icon{ transform:translate(4px,-4px); color:var(--ink); }
  @media (max-width:600px){
    .rw-title-group{ flex-direction:column; align-items:flex-start; gap:4px; }
  }

  /* floating preview image that follows the cursor over the list */
  .rw-float{
    position:fixed; top:0; left:0;
    width:clamp(300px,28vw,420px);
    aspect-ratio:3/4;
    z-index:600;
    pointer-events:none;
    opacity:0;
    transform:translate(-50%,-50%) scale(0.9);
    will-change:transform, opacity;
  }
  .rw-float img{
    width:100%; height:100%;
    box-sizing:border-box;
    object-fit:cover;
    filter:grayscale(1) contrast(1.05);
    display:block;
    border:1px solid var(--ink);
    border-radius:2px;
  }
  @media (pointer:coarse){ .rw-float{ display:none; } }

  /* ---------- scroll-sync gallery ---------- */
  /* Renamed in spirit only — "scroll-sync" no longer applies: the per-column
     parallax scrub was removed by request. This is just a normal grid now,
     every image visible and clickable, scrolling with the rest of the page
     (still gets a one-time zoom-settle via .sg-zoom-wrap below). */
  .scroll-gallery{
    /* Hidden per request (possibly removed for good later) — script.js also
       skips building its contents entirely (see GALLERY_ENABLED there), so
       no image requests fire for it either. display:none takes it out of
       the page flow completely, so the margin-top:400px below no longer
       reserves any space. Delete this display:none line (and flip
       GALLERY_ENABLED in script.js) to bring it back exactly as it was. */
    display:none;
    position:relative;
    padding:0 clamp(20px,5vw,64px);
    margin-top:400px;
    overflow:hidden;
  }
  /* the grid itself lives in an inner wrapper, kept separate from
     .scroll-gallery so the zoom transform never touches the element other
     ScrollTriggers use as their position reference */
  .sg-zoom-wrap{
    display:grid;
    grid-template-columns:repeat(5,1fr);
    gap:3px;
    align-items:start;
    width:100%;
  }
  .sg-col{ position:relative; }
  .sg-col-inner{
    display:flex;
    flex-direction:column;
    gap:3px;
  }
  .sg-item{
    display:block;
    width:100%;
    aspect-ratio: 3/4; /* fallback only — JS sets the real per-image ratio inline */
    flex-shrink:0;
    border-radius:2px;
    background:var(--gray-1);
    background-size:cover;
    background-position:center;
    filter:contrast(1.03);
    cursor:none;
  }
  .sg-item.mid{ background-color:var(--gray-2); }

  /* ---------- logos / clients section ---------- */
  .logos-section{
    margin-top:var(--gap-section);
    padding-bottom:var(--gap-section);
  }
  .logos-head{ padding:clamp(28px,4vw,48px) clamp(20px,5vw,64px) 0; }
  .logos-head h2{
    margin-top:14px;
    font-size:clamp(1.6rem,3vw,2.4rem);
    color:var(--ink);
    max-width:22ch;
  }
  .logos-grid{
    margin-top:clamp(36px,5vw,64px);
    display:flex;
    flex-wrap:wrap;
    justify-content:center;
  }
  .logo-cell{
    width:25%;
    display:flex;
    align-items:center;
    justify-content:center;
    padding:clamp(26px,4vw,44px) 16px;
  }
  .logo-item{
    font-family:'Fraunces',serif;
    font-weight:500;
    font-style:italic;
    font-size:clamp(1.05rem,1.8vw,1.4rem);
    letter-spacing:0.01em;
    color:var(--ink);
    opacity:0.36;
    text-align:center;
    transition:opacity .3s var(--ease-1);
    cursor:default;
  }
  .logo-cell:hover .logo-item{ opacity:1; }
  .logo-img{
    display:block;
    width:auto;
    height:auto;
    max-width:100%;
    /* fallback cap; JS sets a precise per-logo max-height (area-normalised) */
    max-height:54px;
    object-fit:contain;
    opacity:0.42;
    transition:opacity .3s var(--ease-1);
  }
  .logo-cell:hover .logo-img{ opacity:1; }
  /* logos delivered on a white background: knock the white out against the
     white page so only the mark shows (page stays light, so multiply is safe) */
  .logo-img.logo-white{ mix-blend-mode:multiply; }
  @media (max-width:860px){
    .logo-cell{ width:50%; }
  }
  @media (max-width:520px){
    .logo-cell{ width:100%; }
  }

  /* ---------- articles section ---------- */
  .articles-section{
    margin-top:var(--gap-section);
    padding:0 clamp(20px,5vw,64px) var(--gap-section);
  }
  .articles-head{ margin-bottom:clamp(32px,5vw,56px); }
  .articles-head h2{
    margin-top:14px;
    font-family:'Playfair Display', serif;
    font-weight:500;
    font-size:clamp(1.8rem,4vw,2.6rem);
    color:var(--ink);
    max-width:22ch;
  }
  .articles-grid{
    display:grid;
    grid-template-columns:repeat(3,1fr);
    gap:clamp(16px,2vw,26px);
  }
  .article-card{
    display:block;
    color:var(--ink);
  }
  .article-media{
    position:relative;
    aspect-ratio:4/3;
    overflow:hidden;
    background:var(--gray-1);
    margin-bottom:20px;
  }
  .article-media img{
    width:100%; height:100%;
    object-fit:cover;
    display:block;
    filter:contrast(1.03);
    transition:transform .6s var(--ease-1);
  }
  .article-meta{
    display:block;
    font-size:0.66rem;
    letter-spacing:0.14em;
    color:var(--stone);
    margin-bottom:12px;
  }
  .article-title{
    font-family:'Playfair Display', serif;
    font-weight:500;
    font-size:clamp(1.15rem,1.9vw,1.4rem);
    line-height:1.28;
    color:var(--ink);
    margin-bottom:10px;
    transition:opacity .3s var(--ease-1);
  }
  .article-excerpt{
    font-family:Verdana, sans-serif;
    font-weight:300;
    font-size:0.88rem;
    line-height:1.55;
    /* darker than --stone (#8C8C88) for better reading contrast on this
       longer body copy, but not full --ink so it stays a notch under the title */
    color:#4A4A46;
    width:90%;
  }
  @media (max-width:860px){
    .articles-grid{ grid-template-columns:1fr; gap:36px; }
  }

  /* ---------- footer ---------- */
  footer{
    padding:100px clamp(20px,5vw,64px) 40px;
    padding-bottom:max(40px, env(safe-area-inset-bottom));
    margin-top:var(--gap-section);
  }
  footer h2{
    margin-top:18px;
    font-size:clamp(2rem,6vw,4.6rem);
    color:var(--ink);
    max-width:14ch;
  }
  .foot-email{
    display:inline-block;
    margin-top:34px;
    font-family:'Fraunces', serif;
    font-style:italic;
    font-size:clamp(1.2rem,2.4vw,1.6rem);
    color:var(--ink);
    border-bottom:1px solid var(--ink);
    padding-bottom:4px;
  }
  .foot-bottom{
    margin-top:90px;
    display:flex; flex-wrap:wrap; gap:20px;
    justify-content:space-between;
    align-items:center;
    padding-top:26px;
    border-top:1px solid var(--line);
  }
  .foot-links{ display:flex; align-items:center; gap:22px; list-style:none; }
  .foot-links a{ font-family:'JetBrains Mono',monospace; font-size:0.72rem; color:var(--stone); }
  .foot-links a:hover{ color:var(--ink); }
  .foot-links a.foot-social{ display:inline-flex; align-items:center; }
  .foot-links a.foot-social svg{ display:block; }

  /* ---------- contact page ---------- */
  .contact-hero{
    padding:160px clamp(20px,5vw,64px) 48px;
    max-width:900px;
  }
  .contact-hero .hero-name{ margin-top:22px; }
  .contact-hero-copy{
    margin-top:26px;
    font-family:Verdana, sans-serif;
    font-size:clamp(1rem,1.6vw,1.15rem);
    line-height:1.6;
    color:rgba(10,10,10,0.65);
    max-width:52ch;
  }
  .contact-form-section{
    display:flex;
    flex-direction:column;
    align-items:flex-start;
    padding:20px clamp(20px,5vw,64px) var(--gap-section);
    max-width:720px;
  }
  .contact-submit{
    display:inline-block;
    align-self:flex-start;
    margin-top:8px;
    font-family:'JetBrains Mono', monospace;
    font-size:0.78rem;
    letter-spacing:0.1em;
    text-transform:uppercase;
    color:var(--white);
    background:var(--ink);
    border:none;
    padding:14px 32px;
    border-radius:100px;
    cursor:none;
    text-decoration:none;
    transition:background-color .3s var(--ease-1);
  }
  .contact-submit:hover,
  .contact-submit:visited{ color:var(--white); }
  .contact-submit:hover{ background:#2b2b27; }
  /* LinkedIn link below the Book-a-call CTA */
  .contact-linkedin{
    display:flex;
    align-items:center;
    gap:10px;
    width:max-content;
    margin-top:40px;
    font-family:'JetBrains Mono', monospace;
    font-size:0.78rem;
    letter-spacing:0.1em;
    text-transform:uppercase;
    color:var(--ink);
    text-decoration:none;
    opacity:0.72;
    transition:opacity .3s var(--ease-1);
  }
  .contact-linkedin:hover,
  .contact-linkedin:visited{ color:var(--ink); }
  .contact-linkedin:hover{ opacity:1; }
  .contact-linkedin svg{ display:block; }
  /* same Book-a-call CTA reused in the home footer, just with the spacing the
     old email link had */
  footer .foot-cta{ margin-top:34px; }
  /* on the dark About footer an ink pill on black is nearly invisible — flip it
     to a white pill with ink text so the CTA reads as a button */
  body.dark footer .foot-cta{ color:var(--ink); background:var(--white); }
  body.dark footer .foot-cta:hover,
  body.dark footer .foot-cta:visited{ background:#e6e4de; color:var(--ink); }

  @media (max-width:640px){
    .contact-hero{ padding:120px clamp(20px,5vw,64px) 36px; }
  }

  /* ---------- project view (opens in-page on click) ---------- */
  /* The project view is a FLOATING WINDOW over the page (~90% of the
     viewport), not a full-screen page: the home stays visible, dimmed and
     blurred, around it — so it reads as a window opened inside the same page.
     --pv-ix / --pv-iy = gap between the window and the viewport's sides / top.
     The window sits flush on the bottom edge (no bottom gap), like a sheet. */
  .project-view{
    --pv-ix:3vw; --pv-iy:3vh;
    position:fixed; inset:0; z-index:1000;
    visibility:hidden;
  }
  .pv-backdrop{
    position:absolute; inset:0;
    background:rgba(10,10,10,0.42);
    backdrop-filter:blur(6px); -webkit-backdrop-filter:blur(6px);
    opacity:0;
  }
  .pv-window{
    position:absolute;
    top:var(--pv-iy); bottom:0; left:var(--pv-ix); right:var(--pv-ix);
    background:var(--white);
    border-radius:8px 8px 0 0;
    overflow-y:auto; overflow-x:hidden;
    overscroll-behavior:contain;
    scrollbar-width:none;                 /* still scrollable, just no visible bar */
    -ms-overflow-style:none;
    -webkit-overflow-scrolling:touch;
    box-shadow:0 50px 120px -30px rgba(0,0,0,0.5), 0 0 0 1px rgba(10,10,10,0.06);
    opacity:0;
  }
  .pv-window::-webkit-scrollbar{ display:none; width:0; height:0; }
  body.dark .pv-window{ background:var(--ink); box-shadow:0 50px 120px -30px rgba(0,0,0,0.7), 0 0 0 1px rgba(255,255,255,0.08); }
  body.pv-lock{ overflow:hidden; }
  .pv-layout{ display:flex; align-items:flex-start; min-height:100%; }

  /* left info panel (sticky inside the window): 26% of the window */
  .pv-info{
    width:26%;
    position:sticky; top:0;
    height:calc(100vh - var(--pv-iy));
    height:calc(100dvh - var(--pv-iy));
    display:flex; flex-direction:column;
    padding:clamp(24px,3vw,52px);
    border-right:1px solid var(--line);
    background:rgba(255,255,255,0.72);
    backdrop-filter:blur(22px);
    -webkit-backdrop-filter:blur(22px);
    transition:background-color .4s var(--ease-1);
  }
  body.dark .pv-info{ background:rgba(10,10,10,0.72); border-right-color:rgba(255,255,255,0.14); }
  /* "Volver" button: left-aligned in the info column, always black with white text */
  .pv-info-top{ display:flex; justify-content:flex-start; }
  .pv-close{
    display:inline-flex; align-items:center; gap:8px;
    font-family:'JetBrains Mono',monospace; font-size:0.72rem; letter-spacing:0.1em; text-transform:uppercase;
    color:#fff; background:var(--ink); border:1px solid var(--ink);
    padding:9px 16px; border-radius:100px; cursor:none;
    transition:background .35s var(--ease-1), border-color .35s var(--ease-1);
  }
  .pv-close:hover{ background:#2b2b27; border-color:#2b2b27; color:#fff; }
  .pv-close-arrow{ font-size:0.9rem; line-height:1; transition:transform .3s var(--ease-1); }
  .pv-close:hover .pv-close-arrow{ transform:translateX(-3px); }
  .pv-info-body{ margin-top:auto; }
  .pv-title{ font-family:'Fraunces',serif; font-weight:500; font-size:clamp(2rem,3.6vw,3.4rem); color:var(--ink); line-height:1; }
  .pv-desc{ margin-top:20px; max-width:42ch; font-family:Verdana, Geneva, sans-serif; font-size:0.92rem; line-height:1.65; color:var(--stone); }
  .pv-specs{ margin-top:34px; display:flex; flex-direction:column; }
  .pv-spec{ display:flex; flex-direction:column; gap:5px; padding:16px 0; border-top:1px solid var(--line); }
  .pv-spec:last-child{ border-bottom:1px solid var(--line); }
  .pv-spec dt{ font-family:'JetBrains Mono',monospace; font-size:0.64rem; letter-spacing:0.14em; text-transform:uppercase; color:var(--stone); }
  .pv-spec dd{ font-family:Verdana, Geneva, sans-serif; font-size:0.92rem; color:var(--ink); }

  /* right media column */
  .pv-media{ width:74%; }
  .pv-hero{ width:100%; height:calc((100vh - var(--pv-iy)) * 0.92); height:calc((100dvh - var(--pv-iy)) * 0.92); overflow:hidden; }
  .pv-hero img{ width:100%; height:100%; object-fit:cover; filter:contrast(1.03); display:block; }
  .pv-body{ display:flex; flex-direction:column; }
  .pv-fig{ margin:0; overflow:hidden; }
  .pv-img{ width:100%; display:block; filter:contrast(1.03); }
  .pv-foot{
    display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:20px;
    padding:clamp(40px,6vw,90px) clamp(24px,4vw,52px);
    border-top:1px solid var(--line);
  }
  .pv-foot .mono{ color:var(--stone); }
  /* Book-a-call CTA in the project footer (replaces the old "next project"
     button). Reuses the .contact-submit pill; drop its default top margin so
     it centers in the flex-row footer. */
  .pv-book{ margin-top:0; align-self:center; }

  /* dark variants for all project-view text, active when opened over the
     black (post-gallery) part of the page */
  .project-view, .project-view *{
    transition:color .4s var(--ease-1), border-color .4s var(--ease-1), background-color .4s var(--ease-1);
  }
  body.dark .pv-close{ color:#fff; background:var(--ink); border-color:rgba(255,255,255,0.25); }
  body.dark .pv-close:hover{ background:#2b2b27; color:#fff; }
  body.dark .pv-title{ color:var(--white); }
  body.dark .pv-desc{ color:rgba(255,255,255,0.55); }
  body.dark .pv-spec{ border-top-color:rgba(255,255,255,0.14); }
  body.dark .pv-spec:last-child{ border-bottom-color:rgba(255,255,255,0.14); }
  body.dark .pv-spec dt{ color:rgba(255,255,255,0.5); }
  body.dark .pv-spec dd{ color:var(--white); }
  body.dark .pv-foot{ border-top-color:rgba(255,255,255,0.14); }
  body.dark .pv-foot .mono{ color:rgba(255,255,255,0.5); }
  /* on a dark modal the ink pill would vanish into the black bg — flip it to a
     white pill with ink text so the CTA stays visible */
  body.dark .pv-book{ background:var(--white); color:var(--ink); }
  body.dark .pv-book:hover, body.dark .pv-book:visited{ background:#e6e4de; color:var(--ink); }
  .pv-clone{
    position:fixed; z-index:1100;
    object-fit:cover; filter:contrast(1.03);
    display:none; pointer-events:none;
    will-change:transform,width,height,top,left;
  }
  @media (max-width:860px){
    .project-view{ --pv-ix:10px; --pv-iy:14px; }
    .pv-window{ border-radius:7px 7px 0 0; }
    .pv-layout{ flex-direction:column; }
    /* the info panel becomes a translucent, blurred card that overlaps the
       tail end of the hero image (instead of sitting in a plain stack below
       it), so the frosted-glass effect actually has something to blur */
    /* hero → info card → rest of the images: .pv-media's children join the
       column so the info card sits right after the hero (not after every image) */
    .pv-media{ display:contents; }
    .pv-hero{ order:1; }
    .pv-body{ order:3; }
    .pv-info{
      order:2; position:relative; z-index:5;
      width:100%; height:auto;
      margin-top:-130px;
      border-right:none; border-top:1px solid var(--line);
      /* frosted glass moved to ::before: a backdrop-filter on .pv-info itself
         would trap the position:fixed close button inside this card */
      background:transparent;
      backdrop-filter:none; -webkit-backdrop-filter:none;
    }
    .pv-info::before{
      content:''; position:absolute; inset:0; z-index:-1;
      background:rgba(255,255,255,0.72);
      backdrop-filter:blur(22px); -webkit-backdrop-filter:blur(22px);
    }
    body.dark .pv-info{ border-top-color:rgba(255,255,255,0.14); background:transparent; }
    body.dark .pv-info::before{ background:rgba(10,10,10,0.72); }
    .pv-info-body{ margin-top:32px; }
    .pv-hero{ height:56vh; height:56dvh; }
    /* keep the close button always reachable at the top of the screen,
       independent of where the overlapping info card ends up */
    .pv-close{
      position:fixed; top:calc(var(--pv-iy) + 12px); left:calc(var(--pv-ix) + clamp(24px,3vw,52px)); z-index:20;   /* aligned with the info column text */
      background:var(--ink); color:#fff;
    }
    body.dark .pv-close{ background:var(--ink); color:#fff; }
  }

  @media (max-width: 860px){
    .hero{ min-height:auto; padding-top:96px; }
    .hero-inner{ grid-template-columns:1fr; }
    .hero-right{ margin-top:40px; }
    .index-head{ text-align:left; }

    .sg-zoom-wrap{ grid-template-columns:repeat(3,1fr); gap:3px; }
    .caption-row{ padding-bottom:22px; }
    .nav{ padding:20px clamp(16px,4vw,64px); }
    .nav-right{ gap:20px; }
    .nav-links{ gap:14px; }
    .lang-switch{ padding-right:16px; }
  }

  @media (max-width: 520px){
    .nav-logo-mark{ height:1.5rem; }
    /* mobile nav: flatten .nav-right so the language switch and the links
       become direct flex children of .nav. The lang switch sits right after
       the logo (margin-right:auto pushes the links to the far edge), and the
       links get more breathing room between them. */
    .nav{ justify-content:flex-start; gap:12px; }
    .nav-right{ display:contents; }
    .nav-logo{ order:0; }
    .lang-switch{ order:1; margin-right:auto; padding-right:0; border-right:none; }
    .nav-links{ order:2; gap:20px; }
    .nav-links a{ font-size:0.62rem; letter-spacing:0.06em; }
    .nav-links li.nav-cta a{ padding:6px 14px; }
    .lang-opt, .lang-sep{ font-size:0.66rem; }
    .hero{ padding-top:88px; }
    .scroll-cue{ font-size:1.15rem; }
    .sg-zoom-wrap{ grid-template-columns:repeat(2,1fr); gap:2px; }
    /* client logos: 2 per row on phones instead of 4 */
    .logo-cell{ width:50%; }
    .logos-head h2{ font-size:1.5rem; }
    .foot-bottom{ flex-direction:column; align-items:flex-start; gap:14px; }
    footer h2{ font-size:2rem; }
  }

  /* ================= About page (about.html) — always dark ================
     Reuses the existing (site-wide disabled) body.dark component colors —
     nav, hero-name/role/divider, footer — by putting BOTH "dark" and
     "about-page" on <body>. "about-page" only carries the two things the
     dark-mode system never wired up (see notas-operativas.md): the actual
     page background and the grain/selection contrast. Scoped to this file
     only — index.html never gets these classes, so the home page stays
     exactly as it is. */
  html.about-page{ background:#050505; }   /* canvas fill only (overscroll bounce) */
  /* NOTE: body itself must NOT get an opaque background here. body is a
     normal in-flow box, so its own background paints ABOVE any negative
     z-index fixed children (.page-bg, .col-grid) — that was silently hiding
     the column-grid lines and the page-bg glow on this page. The solid black
     fill lives on .page-bg instead, which sits at the correct (negative)
     stacking level, below .col-grid, so the faint white lines show through. */
  .about-page .page-bg{ background:#050505; }   /* a touch darker than --ink */
  .about-page .grain{ mix-blend-mode:screen; opacity:0.03; }
  /* About: content column capped at 1420px (the sections keep their own
     side padding — 64px at desktop — so the box is 1420 + 2×64) and centred
     on wide screens. The fixed nav and the background layers stay full-bleed. */
  body.about-page > section,
  body.about-page > footer{
    width:100%;
    max-width:calc(1420px + 128px);
    margin-left:auto;
    margin-right:auto;
  }
  .about-page ::selection{ background:var(--white); color:var(--ink); }

  /* ---- animated film grain (About only) ----
     The background is a flat solid black (.page-bg carries background:var(--ink)
     above) — the earlier soft radial "glow" drift behind everything was removed
     per request. The animated grain itself is a top overlay (above ALL content
     — text, images, nav), pointer-inert, screen-blended: over the dark areas it
     reads as living film grain, and screen blending leaves the white text
     untouched. JS (initGrainAnim) drives the canvas; motion is frozen to a
     single frame under prefers-reduced-motion. */
  .grain-anim{
    position:fixed; inset:0;
    z-index:9998;                 /* over content, like the static .grain */
    pointer-events:none;
    opacity:0.07;
    mix-blend-mode:multiply;      /* light pages: darkens speckles instead of
                                      screen's "add light", which would simply
                                      vanish over a white background */
  }
  .about-page .grain-anim{
    z-index:9999;                 /* over everything, like the static .grain */
    opacity:0.04;
    mix-blend-mode:screen;        /* dark page: screen reads as living light
                                      specks over black; multiply would just
                                      go black-on-black and disappear */
  }


  .about-hero{
    position:relative;
    min-height:92vh;
    min-height:92dvh;
    display:grid;
    grid-template-columns:minmax(0,0.82fr) minmax(0,1.18fr);
    align-items:center;
    gap:clamp(32px,5vw,88px);
    padding:120px clamp(20px,5vw,64px) 48px;
  }
  .about-hero-text{
    min-width:0;
  }
  .about-hero .hero-eyebrow{ margin-bottom:clamp(18px,2.5vw,30px); }
  .about-hero .hero-name{
    font-size:clamp(2.6rem,6vw,5.4rem);
  }
  .about-hero .hero-divider{ margin-top:clamp(22px,3vw,36px); }
  .about-hero .hero-role{ margin-top:clamp(16px,2vw,24px); }
  .about-hero-photos{
    position:relative;
    display:grid;
    grid-template-columns:1fr 1fr;
    align-items:start;
    gap:clamp(14px,1.6vw,24px);
  }
  .about-hero-photo{
    width:100%;
    aspect-ratio:2/3;
    overflow:hidden;
    border-radius:2px;
    box-shadow:0 40px 80px -30px rgba(0,0,0,0.7);
  }
  .about-hero-photo-b{
    transform:translateY(clamp(32px,6vw,90px));
  }
  .about-hero-photo img{
    width:100%; height:100%;
    object-fit:cover;
    display:block;
    filter:contrast(1.03);
  }
  @media (max-width:900px){
    .about-hero{
      min-height:auto;
      grid-template-columns:1fr;
      align-items:start;
      gap:clamp(28px,5vw,44px);
      padding:104px clamp(20px,5vw,64px) 40px;
    }
    .about-hero-photos{
      order:-1;
      max-width:560px;
    }
    .about-hero-photo-b{
      transform:translateY(28px);
    }
  }

  .about-bio-section{
    padding:clamp(36px,6vw,72px) clamp(20px,5vw,64px) 0;
  }
  .about-bio{
    font-family:Verdana, sans-serif;
    font-weight:300;   /* Verdana has no true light cut, so most browsers just
                          render this as regular weight — kept at 300 anyway
                          per explicit request rather than switching fonts */
    font-size:clamp(0.9rem,1.6vw,1.1rem);
    line-height:1.65;
    letter-spacing:0.005em;
    max-width:64ch;
    color:rgba(255,255,255,0.72);
  }
  .about-bio + .about-bio{ margin-top:1.3em; }

  /* ---------- stack & tools (About) ----------
     Logos load from assets/images/stack/<name>.svg and render as white
     silhouettes so every brand reads in the same monochrome voice on the
     dark page. If a file is missing, the img removes itself and the tile
     shows the tool's initials in an outlined box instead. */
  .stack-section{
    margin-top:var(--gap-section);
    padding:0 clamp(20px,5vw,64px);
  }
  .stack-head{ margin-bottom:clamp(16px,2vw,22px); }
  .stack-head .eyebrow{ color:rgba(255,255,255,0.5); }
  .stack-grid{
    list-style:none; margin:0; padding:0;
    display:grid;
    grid-template-columns:repeat(4,minmax(0,1fr));
    gap:1px;
    background:rgba(255,255,255,0.12);   /* the 1px gaps draw the grid lines */
    border:1px solid rgba(255,255,255,0.12);
  }
  .stack-item{
    display:flex; flex-direction:column; align-items:flex-start;
    gap:6px;
    padding:clamp(20px,2.4vw,32px);
    background:#050505;
    transition:background-color .4s ease;
  }
  .stack-item:hover{ background:#0d0d0d; }
  .stack-logo{
    display:flex; align-items:center;
    height:36px;
    margin-bottom:clamp(14px,2vw,22px);
  }
  .stack-logo img{
    height:100%; width:auto; max-width:120px;
    display:block;
    filter:brightness(0) invert(1);
    opacity:0.85;
    transition:opacity .4s ease;
  }
  .stack-item:hover .stack-logo img{ opacity:1; }
  .stack-logo.is-missing{
    width:36px;
    justify-content:center;
    border:1px solid rgba(255,255,255,0.28);
  }
  .stack-logo.is-missing::before{
    content:attr(data-initials);
    font-family:'JetBrains Mono', monospace;
    font-size:0.7rem;
    letter-spacing:0.04em;
    color:rgba(255,255,255,0.75);
  }
  .stack-name{
    font-family:Verdana, sans-serif;
    font-size:clamp(0.9rem,1.3vw,1rem);
    color:var(--white);
  }
  .stack-cat{
    font-family:'JetBrains Mono', monospace;
    font-size:0.62rem;
    letter-spacing:0.12em;
    text-transform:uppercase;
    color:rgba(255,255,255,0.5);
  }
  @media (max-width:700px){
    .stack-grid{ grid-template-columns:repeat(2,minmax(0,1fr)); }
    .stack-logo{ height:30px; }
    .stack-logo.is-missing{ width:30px; }
  }

  /* ---------- process · double diamond (About) ----------
     Editorial + blueprint: an outlined board with a faint drafting grid,
     dimension lines, callouts and mono annotations around the classic
     double diamond. Each phase (triangle) is linked with its column below:
     hovering / focusing / tapping either one hatches the triangle and dims
     the other columns. The drawing traces itself in on first view
     (.js-draw → .is-drawn, added by the inline script in about.html). */
  .process-section{
    margin-top:var(--gap-section);
    padding:0 clamp(20px,5vw,64px);
  }
  .process-head{
    display:flex; align-items:baseline; justify-content:space-between;
    gap:16px 32px; flex-wrap:wrap;
    margin-bottom:clamp(16px,2vw,22px);
  }
  .process-head .eyebrow{ color:rgba(255,255,255,0.5); }
  .process-intro{
    font-family:'Playfair Display', serif;
    font-style:italic;
    font-size:clamp(1.05rem,1.6vw,1.35rem);
    color:rgba(255,255,255,0.8);
  }
  .process-board{
    position:relative;
    border:1px solid rgba(255,255,255,0.12);
    padding:clamp(34px,4vw,52px) clamp(12px,2.5vw,36px);
    background-image:
      linear-gradient(rgba(255,255,255,0.045) 1px, transparent 1px),
      linear-gradient(90deg, rgba(255,255,255,0.045) 1px, transparent 1px),
      linear-gradient(rgba(255,255,255,0.018) 1px, transparent 1px),
      linear-gradient(90deg, rgba(255,255,255,0.018) 1px, transparent 1px);
    background-size:120px 120px, 120px 120px, 24px 24px, 24px 24px;
    background-position:-1px -1px;
  }
  .pb-meta{
    position:absolute;
    font-family:'JetBrains Mono', monospace;
    font-size:0.58rem;
    letter-spacing:0.14em;
    color:rgba(255,255,255,0.38);
    white-space:nowrap;
  }
  .pb-tl{ top:12px; left:14px; }
  .pb-tr{ top:12px; right:14px; }
  .pb-bl{ bottom:12px; left:14px; }
  .pb-br{ bottom:12px; right:14px; }

  .pd-svg{ display:block; width:100%; height:auto; overflow:visible; }
  .pd-svg line, .pd-svg polygon, .pd-svg circle{ fill:none; }
  .pd-construct line{ stroke:rgba(255,255,255,0.2); stroke-width:1; stroke-dasharray:4 6; }
  .pd-dim line, .pd-callout line{ stroke:rgba(255,255,255,0.45); stroke-width:1; }
  .pd-diamond{ stroke:rgba(255,255,255,0.9); stroke-width:1.6; stroke-linejoin:round; }
  .pd-node{ fill:#050505 !important; stroke:rgba(255,255,255,0.9); stroke-width:1.4; }
  .pd-node-sm{ stroke:rgba(255,255,255,0.55); }
  .pd-hatch-line{ stroke:rgba(255,255,255,0.32); stroke-width:1.2; }
  .pd-phase{
    fill:transparent !important;
    cursor:none;
    transition:fill .3s ease;
  }
  .pd-phase.is-active{ fill:url(#pdHatch) !important; }
  .pd-annot{
    font-family:'JetBrains Mono', monospace;
    font-size:12px;
    letter-spacing:0.16em;
    fill:rgba(255,255,255,0.55);
  }
  .pd-annot-dim{ fill:rgba(255,255,255,0.32); font-size:11px; }
  .pd-label{ pointer-events:none; transition:opacity .35s ease; }
  .pd-num{
    font-family:'JetBrains Mono', monospace;
    font-size:13px; letter-spacing:0.14em;
    fill:rgba(255,255,255,0.55);
  }
  .pd-name{
    font-family:'Playfair Display', serif;
    font-size:30px;
    fill:var(--white);
  }
  .pd-label text{ transition:opacity .35s ease; }
  .process-section.has-active .pd-label:not(.is-active) text{ opacity:0.3; }

  /* AI layer: Claude node under the diagram, dashed feed lines flowing up
     into each phase. The flowing dashes are the "feeding" cue; the active
     phase's feed brightens with the rest of the highlight. */
  .pd-ai{ pointer-events:none; }
  .pd-feed{
    fill:none;
    stroke:rgba(255,255,255,0.42);
    stroke-width:1.2;
    stroke-dasharray:3 6;
    animation:pdFeed 1.1s linear infinite;
    transition:stroke .3s ease;
  }
  .pd-feed.is-active{ stroke:rgba(255,255,255,0.95); }
  @keyframes pdFeed{ to{ stroke-dashoffset:-9; } }
  @keyframes pdFeedM{ to{ stroke-dashoffset:-16; } }
  .pd-feed-dot{ fill:#050505 !important; stroke:rgba(255,255,255,0.75); stroke-width:1.2; }
  .pd-ai-node{ fill:#050505 !important; stroke:rgba(255,255,255,0.9); stroke-width:1.4; }
  .pd-ai-pulse{
    stroke:rgba(255,255,255,0.5); stroke-width:1;
    transform-box:fill-box; transform-origin:center;
    animation:pdPulse 2.6s ease-out infinite;
  }
  @keyframes pdPulse{ from{ transform:scale(1); opacity:.7; } to{ transform:scale(1.9); opacity:0; } }
  @keyframes pdPulseM{ from{ transform:scale(1.7); opacity:.7; } to{ transform:scale(2.8); opacity:0; } }
  .pd-ai-title{ fill:rgba(255,255,255,0.85); }
  @media (prefers-reduced-motion:reduce){ .pd-feed, .pd-ai-pulse{ animation:none; } .pd-ai-pulse{ opacity:0; } }

  /* self-drawing (only when JS armed it, so no-JS still shows everything) */
  .js-draw .pd-draw{
    stroke-dasharray:1; stroke-dashoffset:1;
    transition:stroke-dashoffset 1.3s cubic-bezier(.65,0,.35,1) var(--d,0s);
  }
  .js-draw .pd-fade, .js-draw .pd-node{ opacity:0; transition:opacity .8s ease 1.4s; }
  .js-draw.is-drawn .pd-draw{ stroke-dashoffset:0; }
  .js-draw.is-drawn .pd-fade, .js-draw.is-drawn .pd-node{ opacity:1; }

  .process-steps{
    display:grid;
    grid-template-columns:repeat(4,minmax(0,1fr));
    gap:1px;
    background:rgba(255,255,255,0.12);
    border:1px solid rgba(255,255,255,0.12);
    border-top:none;
  }
  .process-step{
    background:#050505;
    padding:clamp(20px,2.4vw,32px);
    outline:none;
    cursor:none;
    transition:background-color .35s ease;
  }
  .process-step > *{ transition:opacity .35s ease; }
  .process-step.is-active{ background:#0d0d0d; }
  /* dim the content, not the card — card opacity would let the grid-line
     background behind the 1px gaps bleed through as a grey wash */
  .process-section.has-active .process-step:not(.is-active) > *{ opacity:0.32; }
  .process-step:focus-visible{ box-shadow:inset 0 0 0 1px rgba(255,255,255,0.6); }
  .ps-kicker{
    font-family:'JetBrains Mono', monospace;
    font-size:0.62rem; letter-spacing:0.14em; text-transform:uppercase;
    color:rgba(255,255,255,0.5);
  }
  .ps-title{
    margin-top:12px;
    font-family:'Playfair Display', serif;
    font-weight:500;
    font-size:clamp(1.4rem,2vw,1.75rem);
    line-height:1.1;
    color:var(--white);
  }
  .ps-desc{
    margin-top:12px;
    font-family:Verdana, sans-serif;
    font-size:0.86rem;
    line-height:1.6;
    color:rgba(255,255,255,0.72);
  }
  .ps-methods{
    margin-top:16px;
    padding-top:14px;
    border-top:1px dashed rgba(255,255,255,0.16);
    font-family:'JetBrains Mono', monospace;
    font-size:0.62rem; line-height:1.8; letter-spacing:0.08em; text-transform:uppercase;
    color:rgba(255,255,255,0.5);
  }
  @media (pointer:coarse){ .pd-phase, .process-step{ cursor:auto; } }
  @media (max-width:900px){
    .process-steps{ grid-template-columns:repeat(2,minmax(0,1fr)); }
  }
  @media (max-width:700px){
    .process-board{ padding:34px 10px 30px; }
    .pb-tr, .pb-br{ display:none; }
    .pd-annot, .pd-name{ display:none; }   /* too small at phone width — the columns below carry the text */
    .pd-num{ font-size:38px; fill:var(--white); letter-spacing:0.06em; }
    .pd-num{ transform:translateY(22px); }
    .pd-diamond{ stroke-width:3.4; }
    .pd-dim line, .pd-callout line, .pd-construct line{ stroke-width:2.4; }
    .pd-node{ stroke-width:3; }
    .pd-hatch-line{ stroke-width:2.4; }
    .pd-feed{ stroke-width:2.6; stroke-dasharray:6 10; animation-name:pdFeedM; }
    .pd-feed-dot, .pd-ai-node{ stroke-width:2.6; }
    .pd-ai-node, .pd-ai-logo{ transform-box:fill-box; transform-origin:center; transform:scale(1.7); }
    .pd-ai-pulse{ animation-name:pdPulseM; }
    .process-steps{ grid-template-columns:1fr; }
  }

  .hobbies-section{
    margin-top:var(--gap-section);
    padding:0 clamp(20px,5vw,64px) var(--gap-section);
  }
  .hobbies-head{ margin-bottom:clamp(28px,4vw,48px); }
  .hobbies-head .eyebrow{ color:rgba(255,255,255,0.5); }
  .hobbies-intro{
    margin-top:clamp(16px,2vw,24px);
    font-family:Verdana, sans-serif;
    font-size:clamp(0.9rem,1.6vw,1.1rem);
    line-height:1.65;
    max-width:56ch;
    color:rgba(255,255,255,0.72);
  }
  .hobbies-head h2{
    margin-top:14px;
    font-family:'Playfair Display', serif;
    font-weight:500;
    font-size:clamp(2.4rem,6vw,4.4rem);   /* bigger section title */
    line-height:1.05;
    color:var(--white);
    max-width:none;
  }
  .hobbies-grid{
    display:flex;
    flex-direction:column;
    width:100%;
  }
  .hobby-item{
    position:relative;
    display:block;
    cursor:none;
    width:min(930px,78vw);
    aspect-ratio:4/5;
  }
  .hobbies-grid .hobby-item + .hobby-item{
    /* Positive gap (not overlap) between stacked floating items — big enough
       that the ±14px hobbyFloat bob (see keyframes below) never brings two
       consecutive frames close enough to touch. */
    margin-top:clamp(40px,5vw,64px);
  }
  .hobbies-grid .hobby-item:nth-child(odd){ align-self:flex-start; }
  .hobbies-grid .hobby-item:nth-child(even){ align-self:flex-end; }
  .hobby-frame{
    position:absolute;
    inset:0;
    overflow:hidden;
    background:#1A1A18;
    border-radius:2px;
    box-shadow:0 40px 80px -30px rgba(0,0,0,0.65);
    animation:hobbyFloat 7s ease-in-out infinite;
  }
  .hobbies-grid .hobby-item:nth-child(1) .hobby-frame{ animation-delay:0s; }
  .hobbies-grid .hobby-item:nth-child(2) .hobby-frame{ animation-delay:-1.6s; }
  .hobbies-grid .hobby-item:nth-child(3) .hobby-frame{ animation-delay:-3.2s; }
  .hobbies-grid .hobby-item:nth-child(4) .hobby-frame{ animation-delay:-4.8s; }
  .hobbies-grid .hobby-item:nth-child(5) .hobby-frame{ animation-delay:-6.4s; }
  .hobby-item img,
  .hobby-item video{
    width:100%; height:100%;
    object-fit:cover;
    display:block;
    filter:contrast(1.03);
  }

  .hobby-item-split{
    width:min(1340px,89vw);
    aspect-ratio:3/2;
  }
  .hobby-frame-split{
    display:flex;
    gap:2px;
    background:transparent;
  }
  .hobby-frame-split .hobby-pane{
    position:relative;
    flex:1 1 50%;
    overflow:hidden;
    display:flex;
    align-items:center;
    justify-content:center;
  }
  .hobby-frame-split .hobby-pane img,
  .hobby-frame-split .hobby-pane video{
    width:100%; height:100%;
    object-fit:contain;
    display:block;
    filter:contrast(1.03);
  }

  .hobby-num{
    position:absolute;
    top:16px; left:18px;
    z-index:2;
    display:inline-block;
    font-family:Verdana, sans-serif;
    font-size:0.7rem;
    line-height:1;
    letter-spacing:0.02em;
    text-transform:uppercase;
    color:#c9c9c9;
    background:#000;
    padding:5px 9px;
  }
  /* First hobby item (split painting + video): label sits top-right, over
     the video pane, instead of the default top-left. */
  .hobby-item-split .hobby-num{
    left:auto;
    right:18px;
  }

  .hobby-item-natural{ aspect-ratio:auto; }
  .hobby-item-natural .hobby-frame{
    position:relative;
    inset:auto;
  }
  .hobby-item-natural .hobby-frame img{
    height:auto;
    object-fit:contain;
  }

  @keyframes hobbyFloat{
    0%   { transform:translateY(0); }
    50%  { transform:translateY(-14px); }
    100% { transform:translateY(0); }
  }

  @media (prefers-reduced-motion: reduce){
    .hobby-frame{ animation:none; }
  }

  @media (max-width:640px){
    .hobby-item{ width:100%; align-self:center !important; }
    .hobbies-grid .hobby-item + .hobby-item{ margin-top:clamp(28px,6vw,44px); }
  }
