/* Redesign 2026 — shared tokens, nav, footer. Used by pages rebuilt from portfolio-wireframes-2. */

:root{
  /* Darkened, same-hue versions of the brand colors, used wherever they sit as static text on --bg —
     checked against --bg for WCAG AAA (7:1). Full-brightness originals stay in the JS `palette` array
     for animated/decorative use (floating shapes, scramble glyphs), which isn't static text. */
  --teal:#135291; --coral:#863A21; --olive:#273C2C; --ochre:#4A39C1; --indigo:#880666;
  --teal-tint:#E7F2FC; --coral-tint:#FBE6DD; --olive-tint:#E1E6E2; --ochre-tint:#F0EEFA; --indigo-tint:#F3DFF0;
  --bg:#F4F4F2; --ink:#141413;
  /* One fluid vertical rhythm for all sections, instead of a fixed 96px repeated everywhere —
     shrinks gracefully down to phone widths instead of jumping at a breakpoint. */
  --space-section: clamp(48px, 9vw, 96px);
}

/* Scoped to the homepage only (body.home): any ancestor with overflow-x:hidden — even html itself —
   silently disables position:sticky for every descendant in WebKit/Safari. That's fine for the
   homepage (no sticky elements), but it was breaking the sticky TOC sidebar on other pages. */
