/* ===== Design tokens (was css/tokens.css, merged 23 Oct 2026 to save a blocking request) ===== */
/* tokens.css — the locked system. Change here or nowhere. */

:root {
  /* color */
  --ink: #313131;        /* foundation: text, structure */
  --paper: #FAF9F6;      /* backdrop: the ground */
  --neon: #E3E829;       /* the author. sparing. one accent per view. */
  /* RULE: images sit directly on --paper — no boxed/padded frame around
     them. Source images should have transparent backgrounds so they
     blend straight into the page. --placeholder is a defensive fallback
     fill for the rare case a container needs one before deciding it
     doesn't (e.g. an unloaded image) — never a visible frame. */
  --placeholder: #E0E0E0;

  /* type */
  --font-display: var(--font-body);                  /* one family for everything */
  --font-body: 'Inter', sans-serif;            /* everything else: sans */

  /* scale */
  --space-unit: 8px;
  --margin-page: clamp(20px, 5vw, 80px);
  --measure: 68ch;

  /* masthead */
  --masthead-rule: 2px solid var(--neon);
}

/* Night mode: the same system, flipped to almost black. Toggled by the
   sun/moon in the header (js/theme.js); remembered in localStorage. */
:root[data-theme="dark"] {
  --paper: #161616;
  --ink: #ECEAE4;
  --placeholder: #2a2a2a;
}

/* The one typeface is self-hosted (assets/fonts, Google Fonts, Latin subset).
   Inter: variable weight 400-600 (chosen 23 Oct 2026 over Instrument Sans). */
@font-face {
  font-family: 'Inter';
  src: url('../assets/fonts/inter-var.woff2') format('woff2');
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}
/* ===== end of design tokens ===== */

/* main.css — stage 1: reset, type scale, masthead, layout.
   Built on tokens.css. No animation. GSAP hooks are named + commented
   below but nothing is bound to them yet (stage 2). */

/* ---------- reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body { margin: 0; }
img, picture, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; margin: 0; padding: 0; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
h1, h2, h3, p { margin: 0; }

/* ---------- type scale (mobile-first, fluid) ---------- */
:root {
  --fs-h1: clamp(1.75rem, 0.9rem + 3.4vw, 3.75rem);      /* page titles (caps) */
  --fs-h2: clamp(1.125rem, 1rem + 0.6vw, 1.5rem);        /* section titles (caps) */
  --fs-intro: clamp(1.25rem, 1.05rem + 0.9vw, 1.75rem);
  --fs-body: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  --fs-label: 0.75rem;                                  /* small caps-style labels */

  --lh-tight: 1.1;
  --lh-normal: 1.5;
}

/* Background texture: a photo of pavement, concrete, tiles... laid over the
   paper with multiply, faint enough that you feel it before you see it.
   js/texture.js sets --texture per page load; until real textures exist this
   is a soft grain (also takes the edge off the bright paper). */
:root {
  --texture: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .25  0 0 0 0 .22  0 0 0 0 .18  0 0 0 .6 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  --texture-size: 240px;
  --texture-opacity: 0.2;   /* a slight grain in the light version, like Arc's UI; none at night */
}
html[data-theme="dark"] { --texture-opacity: 0; }
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--texture) center / var(--texture-size);
  mix-blend-mode: multiply;
  opacity: var(--texture-opacity);
}

body {
  position: relative;
  overflow-x: clip; /* a cutout dragged past the edge never creates a sideways scrollbar */
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  color: var(--ink);
  background: var(--paper);
}

/* One typeface (Inter). Headlines are sans in capitals, medium
   weight, with a little positive tracking. Nothing bolder than 500. */
h1, h2, h3 {
  font-family: var(--font-body);
  font-weight: 500;
  text-transform: uppercase;
  line-height: var(--lh-tight);
}
h1 { font-size: var(--fs-h1); letter-spacing: 0.01em; }
h2 { font-size: var(--fs-h2); letter-spacing: 0.04em; }
h3 { letter-spacing: 0.05em; }

.label {                       /* small uppercase sans for metadata, tags, the footer */
  font-family: var(--font-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

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

.skip-link {
  position: absolute;
  top: -100%;
  left: var(--margin-page);
  background: var(--paper);
  color: var(--ink);
  padding: 0.5em 1em;
  z-index: 100;
  font-family: var(--font-body);
  font-size: var(--fs-label);
}
.skip-link:focus {
  top: var(--space-unit);
}

/* focus states use ink, not neon — neon stays reserved for the masthead rule */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* ---------- layout ---------- */
.wrap {
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: var(--margin-page);
}

/* ---------- global header ---------- */
/* One bar across the whole top of every page: the flipping name and, on
   phones, the "+" that opens the menu. Neon appears once: the rule under it.
   GSAP hook (stage 2): pin/shrink-on-scroll target. */
:root { --side-w: 280px; --frame: 1320px; } /* the central column; wider screens get empty margins for the floating objects */

.masthead {
  position: relative;
  z-index: 60;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-unit);
  padding-block: calc(var(--space-unit) * 2);
  padding-inline: var(--margin-page);
  border-bottom: var(--masthead-rule); /* the one neon accent for this view */
}

.flap { display: inline-block; } /* one letter of the flipping name, see js/masthead-flip.js */

.masthead__name {
  flex: 1 1 0; /* wraps onto two lines on phones instead of pushing the + down */
  min-width: 0;
  white-space: nowrap;
  font-family: var(--font-body);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 1rem;
}

/* "+" (becomes "X"), phones only. */
.menu-toggle {
  display: none;
  flex: none;
  font-family: var(--font-body);
  font-size: 1.75rem;
  font-weight: 400;
  line-height: 1;
  color: var(--ink);
  padding: var(--space-unit) calc(var(--space-unit) * 1.5);
  margin: calc(var(--space-unit) * -1) calc(var(--space-unit) * -1.5);
}
.menu-toggle:hover { opacity: 0.6; }
.js .menu-toggle { display: block; }

/* ---------- sidebar menu + page shell ---------- */
/* Desktop: the menu is a column that stays in view while the page scrolls,
   between the global header and the global footer. Phones: the same list
   opens under the header from the "+", right-aligned. */
.shell { position: relative; }

.site-menu {
  padding: calc(var(--space-unit) * 2) var(--margin-page) calc(var(--space-unit) * 3);
  text-align: right;
}
.js .site-menu {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 50;
  width: min(100%, 340px);
  max-height: calc(100vh - 72px);
  overflow-y: auto;
  background: var(--paper);
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 15%, transparent);
  border-left: 1px solid color-mix(in srgb, var(--ink) 15%, transparent);
}
.js .site-menu[hidden] { display: none; }

