/* Local copy of the Framer site (Nov 10): Home wall after rachelchen.tech in Hugo's identity, project pages, About.
   Tokens, type and breakpoints follow the Framer project: phone < 810, tablet 810–1199, desktop ≥ 1200; 16-col grid. */
@font-face { font-family: Montreal; src: url(fonts/PPNeueMontreal-Regular.woff2) format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: Montreal; src: url(fonts/PPNeueMontreal-Medium.woff2) format("woff2"); font-weight: 500; font-display: swap; }
:root { --ink: #fff; --paper: #000; --surface: #141414; --mute: #8c8c8c; --value: #a0a0a0; --mx: 42px; --g: 20px; --my: 32px; }
:root[data-theme="light"] { --ink: #000; --paper: #fff; --surface: #f2f2f2; --mute: #767676; --value: #6b6b6b; }   /* mute #767676 = 4.5:1 on white (was #8c8c8c, 3.4:1, under AA; Nov 11 test) */
* { box-sizing: border-box; margin: 0; padding: 0; }
html { background: var(--paper); color: var(--ink); font-family: Montreal, system-ui, sans-serif; -webkit-font-smoothing: antialiased; transition: background-color 300ms; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; text-align: left; }
img, video { display: block; }
.label { font-size: 14px; line-height: 1.2; font-weight: 500; }
.meta { font-size: 14px; line-height: 1.2; color: var(--mute); }
.value { font-size: 14px; line-height: 1.2; color: var(--value); }
.heading { font-size: clamp(20px, 1.67vw, 30px); line-height: 1.05; font-weight: 500; }
.heading.value { color: var(--value); }
.body { font-size: 16px; line-height: 1.4; }
.body.value { color: var(--value); }
.grid { display: grid; grid-template-columns: repeat(16, minmax(0, 1fr)); column-gap: var(--g); padding: 0 var(--mx); }
.u { position: relative; display: inline-block; }
.u::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 1px; background: currentColor; opacity: 0; filter: blur(2px); transition: opacity 200ms, filter 200ms; }
.u:hover::after { opacity: 1; filter: blur(0); }
.btn { display: inline-flex; align-items: center; justify-content: space-between; gap: 16px; padding: 9px 10px; background: var(--ink); color: var(--paper); box-shadow: inset 0 0 0 1px var(--ink); font-size: 14px; font-weight: 500; line-height: 1.2; transition: background 160ms, color 160ms; }
.btn:hover { background: var(--paper); color: var(--ink); }
.muted-link { color: var(--mute); } .muted-link:hover { color: var(--ink); }

/* entrances: fade in with a blur on text, fade only on pictures; once per page */
@keyframes fx-in { from { opacity: .01; filter: blur(12px); } }
@keyframes fade-in { from { opacity: .01; } }
.in { animation: fx-in 600ms cubic-bezier(.2, .7, .2, 1) backwards; }
.in-pic { animation: fade-in 600ms cubic-bezier(.2, .7, .2, 1) backwards; }

/* grain, Level 1 */
.grain { position: fixed; inset: 0; pointer-events: none; z-index: 60; opacity: .55; mix-blend-mode: soft-light; background: url(https://framerusercontent.com/images/RHON4vGQSrjcx7a5DmhR87lW4M.webp) repeat; background-size: 256px; }

/* ---------- Home: the wall ---------- */
.rail { position: fixed; left: var(--mx); top: var(--my); z-index: 20; display: flex; flex-direction: column; }
.rail nav { display: flex; flex-direction: column; gap: 8px; padding-top: 127px; }
.theme-fixed { position: fixed; right: var(--mx); top: var(--my); z-index: 20; }
.home main { grid-column: 4 / span 11; padding: 176px 0 120px; }
.statement { font-size: 44px; line-height: 1.08; letter-spacing: -0.01em; font-weight: 500; max-width: 900px; }
@media (min-width: 1200px) { .statement { font-size: clamp(40px, 3.05vw, 64px); max-width: 20.5em; } }
.facts { display: flex; gap: var(--g); padding-top: 48px; }
.facts > div { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.wall { display: flex; gap: 16px; padding-top: 64px; align-items: flex-start; }
.wall .col { flex: 1; display: flex; flex-direction: column; gap: 32px; min-width: 0; }
.wall-phone { display: none; flex-direction: column; gap: 28px; padding-top: 40px; }
.card { display: flex; flex-direction: column; gap: 10px; }
.cover { position: relative; width: 100%; overflow: hidden; background: var(--surface); }
.cover img, .cover video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.cover video { opacity: 0; transition: opacity 600ms ease; }
.cover video.on { opacity: 1; }
.cap { display: flex; flex-wrap: wrap; gap: 0 6px; }
.cap .kv { display: inline-flex; gap: 0 6px; white-space: nowrap; }   /* kind + year stay together */
.cap.two .sl { display: none; }   /* on their own line, no slash */
.foot { display: flex; justify-content: space-between; align-items: center; padding-top: 120px; }
.foot .soc, .row-soc { display: flex; gap: 20px; }
.phone-top { display: none; }

/* phone top row + menu sheet (used on every page on phones) */
.ptop { display: flex; justify-content: space-between; align-items: center; padding: 16px var(--mx) 0; }
.ptop .wm { font-size: min(34px, calc(((100vw - 88px) / 2 + 16px) * .1749)); font-weight: 500; line-height: 1.2; }
.sheet { position: fixed; inset: 0; z-index: 900; background: var(--paper); display: none; flex-direction: column; padding: 16px var(--mx) 24px; animation: fade-in 120ms; }
.sheet.open { display: flex; }
.sheet .links { margin-top: auto; display: flex; flex-direction: column; gap: 8px; }
.sheet .links a { font-size: min(34px, calc(((100vw - 88px) / 2 + 16px) * .1749)); font-weight: 500; line-height: 1.05; animation: fx-in 350ms cubic-bezier(.2,.7,.2,1) 120ms backwards; }
.sheet .btn { margin-top: 24px; justify-content: space-between; font-size: 18px; padding: 14px 12px; }

/* ---------- Top row (project + about pages) ---------- */
.toprow { position: relative; z-index: 5; padding-top: var(--my); align-items: start; }
.toprow .wm { grid-column: 1 / 3; font-size: calc(((100vw - 384px) / 8 + 20px) * .1749); font-weight: 500; line-height: 1.2; white-space: nowrap; }
.pair { display: flex; flex-direction: column; gap: 3px; }
.toprow .based { grid-column: 5 / 8; } .toprow .now { grid-column: 9 / 13; }
.toprow .n1 { grid-column: 13 / 14; } .toprow .n2 { grid-column: 14 / 15; }
.toprow .cta { grid-column: 15 / 17; align-self: start; }
.pair .meta + .label { margin-top: 0; }

/* ---------- Project page ---------- */
.first { position: relative; height: 100vh; height: 100svh; overflow: hidden; display: flex; flex-direction: column; }
.first .bg, .first .bg img, .first .bg video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.first .bg video { opacity: 0; transition: opacity 400ms; } .first .bg video.on { opacity: 1; }
.first .scrim { position: absolute; inset: 0; background: var(--paper); opacity: .35; }
.first .band { position: absolute; left: 0; right: 0; top: 50%; transform: translateY(-50%); }
.first .band .c { grid-column: 1 / 5; } .first .band .p { grid-column: 5 / 12; }
.first .bottom { margin-top: auto; padding-bottom: var(--my); position: relative; align-items: end; row-gap: 24px; }
.first .tag { grid-column: 1 / 5; grid-row: 1; }
.first .brow { grid-column: 1 / -1; grid-row: 2; display: grid; grid-template-columns: repeat(16, minmax(0, 1fr)); column-gap: var(--g); align-items: baseline; }
.brow .c1 { grid-column: 1 / 5; } .brow .c2 { grid-column: 5 / 9; } .brow .c3 { grid-column: 9 / 13; } .brow .c4 { grid-column: 13 / 17; }
.split { align-items: start; }
.split .left { grid-column: 1 / 5; position: sticky; top: 0; height: 100vh; height: 100svh; display: flex; flex-direction: column; padding: var(--my) 0; }
.left-top { display: flex; gap: 32px; align-items: baseline; }
.left-top .wm { font-size: calc(((100vw - 384px) / 8 + 20px) * .1749); font-weight: 500; line-height: 1.2; white-space: nowrap; }
.left-body { margin-top: 65px; display: flex; flex-direction: column; gap: 40px; overflow-y: auto; scrollbar-width: none; flex: 1; min-height: 0; }
.left-body .blk { display: flex; flex-direction: column; gap: 8px; }
.facts2 { display: grid; grid-template-columns: 1fr 1fr; gap: 24px 20px; }
.progress { margin-top: 24px; position: relative; height: 26px; }
.progress .v { position: absolute; left: 0; top: 0; }
.progress .track { position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: color-mix(in srgb, var(--ink) 18%, transparent); }
.progress .fill { position: absolute; left: 0; bottom: 0; height: 1px; width: 100%; background: var(--ink); transform-origin: left; transform: scaleX(0); }
.media { grid-column: 6 / 17; padding: var(--my) 0 96px; display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.shot { position: relative; width: 100%; aspect-ratio: 16 / 9; background: var(--surface); overflow: hidden; }
.shot img, .shot video, .shot iframe, .shot button { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border: 0; }
.shot button span { position: absolute; left: 20px; bottom: 20px; padding: 6px 8px; background: var(--ink); color: var(--paper); line-height: 1.2; }   /* a filled tag like the View project tag: white "(Play)" on bright film stills was down to 1.4:1 (Nov 11 test) */
.next { padding-top: 40px; display: flex; flex-direction: column; gap: 8px; }
.next .shot img { filter: grayscale(1); transition: filter 400ms; } .next:hover .shot img { filter: none; }
.endrow { padding-bottom: var(--my); align-items: baseline; }
.endrow .c2 { grid-column: 6 / 9; } .endrow .c3 { grid-column: 9 / 13; } .endrow .c4 { grid-column: 13 / 17; }
/* pages presenter */
.pages-bar { position: sticky; top: 0; z-index: 3; background: var(--paper); display: flex; justify-content: space-between; align-items: baseline; gap: 20px; padding: 16px 0 12px; }
.pages-bar .tabs { display: flex; flex-wrap: wrap; gap: 4px 20px; }
.pages-bar button { opacity: .6; } .pages-bar button.on, .pages-bar button:hover { opacity: 1; }
.pages-bar .ctl { display: flex; gap: 20px; flex-shrink: 0; }
.pages-body img { width: 100%; height: auto; background: var(--surface); }
.pages-body { animation: fade-in 320ms cubic-bezier(.2,.7,.2,1); }

/* ---------- About ---------- */
.about-bg { position: fixed; inset: 0; z-index: -1; }
.about-bg video, .about-bg img { width: 100%; height: 100%; object-fit: cover; }
.about-bg::after { content: ""; position: absolute; inset: 0; background: var(--paper); opacity: .35; }
.about { padding-top: 120px; padding-bottom: 40px; align-items: start; min-height: calc(100vh - 80px); }
.about .a1 { grid-column: 1 / 5; display: flex; flex-direction: column; gap: 24px; }
.about .a2 { grid-column: 6 / 12; }
.about .a3 { grid-column: 13 / 17; display: flex; flex-direction: column; gap: 24px; }
.about .blk { display: flex; flex-direction: column; gap: 8px; }
.about .role { display: none; } .about .role.on { display: block; animation: fx-in 400ms cubic-bezier(.2,.7,.2,1) backwards; }
.about .rcols { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 32px; }
.about .rcols ul { list-style: none; display: flex; flex-direction: column; gap: 8px; }
.about .names button { display: block; } .about .names button:not(.on) { color: var(--mute); }
.about .btn-l { width: 100%; font-size: 20px; padding: 14px 16px; }

/* ---------- tablet ---------- */
@media (max-width: 1199.98px) {
  :root { --mx: 24px; }
  .rail { left: 24px; } .theme-fixed { right: 24px; }
  .home main { grid-column: 5 / span 12; padding: 152px 0 96px; }
  .statement { font-size: 32px; }
  .toprow .wm, .left-top .wm { font-size: max(16px, calc(((100vw - 348px) / 8 + 20px) * .1749)); }
  .toprow .based { display: none; } .toprow .now { grid-column: 4 / 11; } .toprow .n1 { grid-column: 11 / 12; } .toprow .n2 { grid-column: 12 / 13; } .toprow .cta { grid-column: 13 / 17; }
  .split .left { grid-column: 1 / 7; } .media { grid-column: 7 / 17; }
  .about .a1 { grid-column: 1 / 7; } .about .a2 { grid-column: 8 / 17; } .about .a3 { grid-column: 8 / 17; margin-top: 40px; }
}
/* ---------- phone ---------- */
@media (max-width: 809.98px) {
  :root { --mx: 20px; --g: 16px; --my: 16px; }
  .rail, .theme-fixed, .toprow { display: none; }
  .phone-top { display: block; }
  .home .grid { display: block; }
  .home main { padding: 48px 0 64px; }
  .statement { font-size: 28px; }
  .facts { flex-direction: column; gap: 20px; padding-top: 32px; }
  .wall { display: none; } .wall-phone { display: flex; }
  .foot { flex-direction: column; align-items: flex-start; gap: 16px; padding-top: 72px; }
  .heading { font-size: 24px; }
  .first .band { display: none; }
  .first .bottom { display: block; } .first .tag { margin-bottom: 24px; }
  .first .brow { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px; } .brow .c2, .brow .c3 { display: none; }
  .split { display: block; }
  .split .left { position: static; height: auto; padding-top: 32px; } .left-top { display: none; } .left-body { margin-top: 0; overflow: visible; gap: 28px; } .progress { display: none; }
  .media { padding-top: 28px; }
  .endrow { display: flex; flex-direction: column; gap: 12px; } .endrow .c2 { grid-column: auto; }
  .about { display: block; padding-top: 40px; } .about .a2, .about .a3 { margin-top: 48px; } .about .rcols { grid-template-columns: 1fr; }
}

/* ---------- Nov 10 (later): every page on the Home's layout, after rachelchen.tech ---------- */
/* "View project": a square tag that follows the pointer over a cover (hover screens only) */
.view-tag { position: fixed; left: 0; top: 0; z-index: 80; pointer-events: none; padding: 6px 8px; background: var(--ink); color: var(--paper); font-size: 14px; font-weight: 500; line-height: 1.2; opacity: 0; filter: blur(6px); transition: opacity 180ms, filter 180ms; white-space: nowrap; }
.view-tag.on { opacity: 1; filter: blur(0); }
@media (hover: none) { .view-tag { display: none; } }

/* the shared frame: rail on the left, theme top-right, content column */
.shell main { grid-column: 4 / span 11; padding: 176px 0 120px; }
.crumb { display: flex; gap: 6px; align-items: baseline; }
.toc { display: flex; flex-direction: column; gap: 8px; padding-top: 127px; max-height: calc(100vh - 220px); overflow-y: auto; scrollbar-width: none; }
.toc a { color: var(--mute); } .toc a:hover, .toc a.on { color: var(--ink); }
.toc a.sub { padding-left: 12px; }
.sec { padding-top: 96px; scroll-margin-top: 24px; }
.sec > .meta:first-child { display: block; margin-bottom: 16px; }
.text { max-width: 760px; }
.title { font-size: 34px; line-height: 1.1; letter-spacing: -0.01em; font-weight: 500; }
@media (min-width: 1200px) { .title { font-size: clamp(32px, 2.4vw, 46px); } }
.pfacts { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 20px var(--g); padding-top: 40px; max-width: 760px; }
.pfacts > div { display: flex; flex-direction: column; gap: 4px; }
.lead-body { font-size: 18px; line-height: 1.45; color: var(--value); max-width: 680px; }
.impact { display: flex; flex-direction: column; gap: 4px; margin-top: 40px; }
.impact .big { font-size: clamp(40px, 4vw, 64px); line-height: 1; font-weight: 500; letter-spacing: -0.02em; }
.hero { position: relative; aspect-ratio: 16 / 9; overflow: hidden; background: var(--surface); }
.hero img, .hero video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero video { opacity: 0; transition: opacity 400ms; } .hero video.on { opacity: 1; }
.stack { display: flex; flex-direction: column; gap: 20px; }
.two { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.next-card { max-width: 560px; }
/* About: timeline */
.tl { display: flex; flex-direction: column; gap: 40px; }
.tl .row { display: grid; grid-template-columns: 3fr 8fr; gap: var(--g); }
.tl .when { color: var(--mute); } .tl .when.now { color: var(--ink); }
.tl .detail { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 16px; }
.tl ul { list-style: none; display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.clients { columns: 3; column-gap: var(--g); }
.clients div { break-inside: avoid; }
.phone-crumb { display: none; }
@media (max-width: 1199.98px) { .shell main { grid-column: 5 / span 12; padding: 152px 0 96px; } .title { font-size: 28px; } .pfacts { grid-template-columns: 1fr 1fr; } }
@media (max-width: 809.98px) {
  .shell .grid { display: block; } .shell main { padding: 32px 0 64px; }
  .phone-crumb { display: flex; padding: 16px var(--mx) 0; }
  .title { font-size: 26px; } .sec { padding-top: 64px; } .pfacts { padding-top: 28px; }
  .two { grid-template-columns: 1fr; } .tl .row { grid-template-columns: 1fr; gap: 4px; } .tl .detail { grid-template-columns: 1fr; } .clients { columns: 2; }
}

/* YouTube draws a thin progress line along its bottom edge while a film plays: the player runs 8px past the box, which crops it */
.shot iframe { top: 0; bottom: auto; height: calc(100% + 8px); }
.next-two { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 809.98px) { .next-two { grid-template-columns: 1fr; gap: 28px; } }

/* Start a project, always there, bottom right (Hugo, Nov 10) */
.cta-fixed { position: fixed; right: var(--mx); bottom: var(--my); z-index: 70; min-width: 170px; }
.foot, .endrow { padding-bottom: 72px; }   /* the footer clears the button */
@media (max-width: 809.98px) { .cta-fixed { min-width: 0; } .sheet.open ~ .cta-fixed, body:has(.sheet.open) .cta-fixed { display: none; } }

/* ===================== Nov 10: everything on the 16-column grid (Hugo) =====================
   The content area spans page columns 4–15 (12 columns; tablet 5–16) and is itself a 12-column grid with the page's gutter,
   so every block below starts and ends on a page column. Nested blocks use subgrid to keep the same lines. */
.home main, .shell main { grid-column: 4 / span 12; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--g); align-content: start; }
.home main > *, .shell main > * { grid-column: 1 / -1; }
.statement { grid-column: 1 / 10 !important; max-width: none; }
.facts { display: grid; grid-template-columns: subgrid; padding-top: 48px; }
.facts > div { grid-column: span 5; }
.facts > div:nth-child(2) { grid-column: 7 / 12; }          /* Previously starts on the right column of the wall */
.filters { display: grid; grid-template-columns: subgrid; padding-top: 64px; align-items: baseline; }
.filters .fl { grid-column: 1 / 10; display: flex; flex-wrap: wrap; gap: 4px 16px; }   /* 16 (was 20) since Motion: five filters fit one line down to 1200 */
.filters .fl button { color: var(--mute); } .filters .fl button.on, .filters .fl button:hover { color: var(--ink); }
.filters .count { grid-column: 10 / 13; justify-self: end; }
.wall { display: grid; grid-template-columns: subgrid; padding-top: 24px; gap: 0 var(--g); }
.wall .col { grid-column: span 6; }
.foot { display: grid; grid-template-columns: subgrid; align-items: baseline; }
.foot > :nth-child(1) { grid-column: 1 / 4; } .foot > :nth-child(2) { grid-column: 7 / 10; } .foot > :nth-child(3) { grid-column: 10 / 13; justify-self: end; }
/* project page */
.ptitle { display: grid; grid-template-columns: subgrid; padding-top: 56px; }
.ptitle .title { grid-column: 1 / 10; }
.pfacts { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; max-width: none; row-gap: 20px; }
.pfacts > div { grid-column: span 3; }
.sec { display: grid; grid-template-columns: subgrid; align-content: start; }
.sec > * { grid-column: 1 / -1; }
.sec > .lead-body, .sec > .impact { grid-column: 1 / 9; max-width: none; }
.two, .next-two { display: grid; grid-template-columns: subgrid; gap: 20px var(--g); }
.two > *, .next-two > * { grid-column: span 6; }
/* About: period on 1–3, role on 4–12 (Responsibilities 4–8, Impact 9–12); clients on the same three lines */
.about-p { grid-column: 1 / 8 !important; margin-top: 24px; max-width: none; }
.book { grid-column: 1 / 4 !important; display: flex; flex-direction: column; gap: 8px; margin-top: 40px; }
.tl { display: grid; grid-template-columns: subgrid; row-gap: 48px; }
.tl .row { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; gap: 0 var(--g); }
.tl .row > .when { grid-column: 1 / 4; }
.tl .row > div { grid-column: 4 / 13; display: grid; grid-template-columns: subgrid; }
.tl .row > div > * { grid-column: 1 / -1; }
.tl .detail { display: grid; grid-template-columns: subgrid; margin-top: 16px; gap: 0 var(--g); }
.tl .detail > :nth-child(1) { grid-column: 1 / 6; } .tl .detail > :nth-child(2) { grid-column: 6 / 10; }
.clients { display: grid; grid-template-columns: subgrid; columns: auto; }
.clients .cl:nth-child(1) { grid-column: 1 / 4; } .clients .cl:nth-child(2) { grid-column: 4 / 6; } .clients .cl:nth-child(3) { grid-column: 6 / 9; }   /* Hugo, Nov 10: the third column two columns after the second (page cols 4, 7, 9) */
@media (min-width: 810px) and (max-width: 1023.98px) { .clients .cl:nth-child(1) { grid-column: 1 / 5; } .clients .cl:nth-child(2) { grid-column: 5 / 8; } .clients .cl:nth-child(3) { grid-column: 8 / 11; } }   /* small tablets: two columns are too narrow for a name */
/* fixed layer: the same 16 columns, so the button fills columns 15–16 and the rails sit on column 1 */
.fixed-grid { position: fixed; left: 0; right: 0; bottom: var(--my); z-index: 70; display: grid; grid-template-columns: repeat(16, minmax(0, 1fr)); column-gap: var(--g); padding: 0 var(--mx); pointer-events: none; }
.cta-fixed { position: static; grid-column: 14 / 17; min-width: 0; pointer-events: auto; padding: 16px 14px; font-size: 16px; white-space: nowrap; }   /* taller, so it's noticed (Hugo); three columns so the label never wraps at 1200–1600 */
.foot, .endrow { padding-bottom: 96px; }
@media (max-width: 1199.98px) {
  .home main, .shell main { grid-column: 5 / span 12; }
  /* tablets (810–1199): the content runs to the right edge, so the button sits bottom left in the rail's empty columns 1–4,
     under the menu / section index, and never covers the page (Hugo, Nov 11: "Yes, move it"). Phones: the rule below. */
  .cta-fixed { grid-column: 1 / 5; }
}
@media (max-width: 809.98px) {
  .home main, .shell main { display: block; }
  .facts, .filters, .wall, .foot, .ptitle, .sec, .tl, .tl .row, .tl .row > div, .tl .detail, .clients { display: block; }
  .facts > div { margin-top: 20px; } .facts { padding-top: 12px; }
  .filters { padding-top: 48px; } .filters .count { display: none; }
  /* phone footer on the same two columns as the facts, clients and the button: socials across, then © | Say hello */
  .foot { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--g); row-gap: 20px; }
  .foot > * { margin-top: 0; }
  .foot > :nth-child(2) { grid-column: 1 / -1; grid-row: 1; }
  .foot > :nth-child(1) { grid-column: 1; grid-row: 2; }
  .foot > :nth-child(3) { grid-column: 2; grid-row: 2; justify-self: start; }
  .pfacts { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--g); } .pfacts > div { grid-column: auto; }
  .two, .next-two { display: grid; grid-template-columns: 1fr; } .two > *, .next-two > * { grid-column: auto; }
  /* phone timeline (Hugo, Nov 10: spacing off on role titles and times): date on its own line 8px over the title, title
     and company 4px apart, 24px before Responsibilities and Impact, 48px between roles (date and title were inline, so
     their lines touched and the title could not balance) */
  .tl .row { margin-top: 48px; } .tl .row:first-child { margin-top: 40px; }
  .tl .when { display: block; margin-bottom: 8px; }
  .tl .heading { display: block; }
  .tl .detail > * { margin-top: 24px; }
  .clients { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--g); row-gap: 8px; } .clients .cl:nth-child(n) { grid-column: auto; }
  /* a name that wraps (Solana Foundation) stays tight; 8px between names so it doesn't read as two clients */
  .clients .heading + .heading { margin-top: 8px; }
  .fixed-grid { grid-template-columns: 1fr 1fr; } .cta-fixed { grid-column: 2; }
  .sec > .lead-body, .sec > .impact, .about-p, .book { max-width: none; }
}

/* Typography rule (Hugo): no line ends with one or two words. build.py ties the last words with no-break spaces;
   headings are balanced and running text wraps "pretty" on top of that. */
body { text-wrap: pretty; }
.tail { white-space: nowrap; } .tail.loose { white-space: normal; }
h1, h2, h3, .statement, .title, .lead, .tl h3 { text-wrap: balance; }
/* small tablets (810–1023): three grid columns are too narrow for a fact or an Impact line to end on three words,
   so facts take six columns (two per row) and Responsibilities sits above Impact across the role's columns */
@media (min-width: 810px) and (max-width: 1023.98px) {
  .pfacts > div { grid-column: span 6; }
}
/* About timeline, all tablets (810–1199): Responsibilities above Impact. Side by side at 1024–1199 Impact was 229 px wide
   (about 30 characters a line) and left "highest-revenue" alone on a line (Nov 11 test); from 1200 up it's stacked too. */
@media (min-width: 810px) and (max-width: 1199.98px) {
  .tl .detail > :nth-child(1), .tl .detail > :nth-child(2) { grid-column: 1 / -1; }
  .tl .detail > :nth-child(2) { margin-top: 16px; }
}

/* Home: the 3D H + ring film (the old Framer hero) beside the main line, on columns 13–16, centred on the statement.
   The film is black, so it's screened onto the dark page and inverted + multiplied onto the white one, and a radial mask
   fades its edge into the page colour. The ring is 44% of the film's width, so the film is 2.28× the four columns. */
.home .grid { overflow-x: clip; }
.home .statement { grid-row: 1; position: relative; z-index: 1; }
.hring { grid-row: 1; grid-column: 10 / 13 !important; position: relative; pointer-events: none; }
.hring video { position: absolute; top: 50%; left: calc(66.667% + var(--g) / 6); width: calc(2.28 * (133.333% + var(--g) / 3)); aspect-ratio: 16 / 9; transform: translate(-50%, -50%); object-fit: cover; mix-blend-mode: screen; -webkit-mask: radial-gradient(closest-side, #000 84%, transparent 100%); mask: radial-gradient(closest-side, #000 84%, transparent 100%); opacity: 0; transition: opacity 900ms; }
.hring video.on { opacity: 1; }
:root[data-theme="light"] .hring video { filter: invert(1); mix-blend-mode: multiply; }
@media (max-width: 1199.98px) { .hring video { left: 50%; width: calc(2.28 * 100%); } }   /* the ring = its three columns (Nov 11 test: at 120% it ran into the page margin at 1024–1199 and met the main line at 1199) */
@media (max-width: 809.98px) {
  .hring { display: block; height: 64vw; margin: -16px 0 8px; }
  .hring video { width: auto; height: 100%; }
}

/* Case study pages (Breeze, Nov 10): question headings, figures, numbers, "Why it works" rows — all on the 12-column
   content subgrid, open (no boxes): label left on columns 1–3, the sentence on 4–9, like the About timeline. */
.big { font-size: clamp(40px, 4vw, 64px); line-height: 1; font-weight: 500; letter-spacing: -0.02em; }
.body { font-size: 16px; line-height: 1.45; }
.sec.case > .q { grid-column: 1 / 10; font-size: clamp(24px, 2vw, 34px); line-height: 1.12; letter-spacing: -0.01em; font-weight: 500; margin-bottom: 16px; }
.sec > .lead-body + .lead-body { margin-top: 12px; }   /* case pages, and Briefs with a blank line (DiversiFi) */
.sec.case > .subhead { margin-top: 72px; margin-bottom: 16px; }
.fig { grid-column: 1 / -1; margin-top: 40px; }
.fig img { width: 100%; height: auto; background: var(--surface); }
.fig.tight { margin-top: 0; }
.fig figcaption { margin-top: 12px; max-width: 56ch; }
.stats { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: 32px; margin-top: 48px; }
.stats > div { grid-column: span 3; display: flex; flex-direction: column; gap: 10px; }
.why { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: 20px; margin-top: 56px; }
.why > .label { grid-column: 1 / -1; }
.why .wrow { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: baseline; }
.why .wrow > .label { grid-column: 1 / 4; } .why .wrow > p { grid-column: 4 / 10; }
.cols3 { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: 32px; margin-top: 40px; }
.cols3 > div { grid-column: span 4; display: flex; flex-direction: column; gap: 10px; }
.cols3 .meta { margin-top: 4px; }
.ladder { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: 16px; margin-top: 40px; }
.ladder li { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: baseline; }
.ladder li > :nth-child(1) { grid-column: 1 / 2; } .ladder li > :nth-child(2) { grid-column: 2 / 7; } .ladder li > :nth-child(3) { grid-column: 7 / 13; }
.taglist { grid-column: 1 / 9; columns: 2; column-gap: var(--g); margin-top: 40px; } .taglist li { padding: 3px 0; }
.capline { grid-column: 1 / 9; margin-top: 12px; }
.phones { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: 20px; margin-top: 40px; }
.phones img { grid-column: span 3; width: 100%; height: auto; background: var(--surface); }
.caselink { grid-column: 1 / -1; display: flex; align-items: center; gap: 16px; margin-top: 48px; }
.note { grid-column: 1 / 9; margin-top: 24px; }
.refs { grid-column: 1 / 10; display: flex; flex-direction: column; gap: 8px; }
.sec.case [data-pages], .pages-title { margin-top: 40px; }
.pages-title + [data-pages] { margin-top: 12px; }
@media (min-width: 810px) and (max-width: 1023.98px) {
  .stats > div { grid-column: span 6; } .why .wrow > p { grid-column: 4 / 13; }
  .cols3 > div { grid-column: 1 / -1; } .ladder li > :nth-child(2) { grid-column: 2 / 8; } .ladder li > :nth-child(3) { grid-column: 8 / 13; }
}
@media (max-width: 809.98px) {
  .stats, .cols3, .phones { display: grid; grid-template-columns: 1fr 1fr; column-gap: var(--g); }
  .stats > div, .phones img { grid-column: auto; } .cols3 { grid-template-columns: 1fr; } .cols3 > div { grid-column: auto; }
  .why, .why .wrow, .ladder, .ladder li { display: block; }
  .why .wrow { margin-top: 20px; } .why .wrow > p { margin-top: 6px; }
  .ladder li { margin-top: 16px; } .ladder li > * { display: block; margin-top: 4px; }
  .taglist { columns: 1; } .sec.case > .subhead { margin-top: 48px; }
}
.caselink .btn { white-space: nowrap; }
@media (max-width: 809.98px) { .caselink { flex-direction: column; align-items: flex-start; gap: 10px; } }

/* Figma case page (Breeze, Nov 10, Hugo: "keep the project page just as it is in the Figma"): the exported page on a white
   sheet. The Figma 960 column sits exactly on content columns 1–12; the sheet's 38 px (Figma) white margins reach into the
   gutters, so text lines up with the grid and the sheet still breathes in dark mode. Light tokens inside the sheet keep the
   inserted presenter readable in both themes. Phones get the same content as HTML (.case-phone): slices would be too small. */
.fsheet { grid-column: 1 / -1; width: calc(100% * 1036 / 960); margin-left: calc(-100% * 38 / 960); background: #fff; container-type: inline-size;
  --ink: #0D0347; --paper: #FFFFFF; --mute: #666F97; --value: #4A5281; --surface: #F2F3F7; color: var(--ink); }
.fslice { display: block; scroll-margin-top: 24px; }
.fslice > img { display: block; width: 100%; height: auto; }
.fvid { padding: 0 calc(100% * 38 / 1036); }
.fvid video, .vidfig video { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; background: var(--surface); }
.fvidin { margin: 0; }
.finsert .fcol { margin: 0 calc(100cqw * 38 / 1036); padding: calc(100cqw * 52 / 1036) 0 calc(100cqw * 44 / 1036); }
.f-label { display: block; font-size: calc(100cqw * 14 / 1036); line-height: 1.43; color: #666F97; margin-bottom: calc(100cqw * 24 / 1036); }
.finsert .fstack { display: flex; flex-direction: column; gap: calc(100cqw * 24 / 1036); }
.finsert .fstack > img { display: block; width: 100%; height: auto; background: #F2F3F7; }
.finsert .pages-bar .tabs button, .finsert .pages-bar .ctl { color: var(--ink); }
.case-phone { display: none; }
@media (max-width: 809.98px) { .fsheet { display: none; } .case-phone { display: block; } .case-phone .ptitle { padding-top: 40px; } }
.shell .grid { overflow-x: clip; }   /* tablets: the sheet's right white margin can reach past the page edge */
.sec.case > .subhead { display: block; }

/* Breeze brand system, rebuilt on the grid: six swatches on two columns each, the type specimen on 1–4 | 5–12,
   the isometric icons spread edge to edge across the twelve columns. Open, no panels. */
.swatches { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: 24px; margin-top: 48px; }
.sw { grid-column: span 2; display: flex; flex-direction: column; gap: 4px; }
.sw i { display: block; aspect-ratio: 1; margin-bottom: 10px; }
:root[data-theme="light"] .sw i.light { box-shadow: inset 0 0 0 1px #d9d9d9; }
.change { grid-column: 1 / 10; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin-top: 24px; }
.change > span:not(.meta) { display: inline-flex; align-items: center; gap: 10px; }
.change i { width: 20px; height: 20px; display: inline-block; }
.typespec { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; align-items: start; margin-top: 56px; }
.typespec .aa { grid-column: 1 / 5; font-size: clamp(120px, 12.5vw, 220px); line-height: .82; font-weight: 500; letter-spacing: -0.04em; }
.typespec .ts { grid-column: 5 / 13; display: flex; flex-direction: column; gap: 14px; }
.ts-h { font-size: clamp(28px, 2.8vw, 44px); line-height: 1.05; font-weight: 500; letter-spacing: -0.02em; text-wrap: balance; }
.ts-code { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 20px; margin-top: 4px; }
.ts-code code { font-family: Inconsolata, ui-monospace, Menlo, monospace; font-weight: 500; font-size: 16px; }
.isorow { grid-column: 1 / -1; display: flex; justify-content: space-between; align-items: end; margin-top: 56px; }
.isorow img { width: clamp(48px, 6.2vw, 96px); height: auto; }
@media (max-width: 809.98px) {
  .swatches { display: grid; grid-template-columns: repeat(3, 1fr); column-gap: var(--g); } .sw { grid-column: auto; }
  .typespec { display: block; } .typespec .aa { display: block; margin-bottom: 20px; }
  .isorow { flex-wrap: wrap; gap: 12px; justify-content: flex-start; } .isorow img { width: 64px; }
}

/* "Why it works / hurts" (Hugo, Nov 10: "barely readable"): each principle is a small block, number, principle as the
   heading, the sentence, its source underneath; two blocks a row for 2 or 4, three for 3, 5, 6. Open, on the subgrid. */
.why { row-gap: 44px; margin-top: 72px; }
.why .why-t { grid-column: 1 / -1; margin-bottom: -16px; }
.why .wrow { grid-column: span 6; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.why.n3 .wrow, .why.n5 .wrow, .why.n6 .wrow { grid-column: span 4; }
.why .wrow > .wk { font-size: clamp(20px, 1.6vw, 26px); line-height: 1.15; font-weight: 500; letter-spacing: -0.01em; color: var(--ink); }
.why .wrow > p { max-width: 62ch; }
.why .wrow > .wn { margin-bottom: 4px; }
.why .wrow > .wsrc { margin-top: 2px; }
@media (min-width: 810px) and (max-width: 1023.98px) { .why .wrow, .why.n3 .wrow, .why.n5 .wrow, .why.n6 .wrow { grid-column: span 6; } }
@media (max-width: 809.98px) { .why .wrow { display: flex; margin-top: 32px; } .why .why-t { margin-bottom: 0; } }
/* Mobile cards (Hugo's reference): two a row on the subgrid, the phone render on its gradient, title + one line under it */
.phonecards { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: 48px; margin-top: 40px; }
.pcard { grid-column: span 6; margin: 0; }
.pcard img { display: block; width: 100%; height: auto; background: var(--surface); }
.pcard figcaption { display: flex; flex-direction: column; gap: 6px; margin-top: 16px; max-width: 46ch; }
.vidfig video[style] { aspect-ratio: auto; }
@media (max-width: 809.98px) { .phonecards { display: grid; grid-template-columns: 1fr; row-gap: 36px; } .pcard { grid-column: auto; } }

/* two films side by side in a case study (Carrot motion): each takes 6 columns, one a row on phones */
.two.vgrid { grid-column: 1 / -1; margin-top: 40px; }
.two.vgrid > .fig { grid-column: span 6; margin-top: 0; }
@media (max-width: 809.98px) { .two.vgrid > .fig { grid-column: auto; } .two.vgrid { row-gap: 20px; } }

/* condensed blocks (Hugo, Nov 10: "instead of 3 we have either 2 or 1"): two columns span 6 each, one stays 6 wide */
.cols3.n2 > div { grid-column: span 6; }
.cols3.n1 > div { grid-column: span 6; }
@media (max-width: 1199.98px) { .cols3.n2 > div { grid-column: span 6; } }
@media (max-width: 809.98px) { .cols3.n2 > div, .cols3.n1 > div { grid-column: auto; } }

/* ===================== Nov 10 (night): project pages after rachelchen.tech/projects/openai (Hugo) =====================
   "shorten the width of the project pages … text sizes replicating this one … the scrolling is very big".
   Desktop (1200+): the page sits on columns 4–13 (ten columns). The cover and the grids (brand bento, image grid, class
   .wide) use all ten; text, figures, films and the page presenter use the middle eight (columns 5–12: 668 px at 1440,
   Rachel's column is 688). Tablets (12 columns, ~700 px) and phones keep their layout. Type steps down to her scale;
   body stays 16 px (Hugo's usability rule; hers is 15). */
@media (min-width: 1200px) {
  .proj main { grid-column: 4 / span 10; grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .proj main > * { grid-column: 2 / 10; }
  .proj main > .hero { grid-column: 1 / -1; }
  .proj .sec > .wide { margin-inline: calc((100% + var(--g)) / -8); }   /* one column + gutter out on each side */
  .proj .sec.case > .q, .proj .ptitle .title, .proj .refs, .proj .change { grid-column: 1 / -1; }
  .proj .phones img { grid-column: span 2; }
  .proj .stats > div { grid-column: span 4; }   /* two a row: every label fits its line */
  .proj .pfacts > div { grid-column: span 4; }   /* two a row: long roles and credits read in two lines, not four */
  .proj .why .wrow, .proj .why.n3 .wrow, .proj .why.n5 .wrow, .proj .why.n6 .wrow, .proj .cols3 > div, .proj .cols3.n2 > div,
  .proj .pcard, .proj .two > *, .proj .next-two > *, .proj .two.vgrid > .fig { grid-column: span 4; }
  .proj .why.n1 .wrow, .proj .cols3.n1 > div { grid-column: span 6; }
  .proj .ladder li > :nth-child(2) { grid-column: 2 / 5; } .proj .ladder li > :nth-child(3) { grid-column: 5 / 9; }
  .proj .foot > :nth-child(1) { grid-column: 1 / 4; } .proj .foot > :nth-child(2) { grid-column: 4 / 7; } .proj .foot > :nth-child(3) { grid-column: 7 / 9; }
}
.proj .title { font-size: clamp(26px, 2.5vw, 36px); }
.proj .lead-body { font-size: 16px; line-height: 1.5; }
.proj .body { line-height: 1.5; }
.proj .sec.case > .q { font-size: clamp(22px, 1.95vw, 28px); line-height: 1.2; margin-bottom: 12px; }
.proj .why .wrow > .wk, .proj .cols3 .heading { font-size: 18px; line-height: 1.3; }
.proj .big { font-size: clamp(32px, 2.8vw, 40px); }
.proj .sec { padding-top: 80px; }
.proj .ptitle { padding-top: 40px; }
.proj .fig, .proj .stats, .proj .cols3, .proj .phonecards, .proj .two.vgrid, .proj .caselink, .proj .sec.case [data-pages], .proj .pages-title { margin-top: 32px; }
.proj .fig.tight { margin-top: 0; }
.proj .pages-title + [data-pages] { margin-top: 12px; }
.proj .why { margin-top: 48px; row-gap: 32px; }
.proj .why .why-t { margin-bottom: -8px; }
.proj .sec.case > .subhead { margin-top: 56px; }
.proj .phonecards { row-gap: 32px; }
@media (max-width: 809.98px) { .proj .sec { padding-top: 56px; } .proj .why .why-t { margin-bottom: 0; } }

/* Brand system bento (Hugo, Nov 10: "a bento or a grid with different sections"): boxed tiles on the page columns with
   the page gutter between them. Each tile is a visual and a caption bar (a filled tag, then the line). Images and films
   run to the tile's edges; type and icons sit 16 px in on top and sides, the caption 16 px in, so every inset is equal. */
.bento { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; row-gap: var(--g); margin-top: 32px; }
.bt { margin: 0; min-width: 0; grid-row: span 2; display: grid; grid-template-rows: subgrid; row-gap: 0; background: var(--surface); }   /* visual + caption rows shared across a bento row, so tags line up */
.bt.s4 { grid-column: span 5; } .bt.s5 { grid-column: span 6; } .bt.s6 { grid-column: span 7; } .bt.s10 { grid-column: span 12; }   /* tablet: 12 columns */
.bv { position: relative; display: flex; flex-direction: column; min-width: 0; }
.bt.tm .bv img, .bt.tm .bv video { display: block; width: 100%; height: auto; background: var(--surface); }
.bt.tm .bv video { aspect-ratio: 16 / 9; object-fit: cover; }
.bt.tp .bv { padding: 16px 16px 0; }
.bc { padding: 16px; display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.btag { padding: 3px 6px 4px; background: var(--ink); color: var(--paper); font-size: 13px; line-height: 1.2; font-weight: 500; }
.bc .value { font-size: 14px; line-height: 1.45; max-width: 64ch; }
/* colour: a mosaic two blocks across, name and value on the colour */
.bsw { flex: 1; display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: minmax(88px, 1fr); }
.bsw > div { padding: 16px; display: flex; flex-direction: column; justify-content: flex-end; gap: 2px; }
.bsw .bhex { font-size: 13px; line-height: 1.2; }
.bsw.b2 { grid-auto-rows: minmax(176px, 1fr); }
/* type: the specimen inside the tile */
.btype { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.btype .aa { font-size: 88px; line-height: .8; font-weight: 500; letter-spacing: -0.03em; margin: 4px 0 16px; }
.btype .ts-h { font-size: 24px; line-height: 1.1; letter-spacing: -0.01em; }
.btype .ts-h4 { font-size: 18px; line-height: 1.2; font-weight: 500; }
.btype code { font-family: Inconsolata, ui-monospace, Menlo, monospace; font-weight: 500; font-size: 16px; margin-top: 4px; }
/* icons: four a row, never under 64 px (the system's own rule: below that the flat icon takes over) */
.bicons { display: grid; grid-template-columns: repeat(4, 80px); justify-content: space-between; row-gap: 16px; }
.bicons img { display: block; width: 80px; height: 80px; }
/* image grid for galleries: one across, then two pairs (16:9, so nothing is cropped) */
.gal { grid-column: 1 / -1; display: grid; grid-template-columns: subgrid; gap: var(--g); }
.gal .shot { grid-column: 1 / -1; } .gal .shot.h { grid-column: span 6; }
@media (min-width: 1200px) {
  .proj .bento, .proj .gal { grid-template-columns: repeat(10, minmax(0, 1fr)); column-gap: var(--g); }
  .bt.s4 { grid-column: span 4; } .bt.s5 { grid-column: span 5; } .bt.s6 { grid-column: span 6; } .bt.s10 { grid-column: span 10; }
  .gal .shot.h { grid-column: span 5; }
}
@media (max-width: 809.98px) {
  .bento, .gal { display: grid; grid-template-columns: 1fr; row-gap: 16px; }
  .bt.s4, .bt.s5, .bt.s6, .bt.s10, .gal .shot, .gal .shot.h { grid-column: auto; }
  .bicons { grid-template-columns: repeat(4, 64px); } .bicons img { width: 64px; height: 64px; }
  .btype .aa { font-size: 72px; }
}

/* checker pass (Nov 10, night): labels that wrap get balanced lines; stats and facts get room so short phrases don't wrap */
.pfacts .value, .stats .value, .bc .value, .pcard figcaption .value, .fig figcaption, .ladder a, .capline { text-wrap: balance; }
.proj .taglist { grid-column: 1 / -1; }
@media (min-width: 810px) and (max-width: 1199.98px) { .proj .stats > div, .proj .pfacts > div { grid-column: span 6; } }
@media (min-width: 810px) and (max-width: 1023.98px) {
  .foot > :nth-child(1) { grid-column: 1 / 5; }
  .bt.s4, .bt.s6, .bt.s10 { grid-column: 1 / -1; } .bt.s5 { grid-column: span 6; }
}
@media (max-width: 809.98px) { .proj .stats, .proj .pfacts { grid-template-columns: 1fr; } }

/* About: the Start a project button matches the fixed one bottom right (Hugo, Nov 10): 16 / 14 padding, 16 px, one line.
   Tablets give it a column more so the label never wraps. */
.book .btn { padding: 16px 14px; font-size: 16px; white-space: nowrap; }
@media (min-width: 1024px) and (max-width: 1199.98px) { .book { grid-column: 1 / 5 !important; } }
@media (min-width: 810px) and (max-width: 1023.98px) { .book { grid-column: 1 / 6 !important; } }

/* Click to enlarge (Hugo, Nov 10): a full-screen viewer over the page in the page colour; the bar on the page margins,
   the picture as large as the screen allows, the caption under it. */
[data-zoomable] { cursor: zoom-in; }
[data-zoomable]:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.lb { position: fixed; inset: 0; z-index: 100; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; row-gap: 16px; padding: var(--my) var(--mx); background: var(--paper); opacity: 0; transition: opacity 200ms; }
.lb.on { opacity: 1; }
.lb[hidden] { display: none; }
.lb-bar { display: flex; justify-content: space-between; align-items: baseline; gap: 20px; }
.lb-ctl { display: flex; gap: 20px; }
.lb-ctl button { color: var(--mute); } .lb-ctl button:hover, .lb-ctl button:focus-visible { color: var(--ink); }
.lb-stage { min-height: 0; display: flex; align-items: center; justify-content: center; }
.lb-media { display: block; object-fit: contain; opacity: .01; transition: opacity 360ms; }
.lb-media.pic { filter: blur(12px); transition: opacity 360ms, filter 360ms; }
.lb-media.in { opacity: 1; filter: none; }
.lb-cap { min-height: 1.2em; max-width: 72ch; text-wrap: balance; }
:root.lb-open { overflow: hidden; }
:root.lb-open .fixed-grid, :root.lb-open .theme-fixed, :root.lb-open .view-tag { visibility: hidden; }
@media (prefers-reduced-motion: reduce) { .lb, .lb-media { transition: none; } }
/* bento colour as stripes, one colour a row, name left and value right (Prism's colour board) */
.bsw.rows { grid-template-columns: 1fr; grid-auto-rows: minmax(36px, 1fr); }
.bsw.rows > div { flex-direction: row; justify-content: space-between; align-items: center; padding: 0 16px; }

/* Image strip (Prism applications, Hugo Nov 11: "simply images to scroll through"): one image at a time, the next one
   peeking in. Desktop: images 8 of the strip's 10 columns, the page gutter between them; tablet 10 of 12; phone 85%. */
.scroller { grid-column: 1 / -1; margin-top: 32px; min-width: 0; }
.sc-bar { display: flex; justify-content: space-between; align-items: baseline; gap: 20px; padding-bottom: 12px; }
.sc-ctl { display: flex; gap: 20px; }
.sc-ctl button { color: var(--ink); } .sc-ctl button:disabled { color: var(--mute); cursor: default; }
.sc-track { display: flex; gap: var(--g); overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; overscroll-behavior-x: contain; }
.sc-track::-webkit-scrollbar { display: none; }
.sc-slide { margin: 0; flex: 0 0 calc((100% - 11 * var(--g)) / 12 * 10 + 9 * var(--g)); scroll-snap-align: start; }
.sc-slide img { display: block; width: 100%; height: auto; background: var(--surface); }
@media (min-width: 1200px) { .proj .scroller .sc-slide { flex-basis: calc((100% - 9 * var(--g)) / 10 * 8 + 7 * var(--g)); } }
@media (max-width: 809.98px) { .sc-slide { flex-basis: 85%; } }

/* Presentation to scroll through (Prism, Hugo Nov 11, like the live hugosantos.co/work/prism): each board full width on
   the ten columns, one after another, the page gutter between them; one column of boards on tablets and phones. */
.pres { grid-column: 1 / -1; display: flex; flex-direction: column; gap: var(--g); margin-top: 32px; }
.pres .pz { margin: 0; }
.pres img, .pres video { display: block; width: 100%; height: auto; background: var(--surface); }
.pres video { object-fit: cover; }

/* Films with sound (Pilled at Breakpoint 2025): the browser's own player, 16:9, black behind the picture */
.film video { display: block; width: 100%; aspect-ratio: 16 / 9; background: #000; object-fit: contain; }

/* Home and About on the project pages' frame (Hugo, Nov 11: "match the grid that runs inside each project presentation,
   so a bit more centered", and Start a project "on its own column so it doesn't overlap with projects"): from 1200 up
   the content sits on page columns 4–13 (ten columns), the rail keeps 1–3 and the fixed button keeps 14–16. */
@media (min-width: 1200px) {
  .home main, .shell:not(.proj) main { grid-column: 4 / span 10; grid-template-columns: repeat(10, minmax(0, 1fr)); }
  /* Home: the statement on 4–10, the H ring on 11–13 (ring = the box's width: the film is 2.28x it) */
  .statement { grid-column: 1 / 8 !important; }
  .shell:not(.proj) .statement { grid-column: 1 / 10 !important; }   /* About has no ring beside it */
  .hring { grid-column: 8 / 11 !important; }
  .hring video { left: 50%; width: calc(2.28 * 100%); }
  .facts > div { grid-column: span 4; } .facts > div:nth-child(2) { grid-column: 6 / 10; }   /* Previously on the wall's right column */
  .filters .fl { grid-column: 1 / 8; } .filters .count { grid-column: 8 / 11; }
  .wall .col { grid-column: span 5; }
  .home .foot > :nth-child(2), .shell:not(.proj) .foot > :nth-child(2) { grid-column: 6 / 9; }
  .home .foot > :nth-child(3), .shell:not(.proj) .foot > :nth-child(3) { grid-column: 9 / 11; }
  /* About: role from page column 7 (the clients' second column), Responsibilities 4 columns, Impact 3 */
  .tl .row > div { grid-column: 4 / 11; }
  .tl .detail > :nth-child(1), .tl .detail > :nth-child(2) { grid-column: 1 / -1; } .tl .detail > :nth-child(2) { margin-top: 16px; }   /* Impact under Responsibilities: side by side they'd be 4 + 3 columns, too narrow */
}

/* One rhythm for running text (Hugo, Nov 11: the gap between two paragraphs read as a different line spacing): consecutive
   paragraphs on project pages follow on the same 24 px line pitch; each still starts on a new line. */
.proj .sec.case > .lead-body + .lead-body { margin-top: 0; }

/* ===================== Nov 11: one max width across the site (Hugo: "make sure that across the website the max width is
   always the one presented on this screenshot", the Pilled text and film column). From 1200 up nothing is wider than the
   8-column text column, page columns 5–12: the project cover, the brand bentos, galleries and presentations, and on Home and
   About every block. Tablets and phones keep their layout. ===================== */
@media (min-width: 1200px) {
  /* project pages: cover and grids back inside the column */
  .proj main > .hero { grid-column: 2 / 10; }
  .proj .sec > .wide { margin-inline: 0; }
  .proj .bento, .proj .gal { grid-template-columns: subgrid; }
  .bt.s4 { grid-column: span 3; } .bt.s5 { grid-column: span 4; } .bt.s6 { grid-column: span 5; } .bt.s10 { grid-column: span 8; }
  .gal .shot.h { grid-column: span 4; }
  .proj .scroller .sc-slide { flex-basis: calc((100% - 7 * var(--g)) / 8 * 7 + 6 * var(--g)); }
  /* Home and About: the same column inside the 4–13 frame */
  .home main > *, .shell:not(.proj) main > * { grid-column: 2 / 10; }
  .statement, .shell:not(.proj) .statement { grid-column: 2 / 10 !important; }
  .hring { grid-column: 10 / 11 !important; }   /* the ring beside the column, over page columns 13–15 */
  .hring video { left: calc(150% + var(--g)); width: calc(2.28 * (300% + 2 * var(--g))); }
  .facts > div { grid-column: span 4; } .facts > div:nth-child(2) { grid-column: 5 / 9; }   /* Previously on the wall's right column */
  .filters .fl { grid-column: 1 / 6; } .filters .count { grid-column: 6 / 9; }
  .wall .col { grid-column: span 4; }
  .home .foot > :nth-child(1), .shell:not(.proj) .foot > :nth-child(1) { grid-column: 1 / 4; }
  .home .foot > :nth-child(2), .shell:not(.proj) .foot > :nth-child(2) { grid-column: 5 / 7; }
  .home .foot > :nth-child(3), .shell:not(.proj) .foot > :nth-child(3) { grid-column: 7 / 9; }
  .about-p { grid-column: 2 / 8 !important; }
  .book { grid-column: 2 / 5 !important; }
  /* About: role on the clients' second column (page 8), clients keep Hugo's spacing (3 apart, then 2) from page column 5 */
  .tl .row > .when { grid-column: 1 / 4; } .tl .row > div { grid-column: 4 / 9; }
}
@media (min-width: 810px) {
  /* Home filters: one row, filters from the first column, count on the last; a filter name never breaks. Flex rather than
     columns since Nov 12: with Motion added (5 filters) the 1200 and 810 grid spans pushed "Commercials & Films" to a 2nd line */
  .home .filters { display: flex; justify-content: space-between; align-items: baseline; gap: 20px; }
  .filters .fl button { white-space: nowrap; } .filters .count { white-space: nowrap; }
}
@media (min-width: 1200px) {
  /* bentos on 8 columns: two-up rows are equal halves (a 3-column colour tile wrapped its names); 4 icons at 64 px;
     colour rows a little shorter so a colour tile stays level with a 16:9 film beside it */
  .bt.s4, .bt.s5, .bt.s6 { grid-column: span 4; } .bt.s10 { grid-column: span 8; }
  .bsw { grid-auto-rows: minmax(56px, 1fr); } .bsw.b2 { grid-auto-rows: minmax(120px, 1fr); }
  .bicons { grid-template-columns: repeat(4, 64px); } .bicons img { width: 64px; height: 64px; }
}

/* Touch screens (Nov 11 usability test): the text links and buttons are 17 px tall (14 px type), under the 24 px minimum
   target (WCAG 2.2, 2.5.8). On touch screens only, an invisible ::before grows each one 5 px up and down and 8 px to each
   side (27 px tall); nothing moves and mouse screens don't change. Stacked links and rows that wrap get 10 px between lines
   (8 px on mouse screens) so the grown areas don't overlap. */
@media (hover: none) and (pointer: coarse) {
  .ptop button, .filters .fl button, .foot a, .rail > a, .rail nav a, .crumb a, .toc a, .pfacts .value a, .pages-bar button, .sc-ctl button { position: relative; }
  :is(.ptop button, .filters .fl button, .foot a, .rail > a, .rail nav a, .crumb a, .toc a, .pfacts .value a, .pages-bar button, .sc-ctl button, .theme-fixed)::before { content: ""; position: absolute; inset: -5px -8px; }
  .filters .fl, .pages-bar .tabs { row-gap: 10px; } .toc, .rail nav { gap: 10px; }
}

/* Before / after wipe (Carrot logo, Hugo Nov 11: "an animation with the bar going from left to right and showing before
   and after of the logo"). One 16:9 stage, the two pictures stacked; the After picture is clipped from the left and a deep
   green bar rides its edge. 6 s loop: before 0.9 s, sweep 2.1 s, after 2 s, then the After picture fades to the old
   ground colour (the stage's own background) and the old logo fades back in, 1 s (a straight crossfade double-exposed
   the two logos). It starts when the figure
   comes into view (.in), so the first thing seen is the old logo. Still state (reduced motion, Figma captures): half and
   half, After on the left, the bar in the middle. */
.wipe { grid-column: 1 / -1; margin: 40px 0 0; }
.wp-stage { position: relative; aspect-ratio: 16 / 9; overflow: hidden; background: var(--surface); }
.wp-l { position: absolute; inset: 0; }
.wp-l img { display: block; width: 100%; height: 100%; object-fit: cover; }
.wp-tag { position: absolute; top: 16px; padding: 3px 6px 4px; background: var(--ink); color: var(--paper); font-size: 13px; line-height: 1.2; font-weight: 500; }
.wp-b .wp-tag { right: 16px; } .wp-a .wp-tag { left: 16px; }
.wp-a { clip-path: inset(0 50% 0 0); }
.wp-bar { position: absolute; top: 0; bottom: 0; left: 50%; width: 3px; margin-left: -1.5px; background: #003322; }
.wipe figcaption { margin-top: 12px; max-width: 56ch; }
.wipe .wp-a { animation: wp-a 6s infinite paused; }
.wipe .wp-b { animation: wp-b 6s infinite paused; }
.wipe .wp-bar { animation: wp-bar 6s infinite paused, wp-bar-on 6s step-end infinite paused; }
.wipe.in .wp-a, .wipe.in .wp-b, .wipe.in .wp-bar { animation-play-state: running; }
@keyframes wp-a {
  0%, 15% { clip-path: inset(0 100% 0 0); opacity: 1; animation-timing-function: cubic-bezier(.65, 0, .35, 1); }
  50%, 83% { clip-path: inset(0 0 0 0); opacity: 1; animation-timing-function: ease-in; }
  90%, 100% { clip-path: inset(0 0 0 0); opacity: 0; }
}
@keyframes wp-b {   /* hidden while the After picture still covers it, so the fade shows no double exposure; then back in */
  0%, 82% { opacity: 1; animation-timing-function: step-end; }
  83%, 90% { opacity: 0; animation-timing-function: ease-out; }
  100% { opacity: 1; }
}
@keyframes wp-bar {
  0%, 15% { left: 0%; animation-timing-function: cubic-bezier(.65, 0, .35, 1); }
  50%, 100% { left: 100%; }
}
@keyframes wp-bar-on { 0% { opacity: 0; } 15% { opacity: 1; } 50%, 100% { opacity: 0; } }   /* the bar shows only while it moves */
@media (prefers-reduced-motion: reduce) { .wipe .wp-a, .wipe .wp-b, .wipe .wp-bar { animation: none; } }
@media (max-width: 809.98px) { .wp-tag { top: 10px; } .wp-b .wp-tag { right: 10px; } .wp-a .wp-tag { left: 10px; } .wp-bar { width: 2px; margin-left: -1px; } }