body.home{overflow-x:hidden} /* safety net: decorative absolutely-positioned stickers must never force a horizontal scrollbar */
.redesign{font-family:'Host Grotesk',sans-serif;background:var(--bg);color:var(--ink);margin:0}
.redesign .hand{font-family:'Nothing You Could Do',cursive}
.redesign a{color:var(--ink)}
.redesign .c-teal{color:var(--teal)} .redesign .c-coral{color:var(--coral)} .redesign .c-olive{color:var(--olive)} .redesign .c-ochre{color:var(--ochre)} .redesign .c-indigo{color:var(--indigo)}
.redesign .ph{border:1.5px dashed #9A9A9A;background:#E7E7E3;display:flex;align-items:center;justify-content:center;text-align:center;font-family:'IBM Plex Mono',monospace;font-size:12px;color:#4A4A4A;padding:8px;box-sizing:border-box}

@media (prefers-reduced-motion: reduce){
  .redesign *{animation:none!important;transition:none!important}
}

/* Site chrome (nav, footer, shared tokens): deliberately NOT scoped under .redesign — this same
   nav/footer markup is dropped into old (not-yet-redesigned) pages too, whose <body> keeps its
   original Webflow classes so the rest of that page's look is untouched. */
.mono{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:#4A4A4A}
.scramble{display:inline-block}
.box{max-width:1200px;margin:0 auto;padding:0 40px;box-sizing:border-box}

/* Nav logo: wiggle on hover */
@keyframes logoWiggle{0%,100%{transform:rotate(0)}20%{transform:rotate(-8deg)}40%{transform:rotate(7deg)}60%{transform:rotate(-5deg)}80%{transform:rotate(3deg)}}
.logo-wiggle img{transform-origin:50% 100%}
.logo-wiggle:hover img,.logo-wiggle:focus-visible img{animation:logoWiggle .5s ease}
@media (prefers-reduced-motion: reduce){.logo-wiggle:hover img,.logo-wiggle:focus-visible img{animation:none}}

/* Nav */
.nav{font-family:'Host Grotesk',sans-serif;display:flex;justify-content:space-between;align-items:center;padding:20px 40px;gap:16px;background:var(--bg)}
.nav a{text-decoration:none;margin-left:20px;color:var(--ink)}
.nav a:first-child{margin-left:0;font-weight:600}
.nav .active{font-weight:700;font-size:18px;border-bottom:2px solid var(--ink);padding-bottom:2px}
.nav-links{display:flex;align-items:center;flex-wrap:wrap}

/* Hamburger button: hidden on desktop, shown once the links no longer fit in one row.
   z-index:1000 keeps it (and its X state) above the full-page menu panel below, which itself
   sits above everything else on the page (stickers z-index:5, hover-follow 50, WIP chip 60). */
.nav-toggle{display:none;flex-direction:column;justify-content:center;gap:5px;width:28px;height:22px;background:none;border:none;padding:0;cursor:pointer;flex-shrink:0;position:relative;z-index:1000}
.nav-toggle span{display:block;width:100%;height:2px;background:var(--ink);border-radius:2px;transition:transform .2s,opacity .2s}
.nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
.nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

@media (max-width:700px){
  .nav{position:relative}
  .nav-toggle{display:flex}
  .nav-links{display:none;position:fixed;inset:0;z-index:999;flex-direction:column;align-items:center;justify-content:center;gap:12px;background:var(--bg)}
  .nav-links.open{display:flex}
  .nav-links a{margin-left:0;padding:14px 0;font-size:24px}
  .nav .active{font-size:26px}
}

/* Footer */
footer.site-footer{font-family:'Host Grotesk',sans-serif;color:var(--ink);background:var(--bg);padding-top:var(--space-section);padding-bottom:clamp(32px,6vw,48px)}
footer.site-footer a{color:var(--ink)}
footer.site-footer .talk{font-size:clamp(36px,7vw,96px);font-weight:500;line-height:1;letter-spacing:-.03em}
footer.site-footer .row{display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;margin-top:32px;padding-top:16px;border-top:1px solid #BDBDBD}

/* Section rhythm + shared titles */
.redesign section.section{padding-top:var(--space-section)}
.redesign .section-title{font-size:clamp(26px,4.5vw,40px);font-weight:500;margin:0 0 24px;letter-spacing:-.02em}

/* Selected work */
/* Bento layout: 5 columns, 1st and 4th card span three, the others two, so rows go wide|narrow then narrow|wide (3:2) */
.redesign .work-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:clamp(24px,5vw,40px) 16px}
.redesign .work-card{grid-column:span 2}
.redesign .work-card:nth-child(1),.redesign .work-card:nth-child(4){grid-column:span 3}
.redesign .work-card{text-decoration:none;color:inherit;display:flex;flex-direction:column;gap:10px}
.redesign .work-card .cover-wrap{height:clamp(220px,32vw,420px)}
.redesign .work-card .cover-wrap img{width:100%;height:100%;object-fit:cover}
.redesign .work-title{font-size:clamp(17px,2.4vw,24px);font-weight:500;line-height:1.3}

/* Side Projects heading */
.redesign .sp-heading{display:flex;gap:clamp(16px,5vw,48px);align-items:center}
.redesign .sp-plus{font-size:clamp(36px,8vw,80px);font-weight:500;flex-shrink:0}
.redesign .sp-h2{font-size:clamp(34px,9vw,112px);font-weight:700;letter-spacing:-.03em;line-height:.9;margin:0}

/* Side-project / experience rows: one shared grid, collapses to a stack on phones */
.redesign .row-list{margin-top:clamp(24px,4vw,40px)}
.redesign .row-list-end{border-top:1px solid var(--ink)}
.redesign .sp-row{text-decoration:none;color:inherit;display:grid;grid-template-columns:clamp(110px,22vw,200px) 1fr auto;gap:clamp(10px,2.5vw,24px);align-items:baseline;padding:14px 0;border-top:1px solid var(--ink)}
.redesign .row-name{font-size:clamp(16px,2.6vw,22px)}

.redesign .exp-section{padding-bottom:40px;position:relative}
.redesign .exp-row{text-decoration:none;color:inherit;display:grid;grid-template-columns:1.4fr 2fr auto;gap:clamp(10px,2.5vw,16px);align-items:baseline;padding:16px 0;border-top:1px solid #BDBDBD}
.redesign .exp-row .row-name{font-weight:500}
.redesign .exp-date{text-align:right}
.redesign .exp-section > .row-list-end{border-top:1px solid #BDBDBD}

@media (max-width:700px){
  .box,.nav{padding-left:16px;padding-right:16px}
  .redesign .g2{grid-template-columns:1fr!important}
  .redesign .work-grid{grid-template-columns:1fr}
  .redesign .work-card:nth-child(n){grid-column:auto}
  .redesign .work-card .cover-wrap{height:auto;aspect-ratio:4/3}
}

/* Phones: stack the label/name/date rows instead of forcing three columns into a narrow screen */
@media (max-width:560px){
  .redesign .sp-row,.redesign .exp-row{grid-template-columns:1fr;row-gap:4px}
  .redesign .sp-row > :first-child,.redesign .exp-row > :first-child{order:2}
  .redesign .sp-row > :nth-child(2),.redesign .exp-row > :nth-child(2){order:1}
  .redesign .sp-row > :last-child,.redesign .exp-row > :last-child{order:3;text-align:left}
  footer.site-footer .row{flex-direction:column;align-items:flex-start;gap:12px}
}

/* Wordmark letters and intro words: nudged by the stickers that hit them (see the shape loop in index.html) */
.redesign .wm{display:inline-block}
/* Homepage hero, after dnbls / Dan Billson: the header fills the first screen; "Francesca [image] Loi" sits on
   one line in the middle, spanning the column; the intro sits bottom-left and a ↓ bottom-right.
   7.45em = the name's width (7.30em measured, incl. the image box) plus the cursive i's overhang, so 100cqw / 7.45 fills the column. The load-in
   scramble only uses glyphs no wider than each final letter (narrowGlyphs in index.html), so it never grows. */
#home-header{container-type:inline-size;--wm-fill:1;display:flex;flex-direction:column;min-height:calc(100svh - 80px);box-sizing:border-box}
/* safety net only: never let the wordmark cause a horizontal scroll; clips sideways, never vertically */
#home-wordmark{overflow-x:clip;overflow-y:visible}
#home-wordmark{font-size:calc(100cqw / 7.45 * var(--wm-fill));letter-spacing:-.04em;line-height:.85;margin:auto 0;position:relative;white-space:nowrap}
.redesign .wm-plain{font-family:'Host Grotesk',sans-serif;font-weight:600;color:var(--ink);text-align:center;transition:color .2s}
/* the picture between name and surname (photos a/b/c, swapped by index.html), cap-height tall, on the baseline; grey while loading */
.redesign .wm-photo{width:1.3em;height:.7em;margin:0 .07em;background:#D6D6D2 center/cover no-repeat;vertical-align:baseline;cursor:pointer}
.hero-row{flex:1;display:flex;flex-direction:column;gap:clamp(24px,4vw,48px)}
.hero-bio{display:flex;align-items:flex-end;gap:clamp(12px,1.5vw,20px);max-width:720px}
.hero-down{position:absolute;right:40px;bottom:clamp(20px,3vw,40px);font-size:20px;text-decoration:none;color:var(--ink)}
/* phones: "Francesca" / "[photo] Loi" on two lines so the name can be much bigger; sized on the longer
   line ("Francesca" = 4.465em measured, so 100cqw / 4.5 fills the column) */
.wm-br{display:none}
@media (max-width:700px){
  .wm-br{display:block}
  #home-wordmark{font-size:calc(100cqw / 4.5 * var(--wm-fill));line-height:.95}
  .redesign .wm-photo{margin-left:0}
  #home-header{min-height:calc(85svh - 64px)}
  .hero-down{right:16px}
}

.hero-bio-slot{width:clamp(64px,8vw,108px);height:clamp(64px,8vw,108px);object-fit:contain;flex-shrink:0;rotate:-4deg} /* `rotate`, not transform, so the stickerPop entrance doesn't cancel the tilt */
#home-intro{font-family:'Space Mono',monospace;font-size:clamp(18px,2.1vw,28px);font-weight:400;line-height:1.3;letter-spacing:-.03em;max-width:34ch;margin:0;position:relative}

/* Wordmark "o": a centered dot, like a slashed/dotted zero */
.redesign .wm-o-dot{position:relative}
.redesign .wm-o-dot::after{content:'';position:absolute;left:50%;top:52%;width:.1em;height:.1em;background:currentColor;border-radius:50%;transform:translate(calc(-50% + var(--px,0px)),calc(-50% + var(--py,0px)));pointer-events:none} /* --px/--py: the dot looks toward the mouse (index.html) */

/* Easter egg: the i links to Side Projects */
.redesign .i-secret{position:relative}

/* Floating shapes */
.redesign .shape-field{position:absolute;inset:0;z-index:5;pointer-events:none;overflow:visible;user-select:none}
.redesign .float-shape{position:absolute;pointer-events:auto;cursor:grab;touch-action:none}
.redesign .float-shape:active{cursor:grabbing}
.redesign .float-shape:focus-visible{outline:2px solid var(--indigo);outline-offset:3px}
.redesign .shape-field.static .float-shape{cursor:default}

/* Stickers sit in place from the start and each pops in with its own bouncy wiggle (staggered via
   animation-delay set in JS), instead of all falling in together */
@keyframes stickerPop{
  0%{transform:scale(.5) rotate(-14deg);opacity:0}
  45%{transform:scale(1.14) rotate(9deg);opacity:1}
  65%{transform:scale(.93) rotate(-5deg)}
  82%{transform:scale(1.05) rotate(3deg)}
  100%{transform:scale(1) rotate(0)}
}
.redesign .sticker-pop{animation:stickerPop .7s cubic-bezier(.3,.6,.35,1) both}
@media (prefers-reduced-motion: reduce){.redesign .sticker-pop{animation:none}}

/* 3D placeholder tilt */
.redesign .tilt-box{transition:transform .15s ease-out;transform-style:preserve-3d}

/* Disabled side-project rows: no destination yet, so no hover/pointer affordance */
.redesign .sp-disabled{color:#B5B5B2;cursor:default}
.redesign .sp-disabled .mono{color:#C8C8C5}

/* Shared hover-follow image, used by Experience rows and Side project rows */
.redesign .hover-follow{position:fixed;width:160px;height:110px;z-index:50;transition:opacity .15s;opacity:0;border-radius:12px;overflow:hidden;pointer-events:none}
.redesign .hover-follow.show{opacity:1}
.redesign .hover-follow img{width:100%;height:100%;object-fit:cover;border-radius:12px;display:block}
.redesign .hover-follow.ph{border-radius:12px}
.redesign .hover-follow.logo{background:#232323;padding:18px;box-sizing:border-box;box-shadow:0 6px 20px rgba(0,0,0,.1)}
.redesign .hover-follow.logo img{object-fit:contain;border-radius:0}

/* "In progress" chip: sticky bottom-left, rainbow background. A dark scrim sits between the
   gradient and the text so contrast holds regardless of which hue is behind the letters. */
.redesign .wip-chip{
  position:fixed;left:16px;bottom:16px;z-index:60;
  font-family:'IBM Plex Mono',monospace;font-size:11px;font-weight:500;letter-spacing:.04em;text-transform:uppercase;
  color:#fff;padding:8px 14px;border-radius:999px;
  background:linear-gradient(90deg,#880666,#CF5F3A,#D4D0F1,#A5CCF3,#880666);
  background-size:300% 100%;
  box-shadow:0 4px 14px rgba(0,0,0,.18), inset 0 0 0 999px rgba(0,0,0,.3);
}
@media (max-width:560px){.redesign .wip-chip{left:12px;bottom:12px;font-size:10px;padding:7px 12px}}

/* Selected work covers: zoom on hover, like the live site's work-list images */
.redesign .cover-wrap{overflow:hidden;border-radius:24px}
.redesign .cover-wrap img{transition:transform .5s cubic-bezier(.25,.8,.25,1);transform:scale(1);display:block}
/* Mouse/trackpad: zoom on hover. Scoped to real hover so touch doesn't need a first "activate hover"
   tap before the second tap actually follows the link — that's what made cards feel like they needed
   two presses. Touch instead gets .in-view, toggled by scroll position (see the JS below). */
@media (hover:hover) and (pointer:fine){
  .redesign a:hover .cover-wrap img{transform:scale(1.06)}
}
.redesign .cover-wrap img.in-view{transform:scale(1.06)}
@media (prefers-reduced-motion: reduce){.redesign .cover-wrap img{transition:none;transform:none!important}}

/* ====================================================================
   Case study pages — built to match Francesca's Figma frames
   (A = TL;DR view, B = full story view), file "Portfolio 2026 bis".
   Figma artboard is 1512 wide with ~24px side margins, so the content
   container here is wider than the site's 1200px .box.
   ==================================================================== */

/* Chart fill sampled from the Figma frame — a light tint, not one of the text-safe palette colours */
:root{--chart-qr:#A6C2F0}

/* Content container: 1464px of content on a 1512px viewport, like the artboard */
.case-wide{max-width:1512px;margin:0 auto;padding:0 24px;box-sizing:border-box}

/* .case-narrow pulls the content in to the same column the homepage uses
   (.box: 1200px, 40px gutters) while the colour bands stay full-bleed. */
.case-narrow .case-wide{max-width:1200px;padding-left:40px;padding-right:40px}
.case-band-pad{padding-top:clamp(48px,7vw,96px);padding-bottom:clamp(48px,7vw,96px)}

/* Full-bleed colour band */
.case-band{width:100%}

/* Reading length toggle, centred under the nav */
.case-reading-length{display:flex;justify-content:center;padding:clamp(20px,4vw,32px) 24px 0}
.case-toggle{display:inline-flex;gap:6px;padding:4px;border:2px solid var(--ink);border-radius:999px}
.case-seg{border:0;cursor:pointer;background:none;color:var(--ink);font-family:'IBM Plex Mono',monospace;font-size:13px;letter-spacing:.03em;padding:10px 18px;border-radius:999px;min-height:40px}
.case-seg[aria-pressed="true"]{background:var(--indigo);color:#fff}
.case-cta{background:var(--indigo);color:#fff}
@media (hover:hover){.case-seg:hover{animation:caseWiggle .45s ease-in-out}}
@keyframes caseWiggle{0%,100%{transform:rotate(0)}20%{transform:rotate(-4deg)}40%{transform:rotate(3deg)}60%{transform:rotate(-2deg)}80%{transform:rotate(1deg)}}

/* ---- Title row: kicker | title + tags | goal (Figma: 229 / 353 / 353, 20px gaps) ---- */
.case-hero-title-row{display:grid;grid-template-columns:minmax(0,229px) minmax(0,353px) minmax(0,353px);
  gap:20px;align-items:start;padding:clamp(40px,6vw,96px) 0 clamp(24px,4vw,40px)}
.case-kicker{font-size:clamp(20px,2vw,24px);font-weight:500;line-height:1.25;margin:0}
.case-subtitle{font-size:clamp(22px,2.3vw,28px);font-weight:500;line-height:1.1;margin:0}
.case-tags{display:flex;flex-wrap:wrap;gap:4px;margin-top:14px}
.case-tags span{background:#EDEDED;border-radius:999px;padding:4px 12px;font-size:14px;white-space:nowrap}
.case-hero-goal{font-size:16px;line-height:1.55;margin:0}
.case-hero-goal b{font-weight:700}
@media (max-width:900px){
  .case-hero-title-row{grid-template-columns:1fr;gap:16px}
}

/* ---- Empty image fields left to fill, full bleed like the Figma frames (406 tall) ---- */
.case-hero-ph{padding-top:clamp(20px,3vw,32px)}
.case-field-ph{width:100%}
.case-hero-ph .case-ph,.case-field-ph .case-ph{height:clamp(180px,21vw,322px);border-radius:0;border-left:0;border-right:0}

/* ---- Two-up image band, full bleed (Figma: 1016 / 496, 384 tall) ---- */
.case-hero-images{display:grid;grid-template-columns:1016fr 496fr;grid-template-rows:clamp(200px,25vw,384px);overflow:hidden}
.case-hero-images img{width:100%;height:100%;object-fit:cover;display:block;min-height:0}
.case-hero-images .case-ph{border-radius:0;height:100%}

/* Release-row images crop to the frame height Figma uses, instead of towering over the text */
.case-release-row .case-img{max-height:440px}
.case-release-row .case-img img{height:100%;object-fit:cover;object-position:top}

/* ---- TL;DR slides: 3 columns of 352 with wide gutters ---- */
.case-tldr-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,352px));
  gap:clamp(32px,7vw,125px);justify-content:center}
.case-tldr-slide{display:flex;flex-direction:column;gap:14px}
.case-tldr-num{font-size:clamp(44px,5vw,64px);font-weight:800;line-height:.9;display:inline-block}
.case-tldr-slide:nth-child(1) .case-tldr-num{transform:rotate(-3deg)}
.case-tldr-slide:nth-child(2) .case-tldr-num{transform:rotate(2deg)}
.case-tldr-slide:nth-child(3) .case-tldr-num{transform:rotate(-2deg)}
.case-tldr-slide .case-h3{font-size:clamp(22px,2.4vw,28px)}
.case-tldr-slide .case-body{font-size:16px}

/* ---- "The numbers": four square tiles, slightly tilted (Figma: 268x268, 16px gap) ---- */
.case-stat-tiles{display:flex;flex-wrap:wrap;gap:16px}
.case-stat-tile{width:clamp(170px,21vw,268px);aspect-ratio:1;border-radius:24px;padding:24px;
  display:flex;flex-direction:column;justify-content:space-between;box-sizing:border-box}
.case-stat-tile .num{font-size:clamp(34px,4.5vw,64px);font-weight:800;letter-spacing:-.02em;line-height:1}
.case-stat-tile .num.is-long{font-size:clamp(24px,2.7vw,40px)} /* "42% → 37%" and friends */
.case-stat-tile p{margin:0;font-size:15px;line-height:1.45}
.case-stat-tile:nth-child(odd){transform:rotate(-1.5deg)}
.case-stat-tile:nth-child(even){transform:rotate(1.5deg)}

/* ---- "The small seller gap": heading | paragraph | bullets ---- */
.case-cols-3{display:grid;grid-template-columns:minmax(0,229px) minmax(0,353px) minmax(0,353px);
  gap:clamp(24px,5vw,72px);align-items:start}
.case-bullets{margin:0;padding-left:20px;display:flex;flex-direction:column;gap:8px}
@media (max-width:900px){.case-cols-3{grid-template-columns:1fr;gap:20px}}

/* ---- Research: heuristic evaluation (926) beside three insight cards (471) ---- */
.case-research-row{display:grid;grid-template-columns:minmax(0,926fr) minmax(0,471fr);gap:16px;align-items:start;margin-top:24px}
.case-research-row figure{margin:0;display:flex;flex-direction:column;gap:8px}
.case-research-row figcaption{font-size:11.5px}
.case-insights{display:grid;grid-template-rows:repeat(3,1fr);gap:10px}
.case-insight{background:#fff;border-radius:12px;padding:14px;display:flex;flex-direction:column;gap:8px}
.case-insight img{width:auto;height:60px;object-fit:contain;align-self:flex-start}
.case-insight h3{margin:0;font-size:18px;font-weight:600}
.case-insight p{margin:0;font-size:15.5px;line-height:1.5}
.case-research-row.is-timeline{grid-template-columns:minmax(0,1fr) minmax(0,1.2fr)}
@media (max-width:900px){.case-research-row,.case-research-row.is-timeline{grid-template-columns:1fr}}

/* ---- Journey maps and wireflows: full-width panoramas, stacked, each captioned.
       They run 4:1 or wider, so side-by-side would make them unreadable. ---- */
.case-stack{display:flex;flex-direction:column;gap:28px;margin-top:24px}
.case-stack figure{margin:0;display:flex;flex-direction:column;gap:8px}
.case-stack figcaption{font-size:11.5px}

/* ---- Releases: alternating equal-width text/image rows ---- */
.case-release-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:40px;align-items:center;margin-top:clamp(40px,6vw,64px)}
.case-release-row > div:not(.case-img){display:flex;flex-direction:column;gap:14px}
.case-release-row .case-h3{margin:0}
.case-release-row .case-body{font-size:16px}

/* ---- "One rating per event": heading, rule, three levels ---- */
.case-levels{margin-top:clamp(48px,7vw,80px);display:flex;flex-direction:column;gap:12px}
.case-levels hr{border:none;border-top:2px solid var(--ink);margin:12px 0 0;width:100%}
.case-levels ol{margin:12px 0 0;padding:0;list-style:none;display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:24px}
.case-levels h4{margin:6px 0 4px;font-size:18px;font-weight:600}
.case-levels .case-body{font-size:16px}

/* ---- Four cards in a row (Rules, Results) ---- */
.case-cards-4{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px}
.case-card-white{background:#fff;border-radius:16px;padding:24px 14px;box-sizing:border-box;min-height:220px}
.case-card-white h3{margin:0 0 8px;font-size:18px;font-weight:600}
.case-card-white p{margin:0;font-size:15.5px;line-height:1.5}
.case-card-white.case-stat{min-height:118px;display:flex;flex-direction:column;justify-content:flex-start;padding:14px}
.case-card-white.case-stat .num{font-size:28px;font-weight:800;letter-spacing:-.02em;line-height:1.2}
.case-card-white.case-stat p{margin-top:8px;font-size:15px}

/* ---- Results: text column (430) beside the chart (984) ---- */
.case-chart-row{display:grid;grid-template-columns:minmax(0,430fr) minmax(0,984fr);gap:20px;align-items:start;margin-top:clamp(32px,4vw,40px)}
.case-chart-row .case-body{font-size:16px;max-width:none}
.case-chart-row .case-note{margin-top:16px}
@media (max-width:900px){.case-chart-row{grid-template-columns:1fr}}

.case-figure{margin:0;border:1px solid #BDBDBD;border-radius:12px;padding:20px;display:flex;flex-direction:column;gap:12px;background:rgba(255,255,255,.35)}
.case-figure figcaption .mono{text-transform:none;letter-spacing:0;font-size:11.5px}
.case-chart{display:flex;align-items:flex-end;gap:6px;height:220px}
.case-bar{flex:1 1 0;min-width:0;display:flex;flex-direction:column;justify-content:flex-end;height:100%}
.case-bar-stack{width:100%;max-width:34px;margin:0 auto;display:flex;flex-direction:column;border-radius:3px 3px 0 0;overflow:hidden}
.case-bar-label{font-size:9.5px;letter-spacing:0;display:block;text-align:center;margin-top:4px}
.case-legend{display:flex;gap:16px;flex-wrap:wrap}
.case-legend .mono{text-transform:none;letter-spacing:0;font-size:11.5px;display:inline-flex;align-items:center}
.case-legend i{width:10px;height:10px;border-radius:2px;margin-right:6px;display:inline-block}

/* ---- Learnings: three plain columns ---- */
.case-cols-3-even{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:24px}
.case-cols-3-even h3{margin:0 0 8px;font-size:18px;font-weight:600}
.case-cols-3-even .case-body{font-size:16px;max-width:300px}

/* ---- Shared type ---- */
.case-h2{font-size:clamp(28px,3.4vw,40px);font-weight:700;letter-spacing:-.02em;line-height:1.1;margin:0}
.case-h2-sm{font-size:clamp(20px,1.7vw,24px);letter-spacing:-.01em}
.case-h3{font-size:clamp(22px,2.4vw,28px);font-weight:600;margin:0}
.case-body{font-size:16px;line-height:1.55;margin:0}
.case-note{font-family:'IBM Plex Mono',monospace;font-size:11.5px;color:#56544E;margin:0;line-height:1.5}

.case-pillchain{display:flex;flex-wrap:wrap;gap:6px}
.case-pillchain span{font-family:'IBM Plex Mono',monospace;font-size:12px;padding:6px 12px;border:1px solid #D6D3CA;border-radius:999px;background:#FAF9F6}

/* Image placeholder (no asset yet) */
.case-ph{border:1.5px dashed #9A9A9A;background:repeating-linear-gradient(135deg,#ECEAE4 0 10px,#E6E4DD 10px 20px);border-radius:10px;display:flex;align-items:flex-end;padding:16px;box-sizing:border-box}
.case-ph span{font-family:'IBM Plex Mono',monospace;font-size:12px;color:#56544E;max-width:60ch}

/* Real image */
.case-img{border-radius:12px;overflow:hidden}
.case-img img{width:100%;display:block;object-fit:cover}

/* Zoom affordance + lightbox */
.case-img{position:relative;cursor:zoom-in}
.case-img::after{
  content:"⤢";position:absolute;top:10px;right:10px;width:26px;height:26px;border-radius:50%;
  background:rgba(255,255,255,.85);color:var(--indigo);display:flex;align-items:center;justify-content:center;
  font-size:14px;line-height:1;opacity:0;transition:opacity .15s;pointer-events:none
}
.case-img:hover::after{opacity:1}
.case-lightbox{position:fixed;inset:0;z-index:2000;background:rgba(20,20,19,.92);display:none;align-items:center;justify-content:center;padding:32px;cursor:zoom-out}
.case-lightbox.open{display:flex}
.case-lightbox img{max-width:100%;max-height:100%;border-radius:8px;display:block}
.case-lightbox .case-lightbox-caption{position:absolute;left:0;right:0;bottom:24px;text-align:center;color:#fff;font-family:'IBM Plex Mono',monospace;font-size:12px;padding:0 24px}
.case-lightbox-close{position:absolute;top:20px;right:24px;color:#fff;font-size:28px;line-height:1;background:none;border:0;cursor:pointer}

/* ---- Date requests page: components the reviews page doesn't use ---- */

/* Anything unconfirmed — never publish without checking it first */
.case-flag{background:var(--coral-tint);color:var(--coral);border-radius:4px;padding:1px 6px;font-weight:600;font-size:.92em}

/* Four TL;DR slides across instead of three */
.case-tldr-grid.is-4{grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:clamp(28px,3vw,44px);justify-content:stretch}

/* Research timeline: numbered steps joined by a line. The step you're reading
   fills its dot and drives the sticky image beside it (see .case-sticky-stack).
   Steps get a min-height so there's scroll distance between them. */
.case-timeline{list-style:none;margin:0;padding:clamp(20px,3vw,36px) 0 0;display:flex;flex-direction:column}
.case-timeline li{display:flex;gap:20px;padding-bottom:32px;position:relative;
  min-height:clamp(180px,24vh,260px);opacity:.5;transition:opacity .35s ease}
.case-timeline li.is-active{opacity:1}
.case-timeline li:last-child{padding-bottom:0;min-height:0}
.case-timeline .dot{transform:scale(.55);transition:transform .35s ease}
.case-timeline li.is-active .dot{transform:scale(1)}

/* The image column stays put while the steps scroll past; layers cross-fade */
.case-sticky-stack{position:sticky;top:100px;height:clamp(320px,52vh,460px)}
.case-sticky-stack figure{position:absolute;inset:0;margin:0;display:flex;flex-direction:column;gap:8px;
  opacity:0;transition:opacity .4s ease;pointer-events:none}
.case-sticky-stack figure.is-active{opacity:1;pointer-events:auto}
.case-sticky-stack .case-ph{flex:1;min-height:0}
.case-sticky-stack figcaption{font-size:11.5px}
@media (max-width:900px){
  /* image above the steps, still sticky so it changes as you read.
     Steps keep some height so the image is paced, not flickering. */
  .case-sticky-stack{order:-1;top:8px;height:230px;margin-bottom:24px}
  .case-timeline li{min-height:150px}
  .case-timeline li:last-child{min-height:0}
}
@media (prefers-reduced-motion:reduce){
  .case-timeline li,.case-timeline .dot,.case-sticky-stack figure{transition:none}
  .case-timeline li{opacity:1}
}
.case-timeline li::before{content:"";position:absolute;left:8px;top:22px;bottom:0;width:2px;background:rgba(20,20,19,.18)}
.case-timeline li:last-child::before{display:none}
.case-timeline .dot{width:18px;height:18px;border-radius:50%;flex:none;margin-top:2px;position:relative;z-index:1}
.case-timeline .num{font-size:13px;font-weight:700}
.case-timeline h3{margin:2px 0 0;font-size:clamp(19px,2vw,24px);font-weight:600}
.case-timeline p{margin:6px 0 0;font-size:16px;line-height:1.55}

/* Interview cards: a big number above the heading, a quote below */
.case-quote-num{font-size:40px;font-weight:800;line-height:.9;display:block;margin-bottom:8px}
.case-quote{font-style:italic;font-size:16px;font-weight:600;line-height:1.4;margin:10px 0 0}

/* Decision panels: text and image side by side, alternating, white on odd */
.case-decision{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.25fr);gap:clamp(24px,4vw,48px);
  align-items:start;border-radius:28px;padding:clamp(24px,3vw,40px);margin-top:clamp(28px,4vw,40px)}
.case-decision.is-flipped{grid-template-columns:minmax(0,1.25fr) minmax(0,1fr)} /* image first */
.case-decision:nth-of-type(odd){background:#fff}
.case-decision > div:not(.case-ph):not(.case-img){display:flex;flex-direction:column;gap:16px}
.case-decision .case-decision-num{font-size:clamp(48px,6vw,72px);font-weight:800;line-height:.8}
.case-decision .case-h3{margin:0}
.case-decision .case-body{font-size:17px;margin-top:6px}
@media (max-width:900px){
  .case-decision,.case-decision:nth-child(even){grid-template-columns:1fr}
}

/* Next steps: two tinted panels */
.case-next{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:20px}
.case-next article{border-radius:28px;padding:clamp(24px,3vw,36px);display:flex;flex-direction:column;gap:14px}
.case-next .case-h3{margin:0}

/* A highlighted aside (how to get at the source data) */
.case-callout{background:#fff;border-radius:16px;padding:18px 22px;margin-top:28px}

/* Small data table inside a figure */
.case-table{border-collapse:collapse;font-size:15.5px;width:100%}
.case-table th,.case-table td{padding:8px 10px 8px 0;border-bottom:1px solid #E6E4DD;text-align:left}
.case-table th{font-weight:600}

/* Percentage bars carry their value above and a count below */
.case-bar-pct{font-size:11.5px;display:block;text-align:center;margin-bottom:4px}
.case-bar-count{font-size:10px;letter-spacing:0;display:block;text-align:center;color:#56544E}

/* ---- Scroll reveal, section by section.
   Gated behind .js-reveal (added by JS) so the page stays fully visible
   if scripting is off, and disabled outright for reduced-motion. ---- */
.js-reveal .case-reveal{opacity:0;transform:translateY(20px);
  transition:opacity .55s cubic-bezier(.22,.61,.36,1),transform .55s cubic-bezier(.22,.61,.36,1)}
.js-reveal .case-reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  .js-reveal .case-reveal{opacity:1;transform:none;transition:none}
}

/* ---- Phones ---- */
@media (max-width:700px){
  /* .case-narrow's desktop gutters are more specific, so name it here too */
  .case-wide,.case-narrow .case-wide{padding-left:16px;padding-right:16px}
  .case-band-pad{padding-top:clamp(36px,9vw,56px);padding-bottom:clamp(36px,9vw,56px)}
  .case-reading-length{padding:20px 16px 0}
  .case-seg{padding:10px 14px;font-size:12px}

  /* the two-up image band stacks rather than squeezing the narrow frame to a sliver */
  .case-hero-images{grid-template-columns:1fr;grid-template-rows:auto}
  .case-hero-images .case-ph{height:180px}

  .case-hero-title-row{padding-top:28px}
  .case-tldr-grid{gap:36px}

  .case-stat-tiles{gap:12px}
  .case-stat-tile{width:calc(50% - 6px);aspect-ratio:auto;min-height:150px;padding:18px;gap:16px}
  .case-stat-tile .num{font-size:clamp(28px,8vw,38px)}
  .case-stat-tile p{font-size:13.5px}

  /* cards size to their text instead of holding a desktop-sized floor */
  .case-card-white{min-height:0;padding:20px 16px}
  .case-card-white.case-stat{min-height:0}

  .case-release-row{gap:24px;margin-top:40px}
  .case-release-row .case-img{max-height:320px}

  /* the chart keeps readable bar widths and scrolls sideways instead of collapsing */
  .case-figure{padding:14px;overflow-x:auto}
  .case-chart{min-width:560px}

  /* wide diagrams (journey maps, wireflows, the heuristic table) pan sideways
     at a legible size rather than shrinking to an unreadable strip */
  .case-stack .case-img,.case-research-row .case-img{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .case-stack .case-img img,.case-research-row .case-img img{min-width:720px;max-width:none}
  /* say so, since a sideways-scrolling area is easy to miss on a phone —
     only where something actually pans (a real image, a chart), not a
     placeholder or a table */
  .case-stack figure:has(.case-img) figcaption::after,
  .case-research-row figure:has(.case-img) figcaption::after,
  .case-figure:has(.case-chart) figcaption::after{content:" · scroll to pan";opacity:.65}

  .case-levels ol{gap:20px}
  .case-cols-3-even{gap:20px}
  .case-cols-3-even .case-body{max-width:none}

  /* let a wide image be panned inside the lightbox too */
  .case-lightbox{padding:16px;overflow:auto}
  .case-lightbox img{max-width:none;min-width:min(760px,160vw)}
}