.site-menu ul { margin: 0; padding: 0; }
.site-menu__pages li + li { margin-top: calc(var(--space-unit) / 2); }
.site-menu__pages a {
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.4;
}
.site-menu .site-menu__index { margin-top: calc(var(--space-unit) * 5); }   /* a clear gap before each block */
.site-menu .site-menu__index--solo { margin-top: calc(var(--space-unit) * 5); }
.site-menu__group { margin-top: calc(var(--space-unit) * 1.25); }
.site-menu__group > a {
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.4;
}
.site-menu__group.is-current > a { text-decoration: underline; text-underline-offset: 0.2em; }
.site-menu__sub { margin-top: calc(var(--space-unit) / 4); }
.site-menu__sub a {
  font-size: 0.8125rem;
  line-height: 1.7;
  opacity: 0.7;
}
.site-menu__sub[hidden] { display: none; }
.site-menu a:hover,
.site-menu a[aria-current="page"],
.site-menu a.is-current {
  opacity: 1;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

@media (min-width: 900px) {
  .masthead { padding-inline: calc(var(--space-unit) * 3); } /* name lines up with the menu below it */
  .shell {
    display: grid;
    grid-template-columns: var(--side-w) minmax(0, 1fr);
    align-items: start;
  }
  .menu-toggle,
  .js .menu-toggle { display: none; }
  /* always open: the catalogue is the navigation */
  .site-menu,
  .js .site-menu,
  .js .site-menu[hidden] {
    display: block;
    position: sticky;
    top: 0;
    z-index: auto;
    width: auto;
    height: 100vh;
    max-height: none;
    overflow-y: auto;
    background: none;
    border: 0;
    padding: calc(var(--space-unit) * 3) calc(var(--space-unit) * 3) calc(var(--space-unit) * 4);
    text-align: left;
  }
}

/* ---------- about ---------- */
/* Intro text with the portrait right beside it (not pushed to the far edge).
   GSAP hook (stage 2): fade/reveal target. */
.about {
  display: grid;
  grid-template-columns: 1fr;
  gap: calc(var(--space-unit) * 4);
  align-items: start;
  padding-block: calc(var(--space-unit) * 4) calc(var(--space-unit) * 12);
  padding-inline: var(--margin-page);
}
@media (min-width: 720px) {
  .about {
    grid-template-columns: minmax(0, 40rem) auto;
    justify-content: start;
    column-gap: calc(var(--space-unit) * 8);
  }
}
.intro__text {
  font-size: var(--fs-intro);
  max-width: var(--measure);
  font-weight: 400;
}
.intro__text a {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

/* Portrait that changes on each page load. Every photo uses the same 3:4
   frame (cropped to fit, never stretched), so the size never changes
   between them. No animation. Without JS the first photo just shows.
   See js/portrait-rotate.js. */
.portrait-cycle {
  width: clamp(150px, 24vw, 280px);
  aspect-ratio: 3 / 4;
  overflow: hidden;
}
.portrait-cycle img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.portrait-cycle img + img { display: none; }
.portrait-cycle.is-picked img { display: none; }
.portrait-cycle.is-picked img.is-active { display: block; }

/* ---------- work grid (homepage + category pages) ---------- */
/* Every project is a square tile and the tiles touch: as many columns as fit
   at ~480px or wider (two on a laptop). Name and category appear over the
   picture on hover (always on touch screens). All tiles are the same kind of
   picture (a square detail), so the grid stays calm.
   GSAP hook (stage 2): .work__item = scroll-reveal targets. */
.work {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 480px), 1fr));
  gap: 0;
  padding: 0;
}
.work__link {
  position: relative;
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
}
.work__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Hover: a full, semi-opaque layer over the square, name set big enough to
   fill it, category tucked at the bottom. Type scales with the tile (cqw =
   1% of the tile's width), so it fills a 480px tile and a 580px tile alike.
   On touch screens (no hover) it is a compact bar along the bottom instead,
   so the pictures stay visible. */
.work__link { container-type: inline-size; }
.work__meta {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: calc(var(--space-unit) * 2);
  padding: 5cqw;
  color: var(--paper);
  background: color-mix(in srgb, var(--ink) 74%, transparent);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.work__link:hover .work__meta,
.work__link:focus-visible .work__meta { opacity: 1; }
.work__meta h2,
.work__meta h3 {
  font-size: clamp(1.5rem, 11cqw, 4.5rem);   /* js/fit-tiles.js sets the exact size on desktop */
  line-height: 0.98;
  letter-spacing: 0.01em;
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.work__meta .work__tag { font-size: clamp(0.75rem, 3.4cqw, 1.125rem); opacity: 1; }
@media (hover: none) {
  .work__meta {
    inset: auto 0 0 0;
    padding: calc(var(--space-unit) * 1.5) calc(var(--space-unit) * 2);
    gap: 2px;
    justify-content: flex-start;
    opacity: 1;
  }
  .work__meta h2, .work__meta h3 { font-size: 1.125rem; }
  .work__meta .work__tag { font-size: 0.75rem; }
}

/* Author cutouts live on the periphery: a layer over the whole page (not
   inside the grid), so they can be dragged anywhere, including over the menu
   and off to the edges. Percentages are of the full page. */

/* A fixed layer, like the menu: the cutouts live down in the menu column and
   can be dragged out onto the page. Hidden on phones (no room). */
.cutout-layer {
  position: fixed;
  inset: 0;
  z-index: 5;
  pointer-events: none;
}
.cutout-layer .cutout {
  pointer-events: auto;
  max-width: none;
  width: clamp(56px, 6vw, 96px);
}
@media (max-width: 899px) { .cutout-layer:not(.cutout-layer--lost) { display: none; } }
.cutout-layer .cutout--list-dog    { left: 2%;   top: 66%; }
.cutout-layer .cutout--list-ipod   { left: 9%;   top: 74%; width: clamp(44px, 4.5vw, 72px); }
.cutout-layer .cutout--list-plaque { left: 6%;   top: 58%; }

/* ---------- hero (project pages) ---------- */
/* GSAP hook (stage 2): hand-transition target. */
.hero {
  padding-block: calc(var(--space-unit) * 4) calc(var(--space-unit) * 6);
  padding-inline: var(--margin-page);
}
.hero__meta {
  margin-top: calc(var(--space-unit) * 2);
  opacity: 0.7;
}
.hero__media {
  margin-top: calc(var(--space-unit) * 4);
  aspect-ratio: 16 / 9;
  overflow: hidden;
  max-width: 900px; /* same cap as the flipbook, so nothing balloons on huge monitors */
}
.hero__media img,
.hero__media video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero__media iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}
/* For transparent-background mockup renders, where cropping would cut
   into the floating object instead of just trimming empty space.
   Background stays the standard placeholder — consistent everywhere. */
.hero__media--contain img {
  object-fit: contain;
}

.case-content {
  padding-inline: var(--margin-page);
  padding-block-end: calc(var(--space-unit) * 8);
  max-width: var(--measure);
}
.case-content p + p { margin-top: 1em; }

/* Embedded Figma prototype (Pausa). Portrait, centred, never taller than the
   screen so the whole phone is visible without scrolling inside the page. */
.proto {
  position: relative;
  margin-top: calc(var(--space-unit) * 4);
  margin-inline: auto;
  width: min(100%, 560px);
  /* the whole prototype fits above the fold: the viewport minus the header, title and footer bar above and below it */
  height: clamp(380px, calc(100svh - 216px - var(--footer-h, 0px) - 16px), 900px);
}
.proto iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

/* ---------- case sections (multi-part case studies, e.g. Paneleirices) ---------- */
.case-section {
  padding-block: calc(var(--space-unit) * 7);
  padding-inline: var(--margin-page);
  border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
}
.case-section:first-of-type {
  border-top: none;
  padding-top: calc(var(--space-unit) * 2);
}
.case-section p {
  max-width: var(--measure);
}
.case-section__title {
  margin-bottom: calc(var(--space-unit) * 2);
}
.case-section__meta {
  margin-bottom: calc(var(--space-unit) * 2);
  opacity: 0.7;
}
.case-section a { text-decoration: underline; text-underline-offset: 0.2em; }
.case-section__media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  margin-top: calc(var(--space-unit) * 3);
}
.case-section__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Product-shot gallery — stacked vertically, each sized to its own
   aspect ratio. No boxed frame — images sit directly on the page;
   their own (transparent) background is the only background. */
.case-section__gallery {
  display: flex;
  flex-direction: column;
  gap: calc(var(--space-unit) * 3);
  margin-top: calc(var(--space-unit) * 3);
}
.case-section__item {
  max-width: 420px;
}
.case-section__item img {
  display: block;
  width: 100%;
  height: auto;
}

/* Hover-swap tiles (e.g. two angles of one product) need both images
   pinned to the same box so one can replace the other exactly. */
.case-section__item--swap {
  position: relative;
  display: grid;
}
.case-section__item--swap img {
  grid-area: 1 / 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition: opacity 0.2s ease;
}
.case-section__item-hover {
  opacity: 0;
}
.case-section__item--swap:hover .case-section__item-base {
  opacity: 0;
}
.case-section__item--swap:hover .case-section__item-hover {
  opacity: 1;
}

/* Small in-flow reference photo above a paragraph — not absolutely
   positioned, so it can't overlap the text next to it regardless of
   column width. */
.case-photo {
  /* position: relative so js/cutout-drag.js can nudge it with left/top
     while its slot in the text flow stays reserved — dragging it never
     reflows the paragraph underneath. */
  position: relative;
  max-width: 220px;
  margin-bottom: calc(var(--space-unit) * 2);
  cursor: grab;
  -webkit-user-drag: none;
  user-select: none;
}
.case-photo--rotate-right { transform: rotate(3deg); }
/* Only claim the touch gesture on mouse/trackpad devices. This image
   sits mid-column, so on a phone a swipe that starts on it should still
   scroll the page rather than get trapped. */
@media (pointer: fine) {
  .case-photo { touch-action: none; }
}

/* ---------- cutouts (author layer) ---------- */
/* Frame only — never placed over .work__img, .hero__media, or case-study
   imagery. That's "the work speaking" and stays clean per the locked system. */
.cutout-scatter {
  position: relative;
}
.cutout {
  position: absolute;
  max-width: 110px;
  width: 20vw;
  pointer-events: auto;
  z-index: 1;
  cursor: grab;
  touch-action: none; /* let JS own the gesture instead of the browser's scroll */
}
.cutout--rotate-left { transform: rotate(-6deg); }
.cutout--rotate-right { transform: rotate(5deg); }

/* Rearranging by hand — see js/cutout-drag.js. Direct manipulation only:
   it moves exactly as far as the cursor does and stops the instant you
   let go. No momentum, no animation, nothing moves on its own. */
.cutout--dragging {
  cursor: grabbing;
  z-index: 2; /* stay above sibling cutouts while being moved */
}

/* Hover-swap cutout (e.g. iPod off/on) — same crossfade technique as
   the Paneleirices tote bag: base fades out, hover image fades in on
   top of it, so one fully replaces the other instead of just layering. */
.cutout-swap {
  display: grid;
}
.cutout-swap img {
  grid-area: 1 / 1;
  width: 100%;
  display: block;
  transition: opacity 0.2s ease;
}
.cutout-swap__hover { opacity: 0; }
.cutout-swap:hover .cutout-swap__base { opacity: 0; }
.cutout-swap:hover .cutout-swap__hover { opacity: 1; }

@media (max-width: 479px) {
  /* keep mobile fast and legible — scatter shrinks, doesn't disappear */
  .cutout { max-width: 64px; }
}

/* ---------- flipbook (Bairros full magazine) ---------- */
/* Uses self-hosted js/vendor/page-flip.browser.js (StPageFlip, MIT).
   No animation added here beyond the library's own page-turn — this is
   a stage 1 content feature, not part of the GSAP stage 2 layer. */
.flipbook-section {
  padding-inline: var(--margin-page);
  padding-block-end: calc(var(--space-unit) * 8);
}
.flipbook-toggle {
  display: block;
  margin-inline: auto;
  margin-bottom: var(--space-unit);
  text-align: right;
  max-width: 900px;
  opacity: 0.7;
}
.flipbook-toggle:hover { opacity: 1; }

/* PageFlip sets its own inline width/max-width on #bairros-flipbook —
   constrain the wrapper instead of fighting that inline style. */
.flipbook-wrap {
  margin-inline: auto;
  max-width: 900px;
}
/* Fullscreen: PageFlip's own 'stretch' sizing can't be trusted to
   recompute correctly here (its height clamp for that mode reads a
   self-referential value — the padding-bottom trick it uses to size
   .stf__wrapper — so it never actually catches an overflow, which is
   what caused the earlier cropping). Rather than ask the library to
   resize itself, the book keeps rendering at its normal fixed 900px
   size always, and bairros-flipbook.js scales the whole thing up to
   fill the screen with a plain CSS transform instead. PageFlip itself
   never has to recompute anything for fullscreen.
   Separate rules, not a comma list — an unsupported selector in a
   shared list can drop the whole rule in some browsers. */
.flipbook-wrap:fullscreen {
  position: relative;
  max-width: none;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #313131; /* fullscreen is always dark, in either theme */
}
.flipbook-wrap:-webkit-full-screen {
  position: relative;
  max-width: none;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #313131; /* fullscreen is always dark, in either theme */
}
.flipbook-wrap:fullscreen .flipbook {
  margin-inline: 0;
  max-width: 900px;
}
.flipbook-wrap:-webkit-full-screen .flipbook {
  margin-inline: 0;
  max-width: 900px;
}

/* Esc hint — pure CSS visibility, only shown while actually fullscreen. */
.flipbook-fs-hint {
  display: none;
}
.flipbook-wrap:fullscreen .flipbook-fs-hint,
.flipbook-wrap:-webkit-full-screen .flipbook-fs-hint {
  display: block;
  position: absolute;
  top: calc(var(--space-unit) * 2);
  left: 50%;
  transform: translateX(-50%);
  color: #FAF9F6; /* fullscreen is always dark (#313131), so the hint must be light in both themes */
  opacity: 0.8;
  z-index: 1;
  user-select: none;
}
.flipbook .page {
  background: var(--placeholder);
}
.flipbook .page img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Cover state shows a single page inside a full double-spread-width
   block. The front cover sits flush right by default (shift left a
   quarter-width to center it); the back cover sits flush left (shift
   right instead). Toggled by bairros-flipbook.js. Transition smooths
   the shift so it runs with the flip instead of snapping after it. */
.flipbook .stf__block {
  transform: translateX(0);
  transition: transform 0.4s ease;
}
.flipbook.is-cover-first .stf__block {
  transform: translateX(-25%);
}
.flipbook.is-cover-last .stf__block {
  transform: translateX(25%);
}

/* ---------- footer ---------- */
.site-footer {
  border-top: 1px solid color-mix(in srgb, var(--ink) 15%, transparent);
  padding-block: calc(var(--space-unit) * 4);
}
.site-footer__contact a {
  font-size: var(--fs-h2);
  font-family: var(--font-display);
}
.site-footer__contact a:hover { text-decoration: underline; }

/* "Email me" → "Tell me something nice" on hover/focus. Both labels sit
   in the same grid cell, so the link is always as wide as the longer one
   and nothing jumps when they swap. */
.contact-link {
  display: inline-grid;
}
.contact-link > span {
  grid-area: 1 / 1;
}
.contact-link__hover {
  visibility: hidden;
}
.contact-link:hover .contact-link__default,
.contact-link:focus-visible .contact-link__default {
  visibility: hidden;
}
.contact-link:hover .contact-link__hover,
.contact-link:focus-visible .contact-link__hover {
  visibility: visible;
}
.site-footer__meta {
  margin-top: var(--space-unit);
  opacity: 0.7;
}

/* ---------- Paneleirices chapters ---------- */
/* Same row on the overview and all four chapters. Ink only — neon stays
   reserved for the masthead rule. */
.chapter-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-unit) calc(var(--space-unit) * 3);
  padding-inline: var(--margin-page);
  padding-block: var(--space-unit) calc(var(--space-unit) * 2);
}
.chapter-nav a { opacity: 0.7; }
.chapter-nav a:hover,
.chapter-nav a[aria-current="page"] {
  opacity: 1;
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

.chapter-next {
  padding-inline: var(--margin-page);
  padding-block: calc(var(--space-unit) * 2) calc(var(--space-unit) * 10);
}
.chapter-next a:hover { text-decoration: underline; }

/* GSAP hook (stage 2): .chapter-card stagger items. */
.chapter-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: calc(var(--space-unit) * 6) calc(var(--space-unit) * 4);
  padding-inline: var(--margin-page);
  padding-block: calc(var(--space-unit) * 4) calc(var(--space-unit) * 10);
}
@media (min-width: 640px) {
  .chapter-grid { grid-template-columns: repeat(2, 1fr); }
}
.chapter-card__link { display: block; }
.chapter-card__media {
  aspect-ratio: 16 / 10;
  overflow: hidden;
}
.chapter-card__media img {
  width: 100%;
  height: 100%;
  object-fit: contain; /* fit whole — never crop the work */
}
.chapter-card:hover .chapter-card__media img { opacity: 0.92; }
.chapter-card__num {
  margin-top: calc(var(--space-unit) * 2);
  opacity: 0.7;
}
.chapter-card__title { margin-top: calc(var(--space-unit) / 2); }
.chapter-card__line {
  margin-top: var(--space-unit);
  max-width: 40ch;
}

/* Where the About cutouts sit: clear space around the portrait, never on
   top of it or the text. Phones: dog top right, iPod to the right of the
   portrait. Wider: both in the empty area under the text. */
.cutout--about-dog { top: -12px; right: 0; }
.cutout--about-ipod { bottom: -20px; right: 30%; }
@media (min-width: 720px) {
  .cutout--about-dog { top: auto; right: auto; bottom: 8px; left: 52%; }
  .cutout--about-ipod { right: auto; bottom: 24px; left: 24%; }
}

/* ---------- contact (email only) ---------- */
.contact {
  padding-block: calc(var(--space-unit) * 4) calc(var(--space-unit) * 12);
  padding-inline: var(--margin-page);
}
.contact__line {
  text-transform: none;   /* a sentence, not a headline */
  letter-spacing: -0.01em;
  margin-top: calc(var(--space-unit) * 2);
  overflow-wrap: anywhere;
}
.contact__address { text-transform: none; letter-spacing: 0; display: block; } /* the address sits on its own second line */
.contact__address .contact-link { display: inline; }
.contact__address a:hover { text-decoration: underline; text-underline-offset: 0.12em; }

/* ---------- poster generator (Posters, Prints & Illustrations) ---------- */
/* Ink on paper, no neon: this is the work, so it stays plain. */
.poster-tool {
  padding-inline: var(--margin-page);
  padding-block: calc(var(--space-unit) * 2) calc(var(--space-unit) * 8);
}
.poster-tool__intro { max-width: 48ch; }
.poster-tool__tabs {
  display: flex;
  gap: calc(var(--space-unit) * 3);
  margin-top: calc(var(--space-unit) * 3);
}
.poster-tool__tabs button {
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.7;
  padding-bottom: 2px;
  border-bottom: 2px solid transparent;
}
.poster-tool__tabs button:hover { opacity: 0.8; }
.poster-tool__tabs button[aria-pressed="true"] { opacity: 1; border-bottom-color: var(--ink); }

.poster-tool__layout {
  display: grid;
  gap: calc(var(--space-unit) * 4);
  margin-top: calc(var(--space-unit) * 3);
}
@media (min-width: 900px) {
  .poster-tool__layout { grid-template-columns: minmax(0, 1fr) 320px; align-items: start; }
}
.poster-tool__stage canvas {
  display: block;
  margin-inline: auto;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 85vh;
}
.poster-tool__fields { display: grid; gap: calc(var(--space-unit) * 2); }
.poster-field {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-unit) calc(var(--space-unit) * 2);
}
.poster-field--range input { grid-column: 1 / -1; grid-row: 2; width: 100%; accent-color: var(--ink); }
.poster-field--range output { text-align: right; opacity: 0.7; }
.poster-field--color input {
  width: 48px; height: 28px; padding: 0;
  border: 1px solid var(--ink); background: none; cursor: pointer;
}
.poster-field--check input { accent-color: var(--ink); width: 20px; height: 20px; }
.poster-tool__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: calc(var(--space-unit) * 2) calc(var(--space-unit) * 3);
  margin-top: calc(var(--space-unit) * 4);
}
.poster-tool__btn {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--ink);
  border-bottom: 2px solid var(--ink);
  padding-bottom: 2px;
}
.poster-tool__btn:hover { opacity: 0.6; }
.poster-tool__btn:disabled { opacity: 0.4; cursor: wait; }
.poster-tool__link { color: var(--ink); opacity: 0.7; text-decoration: underline; text-underline-offset: 0.2em; }
.poster-tool__link:hover { opacity: 1; }
.poster-tool__random { margin-bottom: calc(var(--space-unit) * 3); }
.poster-tool__note { margin-top: calc(var(--space-unit) * 3); opacity: 0.7; text-transform: none; }
.poster-field select,
.poster-field input[type="number"] {
  font: inherit;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--ink);
  border-radius: 0;
  padding: 2px 0;
  width: 7rem;
}

/* ---------- About: the tools on the desk ---------- */
/* Software logos and tools. They start tucked away; "Tools I use" lets them
   pop out of the button and scatter, "Tidy up" sucks them back in
   (js/tools-toggle.js). Natural size so they stay crisp; positions are
   percentages of the desk. */
.about__desk {
  grid-column: 1 / -1;
  min-height: 460px;
}
.about .cutout { width: auto; max-width: min(265px, 38vw); height: auto; }
.about__desk .cutout {
  left: min(var(--l), calc(100% - 5.5rem));   /* never hang off the right edge, even on a phone */
  top: var(--t);
}
@media (max-width: 899px) {
  .about__desk .cutout { left: min(var(--l), calc(100% - min(272px, 42vw))); }
}
.cutout.is-stowed { visibility: hidden; pointer-events: none; }
.tools-toggle {
  position: relative;
  z-index: 6;
  font-family: var(--font-body);
  font-size: 1.125rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  border-bottom: 2px solid var(--ink);
  padding-bottom: 2px;
}
.tools-toggle:hover { opacity: 0.6; }

/* ---------- desktop frame: header, menu and footer stay in view ---------- */
/* Header on top, footer at the bottom of the screen, menu between them; only
   the page content scrolls. So the footer is always in the fold. */
@media (min-width: 900px) {
  :root { --header-h: 64px; --footer-h: 44px; }
  html { scroll-padding-top: var(--header-h); }
  body { display: flex; flex-direction: column; min-height: 100vh; }
  .shell { flex: 1; }

  .masthead {
    position: sticky;
    top: 0;
    height: var(--header-h);
    align-items: center;
    padding-block: 0;
    background: color-mix(in srgb, var(--paper) 80%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .site-menu,
  .js .site-menu,
  .js .site-menu[hidden] {
    top: var(--header-h);
    height: calc(100vh - var(--header-h) - var(--footer-h));
  }
  .site-footer {
    position: sticky;
    bottom: 0;
    z-index: 40;
    height: var(--footer-h);
    display: flex;
    align-items: center;
    padding-block: 0;
    background: color-mix(in srgb, var(--paper) 80%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .site-footer .wrap { padding-inline: calc(var(--space-unit) * 3); max-width: none; margin-inline: 0; }
  .site-footer__meta { margin-top: 0; }
}

/* ---------- layout: centred sidebar + edge-to-edge work ---------- */
/* After matthias.myportfolio.com: a quiet, centred menu on the left and the
   work filling the rest of the screen, square tiles with no gutters. No card,
   no frame around the content: the page is simply the paper. */
@media (min-width: 900px) {
  .masthead,
  .site-footer {
    background: color-mix(in srgb, var(--paper) 78%, transparent);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
  }
}
/* pages that open straight onto a tile grid: title lines up with the tiles' left edge */
.hero--flush { padding-inline: 0; padding-block: calc(var(--space-unit) * 4) calc(var(--space-unit) * 3); }

/* hero cutouts sit in the top-right corner, clear of the title */
.hero > .cutout { top: 8px; right: 16px; }

/* ---------- header tools: night-mode toggle + phone menu ---------- */
.masthead__tools { display: flex; align-items: center; gap: calc(var(--space-unit) * 2); }
.theme-toggle {
  display: grid;
  justify-items: end;
  align-items: center;
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-label);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  white-space: nowrap;
}
.theme-toggle > * { grid-area: 1 / 1; transition: opacity 0.2s ease; }
.theme-toggle__icon { display: flex; width: 22px; height: 22px; }
.theme-toggle__icon svg { width: 100%; height: 100%; }
.theme-toggle__text { opacity: 0; }
/* light mode shows the moon, night mode shows the sun */
.theme-toggle__icon--sun, .theme-toggle__text--sun { display: none; }
html[data-theme="dark"] .theme-toggle__icon--moon,
html[data-theme="dark"] .theme-toggle__text--moon { display: none; }
html[data-theme="dark"] .theme-toggle__icon--sun,
html[data-theme="dark"] .theme-toggle__text--sun { display: flex; }
html[data-theme="dark"] .theme-toggle__text--sun { display: block; }
/* The icon swaps for its hover text only on devices that really hover. On a phone a tap leaves the
   button "hovered", which used to hide the icon with no text in its place, so the toggle vanished. */
@media (hover: hover) {
  .theme-toggle:hover .theme-toggle__icon,
  .theme-toggle:focus-visible .theme-toggle__icon { opacity: 0; }
  .theme-toggle:hover .theme-toggle__text,
  .theme-toggle:focus-visible .theme-toggle__text { opacity: 1; }
}
@media (hover: none) { .theme-toggle__text { display: none; } }

/* ---------- sidebar: left-aligned, quiet ---------- */
.site-menu__pages a,
.site-menu__group > a { font-size: 0.875rem; }
.site-menu__sub a { font-size: 0.75rem; }
@media (min-width: 900px) {
  .site-menu,
  .js .site-menu,
  .js .site-menu[hidden] { text-align: left; }
  .site-menu a { color: color-mix(in srgb, var(--ink) 62%, transparent); }
  .site-menu__sub a { opacity: 1; color: color-mix(in srgb, var(--ink) 48%, transparent); }
  .site-menu a:hover,
  .site-menu a[aria-current="page"],
  .site-menu a.is-current { color: var(--ink); text-decoration: none; }
  .site-menu a[aria-current="page"] { text-decoration: underline; text-underline-offset: 0.3em; }
}

/* ---------- the central column ---------- */
/* On wide monitors nothing spreads: menu + work live in one column of
   --frame width, centred. Header and footer keep their full-width strips but
   their content lines up with the column. The margins outside are for the
   floating objects. */
@media (min-width: 900px) {
  .masthead,
  .site-footer {
    padding-inline: max(calc(var(--space-unit) * 3), calc((100% - var(--frame)) / 2 + var(--space-unit) * 3));
  }
  .shell { width: 100%; max-width: var(--frame); margin-inline: auto; }
  .site-footer .wrap { padding-inline: 0; }
}
/* big screens: the cutouts float in the margins either side of the column */
@media (min-width: 1700px) {
  .cutout-layer .cutout--list-dog    { left: 7%;  top: 60%; }
  .cutout-layer .cutout--list-ipod   { left: 12%; top: 30%; }
  .cutout-layer .cutout--list-plaque { left: auto; right: 9%; top: 22%; }
}

/* ---------- 404: lost ---------- */
.lost { padding: calc(var(--space-unit) * 10) var(--margin-page) calc(var(--space-unit) * 12); }
.lost__quote { margin: 0; }                /* no browser indent: everything shares one left edge */
.lost__quote[hidden] { display: none; }
.lost__text {
  text-indent: -0.42em;                      /* the opening quote mark hangs in the margin, so the letters line up */
  font-size: clamp(1.5rem, 1rem + 2.2vw, 2.75rem);
  line-height: 1.2;
  letter-spacing: -0.01em;
  max-width: 22em;
}
.lost__by { margin-top: calc(var(--space-unit) * 2); opacity: 0.7; }
.lost__msg { margin-top: calc(var(--space-unit) * 8); font-size: var(--fs-intro); max-width: 24em; }
.lost__again { margin-top: calc(var(--space-unit) * 5); font-size: var(--fs-intro); }
.lost__again a { text-decoration: underline; text-underline-offset: 0.2em; }
.lost__again a:hover { opacity: 0.6; }
/* the tools keep their natural size wherever they land */
.cutout-layer .cutout--tool { width: auto; max-width: 150px; height: auto; }

/* ---------- making-of pages (figures + type specimen list) ---------- */
.fig-grid {
  display: grid;
  gap: calc(var(--space-unit) * 2);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
  margin-top: calc(var(--space-unit) * 3);
}
.fig-grid--single { grid-template-columns: minmax(0, 560px); }
.fig-grid--small { grid-template-columns: repeat(auto-fill, minmax(min(100%, 180px), 1fr)); }
.fig-grid--pairs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fig-grid figure { margin: 0; }
.fig-grid img { display: block; width: 100%; height: auto; }
.fig-grid figcaption { margin-top: var(--space-unit); opacity: 0.7; }
.case-section h3 { margin-top: calc(var(--space-unit) * 3); margin-bottom: var(--space-unit); font-size: 1rem; }
.spec {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-unit) calc(var(--space-unit) * 4);
  margin: calc(var(--space-unit) * 4) 0 0;
  max-width: var(--measure);
  font-size: 0.9375rem;
}
.spec dt { font-weight: 500; }
.spec dd { margin: 0; opacity: 0.8; }
@media (max-width: 640px) { .spec { grid-template-columns: 1fr; gap: 2px; } .spec dd { margin-bottom: var(--space-unit); } }


/* ---------- stepper: one figure at a time, with prev / next (js/stepper.js) ---------- */
.stepper { margin-top: calc(var(--space-unit) * 3); max-width: 640px; }
.stepper__slide { margin: 0; }
.stepper__slide img { display: block; width: 100%; height: auto; }
.stepper__slide + .stepper__slide { margin-top: calc(var(--space-unit) * 2); }
.stepper__bar { display: none; align-items: center; justify-content: center; gap: calc(var(--space-unit) * 2); margin-top: calc(var(--space-unit) * 2); }
.stepper.is-active .stepper__bar { display: flex; }
.stepper.is-active .stepper__slide + .stepper__slide { margin-top: 0; }
.stepper__btn {
  appearance: none; background: none; border: 1px solid currentColor; color: inherit;
  width: 44px; height: 44px; border-radius: 50%; font: inherit; font-size: 1.125rem; line-height: 1; cursor: pointer;
}
.stepper__btn:hover:not(:disabled) { opacity: 0.6; }
.stepper__btn:disabled { opacity: 0.25; cursor: default; }
.stepper__count { min-width: 4.5em; text-align: center; }

/* ---------- spreads (real flipbook pages, two to a row) ---------- */
.spreads { display: grid; gap: calc(var(--space-unit) * 3) calc(var(--space-unit) * 2); grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); margin-top: calc(var(--space-unit) * 3); }
.spread { margin: 0; }
.spread__pages { display: flex; }
.spread__pages img { display: block; width: 50%; height: auto; }
.spread--single .spread__pages { justify-content: center; }
.spread figcaption { margin-top: var(--space-unit); opacity: 0.7; }

/* ---------- photo wall (mixed portrait + landscape, no cropping) ---------- */
.photo-wall { columns: 3 220px; column-gap: calc(var(--space-unit) * 2); margin-top: calc(var(--space-unit) * 3); }
.photo-wall img { display: block; width: 100%; height: auto; margin: 0 0 calc(var(--space-unit) * 2); break-inside: avoid; }

/* ---------- collapsible case sections: only the headline shows until opened ---------- */
details.case-section { padding-block: 0; }
details.case-section > summary {
  display: flex; align-items: baseline; justify-content: space-between; gap: calc(var(--space-unit) * 2);
  padding-block: calc(var(--space-unit) * 3); cursor: pointer; list-style: none;
}
details.case-section > summary::-webkit-details-marker { display: none; }
details.case-section > summary::after { content: "+"; font-size: 1.5rem; line-height: 1; opacity: 0.6; flex: none; }
details.case-section[open] > summary::after { content: "\2212"; }
details.case-section > summary:hover::after { opacity: 1; }
details.case-section > summary:focus-visible { outline: 1px solid currentColor; outline-offset: 4px; }
details.case-section .case-section__title { margin: 0; }
.case-section__body { padding-block: 0 calc(var(--space-unit) * 7); }
.case-section__body > p + p { margin-top: calc(var(--space-unit) * 2); }
.case-section__body > p + .fig-grid,
.case-section__body > p + .stepper { margin-top: calc(var(--space-unit) * 3); }
.case-section__body > .fig-grid + p,
.case-section__body > .spec { margin-top: calc(var(--space-unit) * 3); }

/* two pages shown as one spread, no gap */
.spread--wide { margin-top: calc(var(--space-unit) * 3); max-width: 640px; }

.case-section__body h3.label { margin-top: calc(var(--space-unit) * 5); opacity: 0.7; font-weight: 400; }
.fig-grid--small img { mix-blend-mode: normal; }

/* sub-items in the sidebar read as children of their group */
.site-menu .site-menu__sub { padding-left: calc(var(--space-unit) * 2); }

/* stepper variants: a spread (two pages), a wide pair (spread + diagram), a lone cover */
.stepper__slide .spread__pages { display: flex; }
.stepper__slide .spread__pages img { width: 50%; }
.stepper__slide--cover img { width: 50%; margin-inline: auto; }
.stepper--spread { max-width: 900px; }
.stepper__slide--cover[hidden] { display: none; }
.stepper__slide img { outline: 0; }
/* wireframe pages need an edge to read against the paper */
.stepper__slide:not(.stepper__slide--pair) img[src*="structure-pages"] { outline: 1px solid color-mix(in srgb, var(--ink) 40%, transparent); outline-offset: -1px; }
.fig-grid--cutout img { mix-blend-mode: normal; }

/* Layouts: the layout diagram sits exactly on top of its spread and fades in on hover / focus / tap */
.peek { position: relative; cursor: pointer; }
.peek img { display: block; width: 100%; height: auto; }
.peek__wire { position: absolute; inset: 0; opacity: 0; transition: opacity 0.2s ease; }
.peek:hover .peek__wire,
.peek:focus-visible .peek__wire,
.peek.is-peek .peek__wire { opacity: 1; }
.peek-hint { margin-top: calc(var(--space-unit) * 2); opacity: 0.7; }
@media (prefers-reduced-motion: reduce) { .peek__wire { transition: none; } }
.about__copy .about__bio { max-width: var(--measure); margin-top: calc(var(--space-unit) * 3); }
.about__copy .about__bio a { text-decoration: underline; text-underline-offset: 0.18em; }
.about__copy .intro__text + .about__bio { margin-top: calc(var(--space-unit) * 5); }

/* big underlined link, same look as the "Tools I use" button on About */
.big-link {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 1.125rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  border-bottom: 2px solid var(--ink);
  padding-bottom: 2px;
}
.big-link:hover { opacity: 0.6; }
.big-link-wrap { padding-inline: var(--margin-page); padding-block: 0 calc(var(--space-unit) * 12); }
.big-link--below { position: relative; z-index: 6; display: table; margin-top: calc(var(--space-unit) * 3); }

/* sidebar: a third level that stays hidden behind a "+" until you are on that page */
.site-menu__more {
  margin-left: calc(var(--space-unit) * 1.5);
  font-size: 0.875rem; line-height: 1; opacity: 0.7; vertical-align: baseline;
}
.site-menu__more:hover { opacity: 1; }

/* house-number plaques (page numbers): a neat grid of equal cells, shown at the same scale */
.plaques { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: calc(var(--space-unit) * 3) calc(var(--space-unit) * 2); align-items: center; margin-top: var(--space-unit); max-width: 640px; }
.plaques figure { margin: 0; display: flex; align-items: center; justify-content: center; height: 96px; }
.plaques img { display: block; height: auto; max-height: 100%; max-width: 100%; width: auto; zoom: 1.4; mix-blend-mode: multiply; }
@media (max-width: 560px) { .plaques { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* patterns and textures: every image the same shape and size, cropped to fit */
.fig-grid--equal { grid-template-columns: repeat(2, minmax(0, 1fr)); max-width: 640px; }
.fig-grid--equal img { aspect-ratio: 3 / 2; object-fit: cover; }

/* Paneleirices overview: the four chapters as a small 2x2 of the same tiles the work grid uses.
   Smaller than the homepage tiles on purpose, so they read as parts of this project. */
.chapters { padding-inline: 0; padding-block: calc(var(--space-unit) * 4) calc(var(--space-unit) * 10); } /* flush, like every other tile page */

/* paragraphs in a case section get a line of air between them */
.case-section > p + p { margin-top: calc(var(--space-unit) * 2); }

/* Advertising: phone screenshots in a row, a small banner at its own size */
.stepper--media { max-width: 720px; }
.fig-grid--banner { grid-template-columns: minmax(0, 300px); }
.fig-grid--phones { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: calc(var(--space-unit) * 2); max-width: 760px; }
@media (max-width: 560px) { .fig-grid--phones { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* ======================================================================
   Editorial case-study layout (Paneleirices: Advertising)
   A narrow label column on the left, the writing on the right; the label
   stays in view while you read its chapter. Stacks on phones.
   ====================================================================== */
.stepper__slide[hidden] { display: none; }
.ed { padding-inline: var(--margin-page); padding-block-end: calc(var(--space-unit) * 10); }
.ed-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--space-unit) * 2); }
@media (min-width: 900px) {
  .ed-row { grid-template-columns: minmax(8rem, 11rem) minmax(0, 1fr); column-gap: calc(var(--space-unit) * 6); }
  .ed-row__side { align-self: start; }
  .ed-chapter .ed-row__side,
  .ed-work .ed-row__side { position: sticky; top: calc(var(--header-h, 64px) + var(--space-unit) * 3); }
}
.ed-head { padding-block: calc(var(--space-unit) * 4) calc(var(--space-unit) * 8); }
.ed-meta { margin: 0; display: grid; gap: 2px; font-size: 0.875rem; }
.ed-meta dt { margin-top: calc(var(--space-unit) * 2); opacity: 0.7; }
.ed-meta dt:first-child { margin-top: 0; }
.ed-meta dd { margin: 0; }
.ed-lede { font-size: var(--fs-intro); line-height: 1.32; max-width: 30em; font-weight: 400; }
.ed-chapter, .ed-work { padding-block: calc(var(--space-unit) * 7); border-top: 1px solid color-mix(in srgb, var(--ink) 12%, transparent); }
.ed-title { margin-top: calc(var(--space-unit) / 2); font-size: 1rem; letter-spacing: 0.06em; }
.ed-row__body { min-width: 0; }
.ed-row__body > p { max-width: 38rem; }
.ed-row__body > p + p { margin-top: calc(var(--space-unit) * 2); }
.ed-row__body > h3 { margin-top: calc(var(--space-unit) * 6); margin-bottom: calc(var(--space-unit) * 2); opacity: 0.7; font-weight: 400; }
.ed-row__body > h3:first-child { margin-top: 0; }
.ed-quote { margin: calc(var(--space-unit) * 5) 0 0; padding: 0; max-width: 34rem; }
.ed-quote p:first-child { font-size: var(--fs-intro); line-height: 1.3; }
.ed-quote .label { margin-top: calc(var(--space-unit) * 1.5); opacity: 0.7; }
.ed-fig { margin: 0; }
.ed-fig img { display: block; width: 100%; height: auto; }
.ed-fig--banner img { width: 300px; max-width: 100%; }
.ed-hint { margin-top: calc(var(--space-unit) * 1.5); opacity: 0.7; }

/* A pair (the mockup + the flat artwork) in one frame that never changes height,
   so stepping through the variations doesn't jump. --a / --b are the two pictures' aspect ratios. */
.stepper--diptych { max-width: none; }
.stepper__slide--diptych { display: flex; gap: 2%; aspect-ratio: calc((var(--a) + var(--b)) * 1.0204); }
.stepper__slide--diptych img { height: 100%; width: auto; min-width: 0; object-fit: cover; }
.stepper__slide--diptych img:first-child { flex: var(--a) 1 0; }
.stepper__slide--diptych img:last-child { flex: var(--b) 1 0; }
.stepper--diptych .stepper__slide + .stepper__slide { margin-top: calc(var(--space-unit) * 2); }

/* The phone: stories are swiped inside the hand's phone */
.phone { margin-top: calc(var(--space-unit) * 3); max-width: 520px; outline-offset: 6px; }
.phone__stage { position: relative; width: 100%; aspect-ratio: var(--w) / var(--h); touch-action: pan-y; cursor: grab; user-select: none; -webkit-user-select: none; }
.phone__stage:active { cursor: grabbing; }
.phone__inner { position: absolute; left: 0; top: 0; width: calc(var(--w) * 1px); height: calc(var(--h) * 1px); transform: scale(var(--s, 0.5)); transform-origin: 0 0; }
.phone__screen { position: absolute; left: 0; top: 0; width: 560px; height: 1212px; overflow: hidden; transform-origin: 0 0; background: #0b0f14; }
.phone__strip { display: flex; width: max-content; height: 100%; will-change: transform; }
.phone__strip img { display: block; width: 560px; height: 1212px; flex: none; pointer-events: none; -webkit-user-drag: none; }
.phone__hand { position: absolute; left: 0; top: 0; width: calc(var(--w) * 1px); height: calc(var(--h) * 1px); pointer-events: none; }
.phone__bar { display: flex; align-items: center; gap: calc(var(--space-unit) * 2); margin-top: calc(var(--space-unit) * 2); }
.phone__meta { min-width: 6.5em; text-align: center; }
.phone__dots { display: flex; gap: 6px; margin-top: calc(var(--space-unit) * 1.5); }
.phone__dot { width: 8px; height: 8px; border-radius: 50%; border: 1px solid currentColor; opacity: 0.6; padding: 0; }
.phone__dot[aria-current="true"] { background: currentColor; opacity: 1; }
/* the ads are wide: label on top, pictures across the full column */
@media (min-width: 900px) {
  .ed-work { grid-template-columns: minmax(0, 1fr); }
  .ed-work .ed-row__side { position: static; }
}
/* phones: the pair is too small to read, so show the flat artwork alone (still one fixed frame per row) */
@media (max-width: 640px) {
  .stepper__slide--diptych { display: block; aspect-ratio: var(--b); }
  .stepper__slide--diptych img:first-child { display: none; }
  .stepper__slide--diptych img:last-child { width: 100%; height: 100%; }
}

/* ---- Pausa case study additions (reuses the editorial layout above) ---- */
.stepper--sketch, .stepper--site { max-width: none; }
.stepper__slide--fixed { aspect-ratio: var(--r); }
.stepper__slide--fixed img { width: 100%; height: 100%; object-fit: cover; display: block; }
.stepper--sketch, .stepper--site { margin-top: calc(var(--space-unit) * 3); }
.ed-row__body > .ed-fig { margin-top: calc(var(--space-unit) * 3); margin-bottom: calc(var(--space-unit) * 3); }
.ed-row__body > .ed-fig:last-child { margin-bottom: 0; }

.ed-stats { list-style: none; margin: calc(var(--space-unit) * 3) 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(var(--space-unit) * 3) calc(var(--space-unit) * 4); max-width: 38rem; }
.ed-stat__n { display: block; font-size: clamp(2rem, 1.4rem + 2.4vw, 3.25rem); line-height: 1; font-weight: 500; letter-spacing: 0.01em; }
.ed-stat__t { display: block; margin-top: var(--space-unit); font-size: 0.9375rem; max-width: 18rem; }
@media (max-width: 480px) { .ed-stats { grid-template-columns: 1fr; } }

.ed-table-wrap { overflow-x: auto; margin-top: calc(var(--space-unit) * 3); -webkit-overflow-scrolling: touch; }
.ed-table { border-collapse: collapse; width: 100%; font-size: 0.875rem; line-height: 1.4; }
.ed-table th, .ed-table td { text-align: left; vertical-align: top; padding: calc(var(--space-unit) * 1.25) calc(var(--space-unit) * 1.5) calc(var(--space-unit) * 1.25) 0; border-bottom: 1px solid color-mix(in srgb, var(--ink) 12%, transparent); }
.ed-table thead th { font-size: var(--fs-label); letter-spacing: 0.08em; text-transform: uppercase; font-weight: 500; opacity: 0.7; white-space: nowrap; }
.ed-table tbody th { font-weight: 500; }
.ed-table--compare { min-width: 560px; }
.ed-table--compare td.is-pausa, .ed-table--compare th.is-pausa { background: color-mix(in srgb, #761DF1 10%, transparent); padding-left: calc(var(--space-unit) * 1.5); font-weight: 500; opacity: 1; }
.ed-table--flows { min-width: 560px; }
.ed-sub { display: block; font-weight: 400; opacity: 0.7; margin-top: 2px; }
.ed-dot { display: inline-block; width: 0.6em; height: 0.6em; border-radius: 50%; margin-right: 0.5em; }
.ed-table--heur { min-width: 520px; }
.ed-table--heur th { width: 32%; }
.ed-pill { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 0.75rem; white-space: nowrap; background: color-mix(in srgb, var(--ink) 10%, transparent); }
.ed-pill--pass { background: #038C65; color: #fff; }
.ed-pill--flag, .ed-pill--na, .ed-pill--by-design { background: #D9AE30; color: #1A0B2E; }

.ed-chips { list-style: none; margin: calc(var(--space-unit) * 3) 0 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: var(--space-unit); max-width: 38rem; }
.ed-chips li { display: flex; flex-direction: column; justify-content: space-between; min-height: 76px; padding: calc(var(--space-unit) * 1.25); font-size: 0.75rem; letter-spacing: 0.04em; }

.ed-details { margin-top: calc(var(--space-unit) * 3); }
.ed-details > summary { cursor: pointer; list-style: none; display: inline-flex; gap: 0.75em; align-items: baseline; border-bottom: 1px solid currentColor; padding-bottom: 2px; }
.ed-details > summary::-webkit-details-marker { display: none; }
.ed-details > summary::after { content: "+"; }
.ed-details[open] > summary::after { content: "\2212"; }

/* zoomable images + the lightbox */
img[data-full] { cursor: zoom-in; }
.has-lightbox { overflow: hidden; }
.lightbox { position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center; padding: 3vmin; background: color-mix(in srgb, var(--paper) 94%, transparent); cursor: zoom-out; }
.lightbox img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.lightbox__close { position: absolute; top: 12px; right: 16px; font-size: 2rem; line-height: 1; width: 44px; height: 44px; }

/* the banner shown in context: a news site with the animated ad sitting in its slot */
.ed-scene { position: relative; margin: 0; }
.ed-scene > img { display: block; width: 100%; height: auto; }
.ed-scene__slot { position: absolute; left: 75.206%; top: 17.661%; width: 20.928%; height: 27.258%; overflow: hidden; }
.ed-scene__slot img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Branding case study: fixed-frame steppers (no jumping), framed brand-book pages, contained mockups */
.stepper--ed { max-width: 760px; margin-top: calc(var(--space-unit) * 3); }
.stepper__slide--contain { background: color-mix(in srgb, var(--ink) 5%, transparent); }
.stepper__slide--contain img { object-fit: contain; }
.stepper__slide--framed img { outline: 1px solid color-mix(in srgb, var(--ink) 18%, transparent); outline-offset: -1px; }
.ed-wild { max-width: 760px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr)); }
.ed-wild img { aspect-ratio: 3 / 4; object-fit: cover; }
.stepper--ed .stepper__slide--contain { aspect-ratio: 4 / 3; }
.stepper--ed .stepper__slide--contain img { padding: 4%; box-sizing: border-box; }

/* Resume */
.cv-item + .cv-item { margin-top: calc(var(--space-unit) * 4); }
.cv-item__when { opacity: 0.7; }
.cv-item__title { margin: calc(var(--space-unit) / 2) 0 0; font-size: 1.0625rem; font-weight: 500; }
.cv-item__org { margin: 2px 0 0; }
.cv-item__org span { opacity: 0.7; }
.cv-item__text { margin-top: var(--space-unit); max-width: 38rem; }
.cv-item .ed-details { margin-top: calc(var(--space-unit) * 1.5); }
.cv-list { margin: calc(var(--space-unit) * 1.5) 0 0; padding-left: 1.1em; max-width: 38rem; font-size: 0.9375rem; }
.cv-list li + li { margin-top: var(--space-unit); }
.cv-chips { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.cv-chips li { border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); border-radius: 999px; padding: 4px 12px; font-size: 0.875rem; }
.ed-row__body > h3.label + .cv-chips { margin-bottom: 0; }

/* packaging steppers: fixed frames per stepper, with a small caption under the picture */
.stepper__slide--wide { aspect-ratio: 16 / 9; }
.stepper__slide--tall { aspect-ratio: 3 / 4; max-width: 420px; }
.stepper__slide--sq { aspect-ratio: 1 / 1; }
.stepper__slide figcaption { position: absolute; left: 0; bottom: 0; padding: 6px 10px; background: color-mix(in srgb, var(--paper) 82%, transparent); }
.stepper__slide { position: relative; }
.stepper--ed .stepper__slide--wide.stepper__slide--contain img,
.stepper--ed .stepper__slide--sq.stepper__slide--contain img,
.stepper--ed .stepper__slide--tall.stepper__slide--contain img { padding: 0; width: 100%; height: 100%; object-fit: contain; }
.stepper--ed .stepper__slide--wide.stepper__slide--contain { aspect-ratio: 16 / 9; }
.stepper--ed .stepper__slide--tall.stepper__slide--contain { aspect-ratio: 3 / 4; }
.stepper--ed .stepper__slide--sq.stepper__slide--contain { aspect-ratio: 1 / 1; }
video.loop { display: block; width: 100%; max-width: 640px; height: auto; margin-top: calc(var(--space-unit) * 3); background: color-mix(in srgb, var(--ink) 8%, transparent); }

.cv-kind { margin-left: 0.75em; padding: 1px 8px; border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); border-radius: 999px; font-size: 0.6875rem; }
.cv-item--study .cv-kind { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.cv-item .cv-item__text { opacity: 0.9; }

/* Animations page: the reel is the content; give the last paragraph room */
.case-content:last-of-type { padding-block-end: calc(var(--space-unit) * 10); }
.cv-item__more { margin-top: var(--space-unit); }
.cv-item__more a { text-decoration: underline; text-underline-offset: 0.2em; }
.cv-item__text a { text-decoration: underline; text-underline-offset: 0.2em; }
.cv-item--design .cv-kind { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.ed-lede2 { margin-top: calc(var(--space-unit) * 3); max-width: 34rem; }

/* 3D wordmark in the Paneleirices hero. Positions are percentages of the 1920 x 1080 hero image. */
.logo3d { position: relative; }
/* the 3D wordmark sits on the page itself: no background, no frame; the box is the canvas */
.hero__media.logo3d { aspect-ratio: 1400 / 1000; overflow: visible; max-width: 900px; }
.hero__media.logo3d img { object-fit: contain; }
html[data-theme="dark"] .logo3d > img { filter: invert(1); }
.logo3d__canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: none; pointer-events: none; }
.logo3d.is-3d .logo3d__canvas { display: block; }
.logo3d__zone { position: absolute; left: 14.9%; top: 31.5%; width: 69.9%; height: 38.9%; cursor: pointer; outline-offset: -2px; }

/* ======================================================================
   Story page: four self-contained blocks (the headline, then one block per
   beat of the story). Each beat pairs its words with its picture on a
   6 / 6 split, and the picture swaps sides every time. Hairlines separate
   the blocks. Cut-outs sit on quiet square panels.
   ====================================================================== */
.story { padding: calc(var(--space-unit) * 2) var(--margin-page) calc(var(--space-unit) * 10); max-width: 1240px; }
.story-block { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: calc(var(--space-unit) * 2); align-items: center; padding-block: calc(var(--space-unit) * 7); border-top: 1px solid color-mix(in srgb, var(--ink) 14%, transparent); }
.story-block--head { border-top: 0; padding-block: calc(var(--space-unit) * 4) calc(var(--space-unit) * 7); }
.story-block--head .story__big { grid-column: 1 / 10; }
.story-block--close { padding-block-end: 0; }
.story-block--close .story__big { grid-column: 1 / 9; }
.story-block--close .story__text { grid-column: 1 / 7; margin-top: calc(var(--space-unit) * 3); }
.story-block__fig { grid-column: 7 / 13; margin: 0; min-width: 0; }
.story-block__text { grid-column: 1 / 6; min-width: 0; }
.story-block--flip .story-block__fig { grid-column: 1 / 7; grid-row: 1; }
.story-block--flip .story-block__text { grid-column: 8 / 13; grid-row: 1; }
.story-block__num { opacity: 0.7; margin-bottom: calc(var(--space-unit) * 2); }
.story-block__text .story__text + .story__text { margin-top: calc(var(--space-unit) * 3); }

.story__big { font-size: clamp(1.5rem, 1.1rem + 1.9vw, 2.75rem); line-height: 1.14; letter-spacing: -0.005em; font-weight: 500; max-width: 18em; }
.story__text { font-size: 1rem; max-width: 30rem; }
.story__text--lg { font-size: var(--fs-intro); line-height: 1.3; }
.story__text a { text-decoration: underline; text-underline-offset: 0.2em; }

.panel { position: relative; aspect-ratio: 1; background: color-mix(in srgb, var(--ink) 6%, transparent); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.panel img { display: block; width: 82%; height: 82%; object-fit: contain; }
.panel--swap img { position: absolute; inset: 0; margin: auto; transition: opacity 0.35s ease; }
.panel--swap .panel__hover { opacity: 0; }
.panel--swap:hover .panel__hover { opacity: 1; }
.panel--swap:hover .panel__base { opacity: 0; }
.story figcaption { margin-top: var(--space-unit); display: flex; gap: 1em; opacity: 0.7; }
.story figcaption span { opacity: 0.7; }

@media (max-width: 899px) {
  .story-block { grid-template-columns: 1fr; row-gap: calc(var(--space-unit) * 3); }
  .story-block > * { grid-column: 1 / -1 !important; grid-row: auto !important; }
  .story-block--flip .story-block__fig { order: 2; }
}
@media (prefers-reduced-motion: reduce) { .panel--swap img { transition: none; } }

/* ---- the block system, rolled out to Branding, Packaging, Advertising and the packaging making-of ---- */
.story-block--head { align-items: start; row-gap: calc(var(--space-unit) * 4); }
.story-meta { grid-column: 1 / 13; margin: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: calc(var(--space-unit) * 2) calc(var(--space-unit) * 4); font-size: 0.875rem; }
.story-meta dt { font-size: var(--fs-label); letter-spacing: 0.08em; text-transform: uppercase; font-weight: 500; opacity: 0.7; }
.story-meta dd { margin: 2px 0 0; }
.story-block__title { font-size: 1rem; letter-spacing: 0.06em; margin-bottom: calc(var(--space-unit) * 3); }
.story-block__num + .story-block__title { margin-top: 0; }
.story-block__media { grid-column: 7 / 13; min-width: 0; }
.story-block--flip .story-block__media { grid-column: 1 / 7; grid-row: 1; }
.story-block__media > * + * { margin-top: calc(var(--space-unit) * 4); }
.story-block__media > h3 { margin-top: calc(var(--space-unit) * 5); margin-bottom: calc(var(--space-unit) * 1.5); opacity: 0.7; font-weight: 400; }
.story-block__media > h3:first-child { margin-top: 0; }
.story-block__media .stepper { max-width: none; margin-top: 0; }
.story-block__text .story__text + .story__text,
.story-block__text .story__text + blockquote,
.story-block__text blockquote + .story__text { margin-top: calc(var(--space-unit) * 3); }
.story-block__text .ed-quote { margin-top: calc(var(--space-unit) * 4); max-width: 34rem; }
.story-block--text .story-block__text { grid-column: 1 / 9; }
.story-block--text .ed-quote p:first-child { font-size: var(--fs-intro); line-height: 1.3; }
.story-block--wide { row-gap: calc(var(--space-unit) * 5); align-items: start; }
.story-block--wide .story-block__text { grid-column: 1 / 8; }
.story-block--wide .story-block__media { grid-column: 1 / 13; }
.story-block--wide .stepper { max-width: 880px; }
@media (max-width: 899px) { .story-block__media > * + * { margin-top: calc(var(--space-unit) * 3); } }

/* Sofia: she stands on the bottom edge of her panel, as tall as the panel allows, so her legs run off the frame instead of floating */
.panel--stand { align-items: flex-end; }
.panel--stand img { width: auto; height: 100%; max-width: 100%; margin: 0 auto; left: 0; right: 0; top: auto; bottom: 0; inset: auto 0 0 0; object-position: center bottom; }
.panel--stand.panel--swap img { position: absolute; }

/* Posters page: intro, tiles, then one block per work */
.story__big--intro { font-size: var(--fs-intro); line-height: 1.32; font-weight: 400; max-width: 34em; }
.work__item--type .work__link { background: var(--ink); }
.work__item--type .work__meta { opacity: 1; background: transparent; }
.story-block__meta { opacity: 0.7; margin: calc(var(--space-unit) * -2) 0 calc(var(--space-unit) * 3); }
.story__links { display: flex; flex-direction: column; gap: var(--space-unit); margin-top: calc(var(--space-unit) * 4); }
.story__links a { text-decoration: underline; text-underline-offset: 0.25em; }
.stepper__slide--tall { max-width: none; }
.stepper--ed .stepper__slide--tall.stepper__slide--contain { aspect-ratio: 3 / 4; }

/* See the code: code on the left, the poster appearing on the right */
.runner { padding: calc(var(--space-unit) * 2) var(--margin-page) calc(var(--space-unit) * 10); max-width: 1240px; }
.runner__bar { display: flex; flex-wrap: wrap; align-items: center; gap: calc(var(--space-unit) * 2) calc(var(--space-unit) * 3); margin-bottom: calc(var(--space-unit) * 3); }
.runner__tabs { display: flex; gap: var(--space-unit); }
.runner__tab, .runner__play { font-size: 0.875rem; padding: 6px 14px; border: 1px solid color-mix(in srgb, var(--ink) 35%, transparent); border-radius: 999px; }
.runner__tab[aria-pressed="true"] { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.runner__make { margin-left: auto; text-decoration: underline; text-underline-offset: 0.25em; }
.runner__split { display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--space-unit) * 2); }
.runner__code { height: 42vh; min-height: 260px; overflow: hidden; background: color-mix(in srgb, var(--ink) 6%, transparent); padding: calc(var(--space-unit) * 2); }
.runner__lines { font-size: 0.8125rem; line-height: 1.55; font-variant-numeric: tabular-nums; }
.runner__line { padding-left: calc(var(--i, 0) * 1.6em + 10px); border-left: 2px solid transparent; opacity: 0.22; white-space: pre; transition: opacity 0.2s; }
.runner__line.is-seen { opacity: 1; }
.runner__line.is-run { background: color-mix(in srgb, var(--ink) 10%, transparent); border-left-color: var(--ink); }
.runner__line b { font-weight: 600; }
.runner__line i { font-style: normal; opacity: 0.7; }
.runner__stage { display: flex; align-items: flex-start; justify-content: center; height: 52vh; min-height: 300px; background: color-mix(in srgb, var(--ink) 6%, transparent); padding: calc(var(--space-unit) * 2); }
.runner__stage canvas { display: block; box-shadow: 0 2px 16px rgba(0, 0, 0, 0.12); }
@media (min-width: 900px) {
  .runner__split { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); gap: calc(var(--space-unit) * 3); }
  .runner__code { height: 74vh; }
  .runner__stage { height: 74vh; align-items: center; }
}
.stepper__video { display: block; width: 100%; height: 100%; object-fit: contain; background: transparent; }
.story-meta > div:first-child { grid-column: span 2; }
@media (max-width: 560px) { .story-meta > div:first-child { grid-column: auto; } }

/* Bairros: the Funerária sign is part of the author layer (like the 58A plaque), never part of the text */
.hero > .cutout--funeraria { top: auto; left: auto; bottom: 6%; right: 1%; width: 22vw; max-width: 170px; }

/* ---- scan, then expand: each theme is one headline line until you open it ---- */
details.story-fold { border-top: 1px solid color-mix(in srgb, var(--ink) 14%, transparent); }
details.story-fold:last-of-type { border-bottom: 1px solid color-mix(in srgb, var(--ink) 14%, transparent); }
details.story-fold > summary { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; gap: 0 calc(var(--space-unit) * 2); padding-block: calc(var(--space-unit) * 3); cursor: pointer; list-style: none; }
details.story-fold > summary::-webkit-details-marker { display: none; }
details.story-fold > summary::after { content: "+"; font-size: 1.5rem; line-height: 1; opacity: 0.6; }
details.story-fold[open] > summary::after { content: "\2212"; }
details.story-fold > summary:hover::after { opacity: 1; }
details.story-fold > summary:focus-visible { outline: 1px solid currentColor; outline-offset: 4px; }
.fold__title { font-size: 1.0625rem; letter-spacing: 0.05em; margin: 0; }
.fold__tease { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; margin-top: 6px; font-size: 0.9375rem; opacity: 0.7; max-width: 40rem; }
details.story-fold[open] .fold__tease { display: none; }
details.story-fold > .story-block { border-top: 0; padding-block: calc(var(--space-unit) * 2) calc(var(--space-unit) * 8); }

/* Bairros: the description on the left, role / school / tools in a quiet column on the right */
.case-content:has(.story-meta--page) { max-width: none; display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--space-unit) * 5); align-items: start; }
.story-meta--page { grid-column: auto; margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: calc(var(--space-unit) * 3); font-size: 0.875rem; }
.story-meta--page > div:first-child { grid-column: auto; }
@media (min-width: 900px) {
  .case-content:has(.story-meta--page) { grid-template-columns: minmax(0, 38rem) minmax(11rem, 15rem); justify-content: space-between; gap: calc(var(--space-unit) * 8); }
  .story-meta--page { padding-top: 6px; }
}
/* Claro: its own palette on the hero (the work speaking) */

/* nested fold (print-ready inside the business card) */
details.story-fold--nested { margin-bottom: calc(var(--space-unit) * 6); }
details.story-fold--nested > summary { padding-block: calc(var(--space-unit) * 2); }
details.story-fold--nested .fold__title { font-size: 1rem; }

/* hyperlinks are underlined everywhere except the main menu, masthead and project tiles */
.shell__main a:not(.work__link):not(.big-link):not(.cutout-swap),
.site-footer a,
.chapter-nav a,
.chapter-next a { text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }

/* "click here": looks like every other link, opens the question-and-answer card */
.ask-link { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
.ask-link:hover { opacity: 0.6; }
.case-content__text p + p { margin-top: 1em; }

/* the card: a question, then an answer, like a chat with an AI */
dialog.ask { padding: 0; border: 1px solid color-mix(in srgb, var(--ink) 18%, transparent); border-radius: 16px; background: var(--paper); color: var(--ink); width: min(680px, calc(100vw - 24px)); max-height: min(86vh, 860px); overflow: hidden; }
dialog.ask::backdrop { background: rgb(0 0 0 / 0.45); }
dialog.ask[open] { display: flex; flex-direction: column; }
.ask__close { position: absolute; top: 10px; right: 12px; z-index: 1; margin: 0; }
.ask__close button { width: 44px; height: 44px; border: 0; background: none; color: inherit; font: inherit; font-size: 1.5rem; line-height: 1; cursor: pointer; opacity: 0.7; }
.ask__close button:hover { opacity: 1; }
.ask__scroll { overflow-y: auto; padding: calc(var(--space-unit) * 6) calc(var(--space-unit) * 3) calc(var(--space-unit) * 4); font-size: 0.9375rem; line-height: 1.6; }
.ask__user { margin: 0 0 calc(var(--space-unit) * 4) auto; width: fit-content; max-width: 85%; padding: 10px 16px; border-radius: 18px 18px 4px 18px; background: color-mix(in srgb, var(--ink) 9%, transparent); }
.ask__answer > * + * { margin-top: 0.9em; }
.ask__word { font-family: inherit; font-size: 1.25rem; font-weight: 500; margin: 0; text-transform: none; letter-spacing: 0; }
.ask__meta { opacity: 0.7; font-size: 0.875rem; }
.ask__senses { padding-left: 1.25em; display: grid; gap: 0.9em; list-style: decimal; }
.ask__senses p { margin: 0; }
.ask__senses .ask__ex { margin-top: 0.4em; padding-left: 0.9em; border-left: 2px solid color-mix(in srgb, var(--ink) 20%, transparent); opacity: 0.85; }
.ask__notes { padding-left: 1.25em; display: grid; gap: 0.6em; list-style: disc; }
.ask__senses li::marker, .ask__notes li::marker { opacity: 0.6; }
@media (min-width: 700px) { .ask__scroll { padding-inline: calc(var(--space-unit) * 5); } }
/* the canvas has breathing room around the wordmark; pull it up so the layout sits like Bairros */
.hero__media.logo3d { margin-top: calc(var(--space-unit) * -2); margin-bottom: calc(var(--space-unit) * -8); }

/* tools on Timelines & stuff: chips are buttons; one opens a list of the projects that used it */
.cv-chips li:has(> .cv-chip) { padding: 0; border: 0; }
.cv-chip { font: inherit; font-size: 0.875rem; color: inherit; background: none; cursor: pointer; border: 1px solid color-mix(in srgb, var(--ink) 30%, transparent); border-radius: 999px; padding: 4px 12px; }
.cv-chip:hover, .cv-chip[aria-expanded="true"] { border-color: var(--ink); }
.cv-chip[aria-expanded="true"] { background: var(--ink); color: var(--paper); }
.cv-tool-panel { margin: calc(var(--space-unit) * 2) 0 calc(var(--space-unit) * 3); padding: calc(var(--space-unit) * 2) 0 0; border-top: 1px solid color-mix(in srgb, var(--ink) 14%, transparent); font-size: 0.9375rem; }
.cv-tool-panel p { margin: 0 0 calc(var(--space-unit) * 1); }
.cv-tool-panel ul { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 20px; }

/* forward link at the top of a chapter page, opposite the way back */
.chapter-nav__next { margin-left: auto; }

/* labels: drag to rearrange, snapping to a grid */
.label-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: calc(var(--space-unit) * 1.5); max-width: 900px; }
@media (min-width: 700px) { .label-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.label-cell { position: relative; aspect-ratio: 1 / 1; transition: background-color .15s; }
.label-cell.is-target { background: color-mix(in srgb, var(--ink) 8%, transparent); }
.label-item { position: absolute; inset: 0; padding: 12%; margin: 0; border: 0; background: none; cursor: grab; touch-action: none; user-select: none; -webkit-user-select: none; display: flex; align-items: center; justify-content: center; }
.label-item img { max-width: 100%; max-height: 100%; width: auto; height: auto; pointer-events: none; }
.label-item.is-dragging { cursor: grabbing; z-index: 5; filter: drop-shadow(0 10px 18px rgb(0 0 0 / 0.25)); }
.label-item:focus-visible { outline: 1px solid currentColor; outline-offset: 2px; }

/* a smaller carousel (The making of), with a video slide that fits its frame */
.stepper__slide video { display: block; width: 100%; height: 100%; object-fit: contain; }
.stepper--small, .story-block--wide .stepper.stepper--small { max-width: 420px; }
.stepper--ed.stepper--small .stepper__slide--fixed.stepper__slide--contain { aspect-ratio: var(--r); }
.stepper--ed.stepper--small .stepper__slide--contain img { padding: 0; width: 100%; height: 100%; object-fit: contain; }

/* the iPod sits low in the menu column, above the footer, so it never lands on text */
.cutout-layer .cutout--list-ipod { top: auto; bottom: calc(var(--footer-h, 44px) + 18px); }

.contact__body { margin: calc(var(--space-unit) * 3) 0 0; max-width: 34rem; }

/* Jacquie: a little bigger, and when you hover her or hold her she slowly turns upright (-160deg puts the chair on its base) */
.cutout--dog { max-width: 150px; transform: rotate(-6deg); transition: transform 2.2s cubic-bezier(.35,0,.2,1); }
.cutout--dog:hover, .cutout--dog.cutout--dragging { transform: rotate(-160deg); }
.cutout-layer .cutout--dog { width: clamp(84px, 9vw, 140px); max-width: none; }
@media (prefers-reduced-motion: reduce) { .cutout--dog { transition-duration: 0.01s; } }

/* section pictures on the Advertising page */
.ed-fig--sect { max-width: 420px; }
.ed-fig--ink { max-width: 360px; }
html[data-theme="dark"] .ed-fig--ink img { filter: invert(1); }

/* Pausa: fullscreen toggle for the prototype. It sits in the gap above the frame, so nothing shifts. */
.proto-toggle { position: absolute; top: -26px; right: 0; background: none; border: 0; padding: 0; color: inherit; cursor: pointer; opacity: 0.7; }
.proto-toggle:hover { opacity: 1; }
.proto:fullscreen { width: 100vw; height: 100vh; margin: 0; background: #000; }
.proto:-webkit-full-screen { width: 100vw; height: 100vh; margin: 0; background: #000; }
.proto:fullscreen .proto-toggle { top: 12px; right: 16px; color: #FAF9F6; z-index: 2; }
.proto:-webkit-full-screen .proto-toggle { top: 12px; right: 16px; color: #FAF9F6; z-index: 2; }


/* Home welcome: two lines slide up through a frame, slide away, then the tiles appear one by one.
   Only when js/intro.js plays it (first visit per session, no reduced motion). Otherwise the h1 is
   visually hidden and the tiles are simply there. */
.intro { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: -1px; }
html.intro-play main#main { position: relative; }
html.intro-play .intro {
  position: absolute; inset: 0 0 auto 0; width: auto; height: auto; clip: auto; margin: 0; white-space: normal; overflow: visible;
  z-index: 3; pointer-events: none; padding: calc(var(--space-unit) * 2) calc(var(--space-unit) * 4);
  font-size: clamp(2.5rem, 6.2vw, 7rem); font-weight: 400; line-height: 1.06; letter-spacing: -0.02em; text-transform: none;
}
.intro__frame { display: block; overflow: hidden; padding-bottom: 0.08em; }
.intro__line { display: block; }
html.intro-play .intro__line { transform: translateY(105%); }
/* The tiles are drawn from the start and hidden under a paper-coloured cover that fades away, one tile
   after another. Looks the same as fading the tile in, but browsers (and PageSpeed) see the pictures as
   shown straight away instead of after the intro. */
html.intro-play .work__item { position: relative; }
html.intro-play .work__item::after {
  content: ''; position: absolute; inset: -1px; z-index: 2; pointer-events: none; background: var(--paper);   /* -1px: no hairline at tile edges */
  transition: opacity 500ms ease-out var(--reveal-delay, 0ms);
  animation: intro-failsafe 0s linear 8s forwards;   /* never leave the tiles hidden */
}
html.intro-play .work__item.is-revealed::after { opacity: 0; }
@keyframes intro-failsafe { to { opacity: 0; } }

/* tile pages on phones: the title keeps the page margin (the flush alignment is for the desktop grid) */
@media (max-width: 899px) { .hero--flush { padding-inline: var(--margin-page); } }

/* menu button: the + turns into an × by rotating, so both states are the same glyph and size */
.menu-toggle { transition: transform 0.25s ease; }
.menu-toggle[aria-expanded="true"] { transform: rotate(45deg); }
@media (prefers-reduced-motion: reduce) { .menu-toggle { transition: none; } }

/* phones: the menu stays closed from the very first paint, before js/menu.js (deferred) has run */
@media (max-width: 899px) { html.js:not(.menu-ready) .site-menu { display: none; } }
