/* ── Cem Kurtaraner — Portfolio v4 ──────────────────────────── */

:root {
  --paper: #f2f1ea;
  --card: #ffffff;
  --card-inset: #faf9f5;
  --border: #e7e5dc;
  --border-strong: #dddbd0;

  --ink: #16181d;
  --ink-2: #55585f;
  --ink-3: #8b8d94;

  --accent: #2563eb;

  --yellow: #f5b301;
  --orange: #f5732b;
  --pink: #ec5fa0;
  --blue: #2563eb;

  --radius-lg: 22px;
  --radius-md: 16px;
  --radius-sm: 12px;

  --shadow-card: 0 1px 2px rgba(20, 24, 29, 0.04), 0 6px 24px rgba(20, 24, 29, 0.04);
  --shadow-pill: 0 1px 2px rgba(20, 24, 29, 0.06), 0 2px 8px rgba(20, 24, 29, 0.05);

  /* Type scale — stick to these steps, no in-between values.
     12  micro labels (placeholder tags)
     13  meta: dates, sub-labels, captions, pills, status chips
     14  secondary UI: buttons, eyebrows, card descriptions
     15  base UI: nav, body rows, values                (body default)
     16  emphasised: card titles, leads
     17  long-form prose (case study body only)
     18  card + section headings
     21  large headings: lede, callout, case card title
     26  empty-state title
     + clamped displays for hero titles                              */

  --sidebar-w: 360px;
  --gutter: 40px;
  --gutter-y: 16px;
  --nav-top: 30px;
  --content-max: 1200px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
}

body {
  background: var(--paper);
  color: var(--ink);
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: inherit; text-decoration: none; }

/* ── App shell ──────────────────────────────────────────────── */
.app {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  height: 100vh;
  overflow: hidden;
}

/* ── Sidebar ────────────────────────────────────────────────── */
.sidebar {
  display: flex;
  flex-direction: column;
  gap: 22px;
  padding: var(--nav-top) var(--gutter) var(--gutter-y);
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  overflow-y: auto;
}

.profile-card {
  display: flex;
  align-items: center;
  gap: 13px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  box-shadow: var(--shadow-card);
}

.avatar {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  font-size: 17px;
  display: grid;
  place-items: center;
  letter-spacing: 0.2px;
}

.profile-meta { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.profile-name { font-weight: 600; font-size: 15px; color: var(--ink); }
.profile-sub { font-size: 13px; color: var(--ink-3); }

.nav { display: flex; flex-direction: column; gap: 4px; }
.nav--footer { margin-top: auto; }

.nav-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  border-radius: var(--radius-sm);
  color: var(--ink-2);
  font-weight: 500;
  font-size: 15px;
  border: 1px solid transparent;
  transition: background .15s ease, color .15s ease, box-shadow .15s ease;
}

.nav-item:hover { background: rgba(20, 24, 29, 0.045); color: var(--ink); }

.nav-item.is-active {
  background: var(--card);
  color: var(--ink);
  font-weight: 600;
  border-color: var(--border);
  box-shadow: var(--shadow-pill);
}

.nav-item .ic {
  flex: none;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Mobile menu button. Hidden on the wide layout, where the full rail is
   always visible; see the max-width: 860px block for its placement. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  flex: none;
  appearance: none;
  cursor: pointer;
  color: var(--ink-2);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-pill);
}
.nav-toggle:hover { color: var(--ink); }
.nav-toggle .ic {
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.nav-toggle .ic-close { display: none; }
.sidebar.is-open .nav-toggle { color: var(--ink); }
.sidebar.is-open .nav-toggle .ic-open { display: none; }
.sidebar.is-open .nav-toggle .ic-close { display: block; }

/* ── Content card ───────────────────────────────────────────── */
.content {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  margin: var(--gutter-y) var(--gutter) var(--gutter-y) 0;
  height: calc(100vh - 2 * var(--gutter-y));
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-width: 0;
}

.topbar {
  flex: none;
  border-bottom: 1px solid var(--border);
  padding: 0 40px;
}
.topbar-inner {
  max-width: var(--content-max);
  margin-inline: auto;
  padding: 26px 0 22px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}

.topbar-title { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }

.topbar-meta { text-align: right; line-height: 1.35; }
.topbar-place { display: block; font-weight: 600; font-size: 15px; }
.topbar-time { display: block; font-size: 13px; color: var(--ink-3); }

.content-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0 40px; }
.content-inner { max-width: var(--content-max); margin-inline: auto; padding: 30px 0 44px; }

.greeting {
  margin: 8px 0 40px;
  font-size: clamp(40px, 5.2vw, 66px);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--ink);
}

/* ── Quick actions ──────────────────────────────────────────── */
.quick-actions {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  margin-bottom: 26px;
}

.action {
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 20px 20px 22px;
  box-shadow: var(--shadow-card);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}

.action:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: 0 2px 4px rgba(20,24,29,.05), 0 12px 28px rgba(20,24,29,.07);
}

.action-icon {
  width: 42px;
  height: 42px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  margin-bottom: 14px;
}
.action-icon svg { width: 22px; height: 22px; fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.action-icon--yellow { background: var(--yellow); }
.action-icon--orange { background: var(--orange); }
.action-icon--pink   { background: var(--pink); }
.action-icon--blue   { background: var(--blue); }
/* filled-look grid icon for browse */
.action-icon--yellow svg rect { fill: #fff; stroke: none; }

.action-title { font-weight: 600; font-size: 16px; color: var(--ink); letter-spacing: -0.01em; }
.action-sub { font-size: 13px; color: var(--ink-3); word-break: break-word; }

/* ── Featured ───────────────────────────────────────────────── */
.featured {
  background: var(--card-inset);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 24px 24px 26px;
}

.featured-label { margin: 0 0 18px; font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }

.featured-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 18px;
}

.feature-card {
  display: flex;
  align-items: center;
  gap: 18px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 22px 22px;
  box-shadow: var(--shadow-card);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}

.feature-card:hover {
  transform: translateY(-2px);
  border-color: var(--border-strong);
  box-shadow: 0 2px 4px rgba(20,24,29,.05), 0 12px 28px rgba(20,24,29,.07);
}

.feature-icon {
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--card-inset);
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
}
.feature-icon svg { width: 24px; height: 24px; fill: none; stroke: var(--ink); stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.feature-card:nth-child(1) .feature-icon svg { stroke: var(--blue); }
.feature-card:nth-child(2) .feature-icon svg { stroke: var(--orange); }

.feature-text { min-width: 0; }
.feature-title { margin: 0 0 7px; font-size: 16px; font-weight: 700; line-height: 1.28; letter-spacing: -0.01em; color: var(--ink); }
.feature-desc { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }

.feature-arrow {
  flex: none;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  align-self: center;
}

/* ── About + Activity split ─────────────────────────────────── */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-top: 20px;
  align-items: start;
}

/* ── About card ─────────────────────────────────────────────── */
.about-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 26px 28px 8px;
}

.about-head {
  display: flex;
  align-items: center;
  gap: 15px;
  padding-bottom: 22px;
}

.about-avatar {
  flex: none;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  object-fit: cover;
  background: var(--card-inset);
}

.about-id { min-width: 0; line-height: 1.3; }
.about-name { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -0.01em; color: var(--ink); }
.about-role { margin: 0; font-size: 15px; color: var(--ink-2); }

.about-bio {
  margin: 0;
  padding: 22px 0 14px;
  border-top: 1px solid var(--border);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 62ch;
}

/* The short bio ends by offering the long one. Block-level so its margin sits
   between the bio and the detail rows, and only as wide as its own text. */
.about-more {
  display: flex;
  align-items: center;
  gap: 6px;
  width: max-content;
  margin: 0 0 20px;
  font-size: 15px;
  font-weight: 600;
  color: var(--accent);
}
.about-more:hover { text-decoration: underline; }

.about-details {
  margin: 0;
  border-top: 1px solid var(--border);
  padding: 8px 0;
}

.about-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
}

.about-row dt {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ink-2);
  font-size: 15px;
}

.about-row dt .ic {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.about-row dd {
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  color: var(--ink);
  text-align: right;
}

/* ── Activity card ──────────────────────────────────────────── */
.activity-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 24px 26px 18px;
}

.activity-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.activity-head svg {
  width: 25px;
  height: 25px;
  fill: none;
  stroke: var(--ink);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.activity-title { margin: 0; font-size: 18px; font-weight: 700; letter-spacing: -0.01em; }

.activity-list { list-style: none; margin: 0; padding: 0; }

.activity-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 13px 0;
}

.activity-date { color: var(--ink-3); font-size: 13px; font-variant-numeric: tabular-nums; }
.activity-text { color: var(--ink); font-size: 15px; letter-spacing: -0.005em; }

.tag {
  justify-self: end;
  padding: 5px 13px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  letter-spacing: -0.005em;
}
.tag--green  { background: #e6f1e9; color: #2f6b48; }
.tag--cream  { background: #f4ecdc; color: #8a6a2c; }
.tag--purple { background: #ede8fb; color: #644ab8; }
.tag--blue   { background: #e6edfb; color: #2f57a8; }

/* ── Page title + filters (section pages) ───────────────────── */
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin: 4px 0 34px;
}
.page-title {
  margin: 0;
  font-size: clamp(34px, 4.4vw, 54px);
  font-weight: 500;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--ink);
}
.filter-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--card);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.filter-btn:hover { background: var(--card-inset); border-color: var(--border-strong); }
.filter-btn svg {
  width: 18px; height: 18px;
  fill: none; stroke: var(--ink-2);
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}

/* ── Filter dropdown ────────────────────────────────────────── */
.dropdown { position: relative; }
.filter-btn .chev { width: 16px; height: 16px; margin-left: 2px; transition: transform .18s ease; }
.dropdown.is-open .chev { transform: rotate(180deg); }
.dropdown.is-open .filter-btn { background: var(--card-inset); border-color: var(--border-strong); }

.dropdown-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 210px;
  list-style: none;
  margin: 0;
  padding: 6px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 10px 34px rgba(20, 24, 29, 0.14);
  z-index: 30;
}
.dropdown-menu[hidden] { display: none; }
/* invisible bridge so hover doesn't drop across the gap to the menu */
.dropdown-menu::before { content: ""; position: absolute; left: 0; right: 0; top: -8px; height: 8px; }

.dropdown-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 9px;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink);
  cursor: pointer;
}
.dropdown-option:hover { background: var(--card-inset); }
.dropdown-option[aria-selected="true"] { font-weight: 600; }
.dropdown-option .check {
  margin-left: auto;
  width: 17px; height: 17px;
  fill: none; stroke: var(--accent);
  stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round;
  opacity: 0;
}
.dropdown-option[aria-selected="true"] .check { opacity: 1; }

/* ── Case study cards ───────────────────────────────────────── */
.cs-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 28px;
}

.cs-card {
  display: flex;
  flex-direction: column;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.cs-card:hover {
  transform: translateY(-3px);
  border-color: var(--border-strong);
  box-shadow: 0 2px 4px rgba(20,24,29,.05), 0 16px 36px rgba(20,24,29,.09);
}

.cs-cover {
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--card-inset);
}
.cs-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

.cs-cover--placeholder { display: grid; place-items: center; }
.cs-cover--soft { background: linear-gradient(135deg, #e3e9fb 0%, #efe3f6 48%, #fce7da 100%); }
.cs-cover__ph {
  width: 66px; height: 66px;
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.8);
  display: grid; place-items: center;
  box-shadow: 0 8px 24px rgba(20, 24, 29, 0.08);
}
.cs-cover__ph svg { width: 30px; height: 30px; fill: none; stroke: #6b4bbd; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

.cs-body { padding: 22px 24px 24px; }
.cs-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  /* On a narrow card a long title and a date range can't share one line, so the
     year drops beneath it rather than being pushed past the card edge. */
  flex-wrap: wrap;
  gap: 4px 16px;
}
.cs-title { margin: 0; font-size: 21px; font-weight: 700; letter-spacing: -0.015em; color: var(--ink); }
.cs-years { flex: none; margin-left: auto; font-size: 15px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.cs-sub { margin: 6px 0 18px; font-size: 15px; color: var(--ink-2); }

.cs-tags { display: flex; flex-wrap: wrap; gap: 10px; }
.cs-tag {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 13px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.cs-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.cs-dot--blue { background: var(--blue); }
.cs-dot--violet { background: #7c3aed; }
.cs-dot--green { background: #2f9e6b; }
.cs-tag svg { width: 15px; height: 15px; fill: none; stroke: var(--ink-2); stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }

/* ── Side project cards ─────────────────────────────────────────────────────
   A side project has no detail page behind it, so the card carries the whole
   write-up: a mock of the product on the left, the story and the outbound
   link on the right. One project per row, stacking below 860px.            */
.pr-list { display: flex; flex-direction: column; gap: 28px; }

.pr-card {
  display: grid;
  grid-template-columns: minmax(0, 0.68fr) minmax(0, 1fr);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}

.pr-media {
  display: grid;
  place-items: center;
  padding: 34px 30px;
  border-right: 1px solid var(--border);
  background: linear-gradient(135deg, #e3e9fb 0%, #efe3f6 48%, #fce7da 100%);
}

/* Reconstruction of the site's own comparison table, trimmed to the columns
   that carry the decision: the mode, how long it takes, and how it is paid
   for. The partner row is labelled here exactly as it is on the live site. */
.pr-mock {
  width: 100%;
  max-width: 380px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: 0 8px 26px rgba(20, 24, 29, 0.09);
  overflow: hidden;
}
.pr-mock-head { padding: 13px 16px; border-bottom: 1px solid var(--border); background: var(--card-inset); }
.pr-mock-route { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 700; color: var(--ink); }
.pr-mock-route svg { width: 14px; height: 14px; flex: none; fill: none; stroke: var(--ink-3); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.pr-mock-note { margin: 5px 0 0; font-size: 12px; color: var(--ink-3); }

/* The group-size control and the partner disclosure are both on the live page.
   They also give the panel enough height to sit squarely in the media column. */
.pr-mock-seg { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.pr-mock-seg-label { margin-right: 2px; font-size: 12px; color: var(--ink-3); white-space: nowrap; }
.pr-mock-chip {
  min-width: 25px;
  padding: 3px 7px;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--card);
  font-size: 12px; font-weight: 600; color: var(--ink-2); text-align: center;
}
.pr-mock-chip.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }

.pr-mock-row {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.pr-mock-row:last-of-type { border-bottom: 0; }
.pr-mock-mode { flex: 1 1 auto; min-width: 0; font-weight: 600; color: var(--ink); }
.pr-mock-time { flex: none; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.pr-mock-flag {
  flex: none;
  padding: 2px 8px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--ink-3);
}

.pr-mock-foot {
  display: flex; align-items: flex-start; gap: 7px;
  margin: 0;
  padding: 11px 16px;
  border-top: 1px solid var(--border);
  background: var(--card-inset);
  font-size: 12px; line-height: 1.45; color: var(--ink-3);
}
.pr-mock-foot svg { width: 13px; height: 13px; margin-top: 1px; flex: none; fill: none; stroke: var(--ink-3); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

.pr-body { padding: 30px 32px 32px; min-width: 0; }
.pr-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 14px; }
.pr-title { margin: 0; font-size: 21px; font-weight: 700; letter-spacing: -0.015em; color: var(--ink); }
.pr-live {
  flex: none; margin-left: auto;
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 11px; border-radius: 999px;
  background: #e6f1e9; color: #2f6b48;
  font-size: 13px; font-weight: 700;
}
.pr-live::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.pr-sub { margin: 7px 0 0; font-size: 15px; color: var(--ink-2); }
.pr-copy { margin: 16px 0 0; font-size: 15px; line-height: 1.65; color: var(--ink-2); }

.pr-facts {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(125px, 1fr));
  gap: 14px 24px;
  margin: 22px 0 0; padding: 18px 0 0;
  border-top: 1px solid var(--border);
  list-style: none;
}
.pr-facts b { display: block; font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.pr-facts span { font-size: 13px; color: var(--ink-3); }
/* The figures are small and early, so the window they cover is stated with them. */
.pr-facts-note { margin: 12px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-3); }

.pr-tags { margin-top: 22px; }
.pr-note {
  margin: 22px 0 0;
  padding-left: 15px;
  border-left: 2px solid var(--border-strong);
  font-size: 15px; line-height: 1.6; color: var(--ink-2);
}

/* Two destinations, one card: the write-up here and the live site elsewhere.
   The filled button is the internal one, so the default is to stay. */
.pr-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 24px; }
.pr-link {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 17px; border-radius: 999px;
  background: var(--card); border: 1px solid var(--border-strong);
  font-size: 14px; font-weight: 600; color: var(--accent);
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.pr-link:hover { background: var(--card-inset); border-color: var(--ink-3); }
.pr-link--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.pr-link--primary:hover { background: #1d4ed8; border-color: #1d4ed8; color: #fff; }
.pr-link svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ── Case study (detail page) ───────────────────────────────── */
.case { max-width: 820px; margin-inline: auto; }

.case-back {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-3);
  margin-bottom: 30px;
}
.case-back:hover { color: var(--ink); }

.case-eyebrow { margin: 0 0 14px; font-size: 14px; font-weight: 600; color: var(--accent); }
.case-title {
  max-width: 720px;
  margin: 0 0 20px;
  font-size: clamp(32px, 4.4vw, 52px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.04;
  color: var(--ink);
}
.case-lede {
  margin: 0 0 24px;
  font-size: clamp(18px, 2.1vw, 21px);
  line-height: 1.5;
  color: var(--ink-2);
}
.case-hero-tags { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 34px; }

.case-facts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 22px;
  padding: 24px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-bottom: 44px;
}
.case-fact-label { margin: 0 0 5px; font-size: 13px; color: var(--ink-3); }
.case-fact-value { margin: 0; font-size: 15px; font-weight: 600; color: var(--ink); }

.case-section { margin: 0 0 52px; }
/* The run from the information model through to the explorations is the
   densest reasoning on the page; it gets a little more air between sections. */
.case-section--airy { margin-bottom: 72px; }
.case-h {
  margin: 0 0 18px;
  font-size: clamp(22px, 2.6vw, 28px);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.case-p { margin: 0 0 18px; font-size: 17px; line-height: 1.65; color: var(--ink-2); }
.case-p:last-child { margin-bottom: 0; }
.case-p strong { color: var(--ink); font-weight: 600; }

.case-callout {
  margin: 8px 0 44px;
  padding: 4px 0 4px 22px;
  border-left: 3px solid var(--accent);
  font-size: clamp(18px, 2.2vw, 21px);
  line-height: 1.5;
  font-weight: 500;
  color: var(--ink);
}

.case-figure { margin: 0 0 44px; position: relative; }
.case-figure img {
  width: 100%;
  display: block;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--card-inset);
}
.case-figure figcaption { margin-top: 12px; font-size: 13px; color: var(--ink-3); text-align: center; }
/* A portrait screenshot at full column width dwarfs the prose around it. */
.case-figure--narrow { max-width: 520px; margin-inline: auto; }
/* Says a screen was recreated rather than exported. Sits under the caption so
   the disclosure is always present but never the first thing read. */
.recon { display: block; margin-top: 4px; font-size: 12px; color: var(--ink-3); opacity: .8; }

.case-list { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 16px; }
.case-list li { position: relative; padding-left: 22px; font-size: 17px; line-height: 1.6; color: var(--ink-2); }
.case-list li::before {
  content: "";
  position: absolute; left: 0; top: 10px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent);
}
.case-list li strong { color: var(--ink); font-weight: 600; }

.steps { display: grid; gap: 34px; margin-top: 8px; }
.step-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.step-num {
  flex: none;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 14px; font-weight: 700;
  display: grid; place-items: center;
}
.step-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--ink); }
.step-desc { margin: 3px 0 0; font-size: 15px; line-height: 1.55; color: var(--ink-2); }

.case-note {
  margin: 0 0 44px;
  padding: 15px 18px;
  border: 1px dashed #e3c866;
  background: #fdf8e8;
  border-radius: 12px;
  font-size: 14px;
  line-height: 1.55;
  color: #7c621f;
}

.metrics { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; margin-top: 6px; }
.metric {
  padding: 15px 18px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card-inset);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}

/* Sub-heading inside a case section */
.case-sub {
  margin: 34px 0 12px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.case-section-body > .case-sub:first-child { margin-top: 0; }

/* Headline result figures */
.stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; margin: 0 0 24px; }
.stat {
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--card-inset);
}
.stat-num {
  margin: 0 0 4px;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.stat-label { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }

/* Figure provenance chip — e.g. a diagram redrawn rather than exported */
.fig-tag {
  display: inline-block;
  margin-right: 6px;
  padding: 2px 9px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card-inset);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2);
  vertical-align: 1px;
}

/* Placeholder / to-confirm markers.
   These are notes to the author, not content: they stay searchable in the
   source and findable on the page, but they must never out-shout the work. */
.ph-note { color: var(--ink-3); border-bottom: 1px dotted var(--border-strong); }
.ph {
  display: block;
  margin: 16px 0 0;
  padding: 0 0 0 14px;
  border-left: 2px dashed var(--border-strong);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-3);
}
.ph strong { color: var(--ink-2); font-weight: 600; }
.ph em { font-style: normal; color: var(--ink-2); }
.ph + .ph { margin-top: 10px; }
.tbc {
  display: inline-block;
  padding: 1px 8px;
  border: 1px dashed var(--border-strong);
  border-radius: 999px;
  background: var(--card-inset);
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-3);
  cursor: help;
}

.case-cta {
  display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap;
  margin-top: 8px;
  padding-top: 36px;
  border-top: 1px solid var(--border);
}
.case-cta a { font-size: 16px; font-weight: 600; color: var(--accent); }
.case-cta a:hover { text-decoration: underline; }

@media (max-width: 720px) {
  .case-facts { grid-template-columns: repeat(2, 1fr); }
  .metrics, .stats { grid-template-columns: 1fr; }
}

/* ── Reader lens picker ─────────────────────────────────────── */
.lens {
  margin: 0 0 34px;
  padding: 18px 20px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card-inset);
}
.lens-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; }
.lens-title { font-size: 14px; font-weight: 700; color: var(--ink); }
.lens-desc { font-size: 14px; color: var(--ink-3); }
.lens-options { display: flex; gap: 8px; flex-wrap: wrap; }
.lens-opt {
  font: inherit; font-size: 14px; font-weight: 600;
  padding: 9px 16px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--card); color: var(--ink-2);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.lens-opt:hover { border-color: var(--border-strong); color: var(--ink); }
.lens-opt[aria-selected="true"] { background: var(--ink); color: #fff; border-color: var(--ink); }

/* ── Sticky reading bar ─────────────────────────────────────── */
.readbar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 0;
  margin: 0 0 28px;
  background: var(--card);
  border-bottom: 1px solid var(--border);
}
.readbar-btn { padding: 7px 13px; font-size: 14px; }
.readbar-toc .dropdown-menu { left: 0; right: auto; }
.readbar-progress { position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; }
.readbar-progress span { display: block; height: 100%; width: 0; background: var(--accent); border-radius: 2px; transition: width .1s linear; }

/* ── Collapsed sections (reader lens) ───────────────────────── */
.section-reveal {
  display: none;
  align-items: center; gap: 8px;
  margin-top: 2px;
  font: inherit; font-size: 14px; font-weight: 600;
  color: var(--ink-2); background: var(--card);
  border: 1px solid var(--border); border-radius: 999px;
  padding: 8px 15px; cursor: pointer;
}
.section-reveal:hover { border-color: var(--border-strong); color: var(--ink); }
.case-section.is-collapsed .section-reveal { display: inline-flex; }
.case-section.is-collapsed .case-section-body { display: none; }
.case-section.is-collapsed .case-h { margin-bottom: 12px; }
.case-section.is-collapsed.is-open .section-reveal { display: none; }
.case-section.is-collapsed.is-open .case-section-body { display: block; }

@media (prefers-reduced-motion: reduce) {
  .readbar-progress span { transition: none; }
}
@media (max-width: 620px) {
  .readbar { flex-wrap: wrap; }
}

/* ── Product-persona journey tabs ───────────────────────────── */
.journey {
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--card);
  box-shadow: 0 1px 2px rgba(20,24,29,.04), 0 10px 30px rgba(37,99,235,.07);
}

/* header: makes it obvious this block is interactive */
.journey-head {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 16px 20px;
  background: linear-gradient(180deg, rgba(37,99,235,.055), rgba(37,99,235,.02));
  border-bottom: 1px solid var(--border);
}
.journey-badge {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  padding: 5px 11px; border-radius: 999px;
  background: var(--accent); color: #fff;
  font-size: 12px; font-weight: 700; letter-spacing: .02em;
}
.journey-badge svg { width: 13px; height: 13px; fill: currentColor; stroke: none; }
.journey-hint { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink-2); }
.journey-hint strong { color: var(--ink); font-weight: 700; }

/* stepper */
.journey-tabs { display: flex; border-bottom: 1px solid var(--border); background: var(--card-inset); overflow-x: auto; }
.jtab {
  position: relative;
  flex: 1 0 auto; min-width: 150px;
  display: flex; align-items: center; gap: 11px;
  font: inherit; text-align: left;
  padding: 14px 26px 14px 16px;
  background: none; border: none; border-bottom: 2px solid transparent;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.jtab + .jtab { border-left: 1px solid var(--border); }
/* chevron between steps */
.jtab:not(:last-child)::after {
  content: ""; position: absolute; right: 9px; top: 50%;
  width: 7px; height: 7px; margin-top: -4px;
  border-right: 1.5px solid var(--ink-3); border-top: 1.5px solid var(--ink-3);
  transform: rotate(45deg); opacity: .55;
}
.jtab-num {
  flex: none; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--card); border: 1.5px solid var(--border-strong);
  font-size: 13px; font-weight: 700; color: var(--ink-3);
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.jtab-text { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.jtab-label { font-size: 15px; font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.jtab-meta { font-size: 13px; color: var(--ink-3); white-space: nowrap; }

.jtab:hover { background: rgba(37,99,235,.05); }
.jtab:hover .jtab-num { border-color: var(--accent); color: var(--accent); }
.jtab:hover .jtab-label { color: var(--ink); }

.jtab[aria-selected="true"] { background: var(--card); border-bottom-color: var(--accent); }
.jtab[aria-selected="true"] .jtab-num { background: var(--accent); border-color: var(--accent); color: #fff; }
.jtab[aria-selected="true"] .jtab-label { color: var(--ink); font-weight: 700; }

/* visited steps get a tick, so exploring all four feels rewarded */
.jtab.is-visited:not([aria-selected="true"]) .jtab-num {
  background: #e6f1e9; border-color: #bcdcc8; color: transparent; position: relative;
}
.jtab.is-visited:not([aria-selected="true"]) .jtab-num::after {
  content: ""; position: absolute; left: 7px; top: 6px;
  width: 5px; height: 9px;
  border-right: 2px solid #2f6b48; border-bottom: 2px solid #2f6b48;
  transform: rotate(42deg);
}

/* nudge the un-explored steps on first view */
.jtab.is-nudge .jtab-num { animation: jnudge 2s ease-out infinite; }
@keyframes jnudge {
  0% { box-shadow: 0 0 0 0 rgba(37,99,235,.45); }
  70% { box-shadow: 0 0 0 8px rgba(37,99,235,0); }
  100% { box-shadow: 0 0 0 0 rgba(37,99,235,0); }
}

/* footer walkthrough */
.journey-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 13px 20px;
  border-top: 1px solid var(--border);
  background: var(--card-inset);
}
.journey-progress { font-size: 13px; font-weight: 600; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.journey-next {
  display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: 14px; font-weight: 600;
  padding: 9px 16px; border-radius: 999px;
  background: var(--card); border: 1px solid var(--border-strong); color: var(--accent);
  cursor: pointer;
  transition: background .15s ease, box-shadow .15s ease;
}
.journey-next:hover { background: var(--accent); border-color: var(--accent); color: #fff; }
.journey-next svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

@media (prefers-reduced-motion: reduce) { .jtab.is-nudge .jtab-num { animation: none; } }
@media (max-width: 700px) {
  .jtab-meta { display: none; }
  .jtab { min-width: 118px; }
}
.jpanel { padding: 24px 24px 26px; display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 26px; align-items: start; }
.jpanel--full { grid-template-columns: 1fr; }
.jpanel[hidden] { display: none; }
.jpanel-body { min-width: 0; }
.jpanel-media { min-width: 0; }
.jpanel-media .case-figure { margin: 0; }
.jpanel-media .case-figure img { border-radius: var(--radius-sm); }
.jplaceholder {
  position: relative;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  display: grid; place-items: center;
}
.jplaceholder--configure { background: linear-gradient(135deg, #e3e9fb, #eef1fb); }
.jplaceholder--verify { background: linear-gradient(135deg, #e4f2ea, #eff7f1); }
.jplaceholder--buyer { background: linear-gradient(135deg, #fbeede, #fdf4ea); }
.jplaceholder .cs-cover__ph svg { stroke: #55585f; }
.jplaceholder-tag {
  position: absolute; bottom: 12px; left: 50%; transform: translateX(-50%);
  font-size: 12px; font-weight: 600; color: var(--ink-3);
  background: rgba(255, 255, 255, 0.85);
  border: 1px solid var(--border);
  padding: 3px 10px; border-radius: 999px; white-space: nowrap;
}
.jpanel-status {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 700;
  padding: 4px 11px; border-radius: 999px; margin-bottom: 15px;
}
.jpanel-status::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.jpanel-status.is-shipped { background: #e6f1e9; color: #2f6b48; }
.jpanel-status.is-next { background: #fbf1cf; color: #8a6a1f; }
.jpanel-status.is-planned { background: var(--card-inset); color: var(--ink-3); }
.jpanel-status.is-foundation { background: #e6edfb; color: #2f57a8; }
.jpanel-lead { margin: 0 0 14px; font-size: 16px; line-height: 1.55; color: var(--ink-2); }
.jpanel-lead strong { color: var(--ink); font-weight: 600; }
.jpanel-link { display: inline-block; margin-top: 4px; font-size: 15px; font-weight: 600; color: var(--accent); cursor: pointer; }
.jpanel-link:hover { text-decoration: underline; }

/* ── Figure zoom + lightbox ─────────────────────────────────── */
.figure-zoom {
  position: absolute; top: 12px; right: 12px;
  width: 34px; height: 34px; border-radius: 9px;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--border);
  display: grid; place-items: center; cursor: pointer;
  opacity: 0; transition: opacity .15s ease; z-index: 3;
}
.case-figure:hover .figure-zoom, .figure-zoom:focus-visible { opacity: 1; }
.figure-zoom svg { width: 17px; height: 17px; fill: none; stroke: var(--ink); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.case-figure img { cursor: zoom-in; }

.lightbox {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(16, 18, 22, 0.82);
  display: flex; align-items: center; justify-content: center;
  padding: 32px; opacity: 0; pointer-events: none;
  transition: opacity .18s ease;
}
.lightbox.is-open { opacity: 1; pointer-events: auto; }
.lightbox img { max-width: min(1200px, 95vw); max-height: 92vh; border-radius: 12px; box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45); }
.lightbox .lb-frame { display: none; width: min(1280px, 95vw); height: min(880px, 90vh); border: 0; border-radius: 12px; background: #fff; box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45); }

/* ── Embedded interactive screen (journey mock) ─────────────── */
.jmock { display: block; width: 100%; padding: 0; border: none; background: none; cursor: pointer; text-align: left; font: inherit; }
.jmock-frame {
  position: relative; display: block;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  overflow: hidden; background: #fff;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.jmock:hover .jmock-frame { border-color: var(--border-strong); box-shadow: 0 10px 28px rgba(20, 24, 29, 0.10); }
.jmock-frame iframe { position: absolute; top: 0; left: 0; width: 320%; height: 320%; transform: scale(.3125); transform-origin: top left; border: 0; pointer-events: none; }
.jmock-cta { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; font-size: 14px; font-weight: 600; color: var(--accent); }
.jmock-cta svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.lightbox-close {
  position: absolute; top: 20px; right: 24px;
  width: 40px; height: 40px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.15); color: #fff;
  border: none; cursor: pointer; display: grid; place-items: center;
}
.lightbox-close svg { width: 20px; height: 20px; fill: none; stroke: #fff; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* ── Annotated hotspots ─────────────────────────────────────── */
.hotspot {
  position: absolute; transform: translate(-50%, -50%);
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent); color: #fff;
  font-size: 13px; font-weight: 700;
  border: 2px solid #fff; box-shadow: 0 2px 10px rgba(20, 24, 29, 0.35);
  cursor: pointer; display: grid; place-items: center; z-index: 4; padding: 0;
}
.hotspot::after {
  content: ""; position: absolute; inset: -5px; border-radius: 50%;
  border: 2px solid var(--accent); opacity: .45;
}
.hotspot:hover, .hotspot.is-active { background: #1d4ed8; }
.anno-pop {
  position: absolute; z-index: 5; max-width: 240px;
  background: var(--ink); color: #fff;
  padding: 11px 14px; border-radius: 10px;
  font-size: 13px; line-height: 1.45;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.32);
  pointer-events: none; opacity: 0; transition: opacity .12s ease;
}
.anno-pop.is-visible { opacity: 1; }
.anno-pop strong { display: block; margin-bottom: 3px; font-weight: 700; }

@media (prefers-reduced-motion: reduce) {
  .lightbox, .figure-zoom, .anno-pop { transition: none; }
  .hotspot::after { display: none; }
}

/* ── Glossary term tooltips ─────────────────────────────────── */
.term { border-bottom: 1px dashed var(--ink-3); cursor: help; }
.term-tip {
  position: fixed; z-index: 120;
  transform: translate(-50%, -100%);
  max-width: 260px;
  background: var(--ink); color: #fff;
  padding: 9px 12px; border-radius: 9px;
  font-size: 13px; line-height: 1.45;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
  opacity: 0; pointer-events: none; transition: opacity .12s ease;
}
.term-tip.is-visible { opacity: 1; }

/* ── Section heading anchor copy ────────────────────────────── */
.case-h { position: relative; }
.anchor-link {
  margin-left: 8px;
  font: inherit; font-size: 0.62em; font-weight: 700;
  color: var(--ink-3); background: none; border: none;
  cursor: pointer; opacity: 0; vertical-align: middle;
  transition: opacity .12s ease, color .12s ease;
}
.case-section:hover .anchor-link, .anchor-link:focus-visible { opacity: 1; }
.anchor-link:hover { color: var(--accent); }
.anchor-link.is-copied { opacity: 1; color: #2f6b48; }

@media (prefers-reduced-motion: reduce) { .term-tip { transition: none; } }
@media (max-width: 640px) {
  .jpanel { grid-template-columns: 1fr; }
  .anchor-link { display: none; }
}

/* ── Empty state (placeholder pages) ────────────────────────── */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 58vh;
  padding: 40px 20px;
}

.empty-icon {
  width: 68px;
  height: 68px;
  border-radius: 20px;
  display: grid;
  place-items: center;
  background: var(--card-inset);
  border: 1px solid var(--border);
  margin-bottom: 22px;
}
.empty-icon svg {
  width: 30px;
  height: 30px;
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.empty-title {
  margin: 0 0 10px;
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.empty-text {
  margin: 0 0 24px;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 42ch;
}

.empty-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 15px;
  border-radius: 999px;
  background: var(--card-inset);
  border: 1px solid var(--border);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-3);
}
.empty-badge::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

.empty-back {
  margin-top: 26px;
  font-size: 15px;
  font-weight: 600;
  color: var(--accent);
}
.empty-back:hover { text-decoration: underline; }

/* ── Collapsible sidebar ────────────────────────────────────────
   State lives on <html>: .nav-collapsed is set by an inline script in
   <head> so the rail never flashes open on load. .nav-anim is added one
   frame later by app.js, so only user-driven changes animate.          */
/* The toggle sits at the foot of the rail and behaves as a nav item, so
   it collapses to an icon with the rest of them. */
.nav-item--toggle {
  width: 100%;
  margin-top: 6px;
  font: inherit;
  font-weight: 500;
  text-align: left;
  background: none;
  cursor: pointer;
}
.nav-item--toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.sidebar { overflow-x: hidden; }
.profile-meta, .nav-item > span { white-space: nowrap; }
.nav-item { overflow: hidden; }

/* Rail tooltips — fixed-position so .sidebar's overflow can't clip them */
.rail-tip {
  position: fixed; z-index: 120;
  transform: translateY(-50%);
  background: var(--ink); color: #fff;
  padding: 7px 11px; border-radius: 8px;
  font-size: 13px; font-weight: 500; line-height: 1.3;
  white-space: nowrap;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.28);
  opacity: 0; pointer-events: none; transition: opacity .12s ease;
}
.rail-tip.is-visible { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .rail-tip { transition: none; } }

@media (min-width: 861px) {
  html.nav-collapsed { --sidebar-w: 120px; }

  .nav-collapsed .sidebar { padding-left: 28px; }
  .nav-collapsed .profile-card { padding: 6px; }
  .nav-collapsed .nav-item { padding-left: 16px; padding-right: 16px; }
  .nav-collapsed .profile-meta,
  .nav-collapsed .nav-item > span { opacity: 0; pointer-events: none; }
  .nav-collapsed .nav-item--toggle .ic { transform: scaleX(-1); }

  /* Animate only after the first paint, and only for people who want motion */
  @media (prefers-reduced-motion: no-preference) {
    .nav-anim .app { transition: grid-template-columns .3s cubic-bezier(.4, 0, .2, 1); }
    .nav-anim .sidebar,
    .nav-anim .profile-card,
    .nav-anim .nav-item { transition: padding .3s cubic-bezier(.4, 0, .2, 1); }
    .nav-anim .nav-item { transition: padding .3s cubic-bezier(.4, 0, .2, 1), background .15s ease, color .15s ease, box-shadow .15s ease; }
    .nav-anim .profile-meta,
    .nav-anim .nav-item > span { transition: opacity .18s ease; }
    .nav-anim .nav-item--toggle .ic { transition: transform .3s cubic-bezier(.4, 0, .2, 1); }
  }
}

/* Single-column layout has no rail to collapse */
@media (max-width: 860px) {
  .nav-item--toggle { display: none; }
}

/* ── Responsive ─────────────────────────────────────────────── */
@media (max-width: 1080px) {
  .quick-actions { grid-template-columns: repeat(2, 1fr); }
  /* Two columns leave the media panel too narrow well before the layout
     itself breaks, so the project card stacks earlier than the rest. */
  .pr-card { grid-template-columns: 1fr; }
  .pr-media { border-right: 0; border-bottom: 1px solid var(--border); }
}

@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; height: auto; overflow: visible; }

  /* The rail becomes a compact sticky bar so the work is the first thing on
     screen rather than a full screen of navigation. The nav itself folds
     into the bar behind a menu button and expands in flow when opened. */
  .sidebar {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: 8px;
    row-gap: 0;
    position: sticky;
    top: 0;
    z-index: 60;
    height: auto;
    overflow: visible;
    padding: 10px var(--gutter);
    background: var(--paper);
    border-bottom: 1px solid var(--border);
  }

  .profile-card { grid-column: 1; grid-row: 1; padding: 9px 13px; gap: 11px; }
  .avatar { width: 34px; height: 34px; font-size: 15px; }

  .nav-toggle { grid-column: 2; grid-row: 1; display: inline-flex; }

  .nav { grid-column: 1 / -1; grid-row: 2; }
  .nav--footer { grid-column: 1 / -1; grid-row: 3; margin-top: 0; }
  .nav, .nav--footer { display: none; }

  /* Open, the two nav groups read as one card, matching the surface the
     rest of the page sits on. The shared edge is the only divider. */
  .sidebar.is-open .nav,
  .sidebar.is-open .nav--footer {
    display: flex;
    background: var(--card);
    border: 1px solid var(--border);
  }
  /* .nav--footer also carries .nav, so the top-of-card rules exclude it. */
  .sidebar.is-open .nav:not(.nav--footer) {
    margin-top: 10px;
    padding: 7px 7px 5px;
    border-radius: var(--radius-md) var(--radius-md) 0 0;
  }
  .sidebar.is-open .nav--footer {
    margin-top: 0;
    padding: 5px 7px 7px;
    border-top: 0;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
  }
  .featured-grid { grid-template-columns: 1fr; }
  .split { grid-template-columns: 1fr; }
  .cs-grid { grid-template-columns: 1fr; }
  .pr-media { padding: 28px 22px; }
  .pr-body { padding: 26px 22px 28px; }
  .content { margin: 0 var(--gutter) var(--gutter); height: auto; overflow: visible; }
  .topbar { padding: 0 22px; }
  .content-body { overflow: visible; padding: 0 22px; }
  .content-inner { padding: 26px 0 32px; }
}

@media (max-width: 520px) {
  .quick-actions { grid-template-columns: 1fr; }
  .feature-card { align-items: flex-start; }
  /* Too narrow for mode, duration and label on one line, so the mode takes
     its own line and the duration sits under it with the label right-aligned. */
  .pr-mock-row { flex-wrap: wrap; row-gap: 5px; }
  /* The label loses a word rather than let the last chip drop to its own line. */
  .pr-mock-seg-word { display: none; }
  .pr-mock-mode { flex: 1 0 100%; }
  .pr-mock-flag { margin-left: auto; }
}

/* ── Wide figures ───────────────────────────────────────────────────────────
   Large product UI needs more room than the 820px reading column. A bleed
   figure widens to the full content column (max --content-max) so reconstructed
   screens stay legible, and collapses back in the single-column layout.      */
.case-bleed {
  width: min(var(--content-max), calc(100vw - var(--sidebar-w) - 136px));
  max-width: none;
  margin-left: 50%;
  transform: translateX(-50%);
}

/* ── Before / after comparison ──────────────────────────────────────────────
   Side by side on desktop, stacked panels on narrow screens.                 */
.compare { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
.compare-pane { min-width: 0; }
.compare-label {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 10px;
  font-size: 13px; font-weight: 600; color: var(--ink-2);
}
.compare-label::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--ink-3);
}
.compare-pane--after .compare-label::before { background: var(--accent); }
.compare-pane--after .compare-label { color: var(--ink); }
.compare-frame {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-inset);
  padding: 12px;
  overflow: hidden;
}

/* ── Compact request cards ──────────────────────────────────────────────── */
/* Client requests — the clients' own words, stated plainly and anonymously.
   Deliberately not a testimonial treatment: no portraits, no names, no pull
   quotes. The label says which part of the product the request was about. */
.reqhead {
  margin: 30px 0 16px;
  font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3);
}
.reqcards { display: grid; gap: 0; margin: 0; }
.reqcard {
  display: grid; grid-template-columns: 168px 1fr; gap: 24px;
  padding: 18px 0;
  border-top: 1px solid var(--border);
}
.reqcard:last-child { border-bottom: 1px solid var(--border); }
.reqcard-title { margin: 0; font-size: 15px; font-weight: 600; color: var(--ink); }
.reqcard-body { margin: 0; font-size: 16px; line-height: 1.55; color: var(--ink-2); }
.reqcard-body b { color: var(--ink); font-weight: 600; }
.reqcard-src { display: block; margin-top: 7px; font-size: 13px; color: var(--ink-3); }

/* ── Signal-grouping diagram ────────────────────────────────────────────────
   An explanatory portfolio diagram, drawn now to describe the thinking — not
   dressed up as a historical research artefact.                              */
/* Three groups with genuinely different amounts in them. Drawn as columns
   under a shared rule rather than as boxes, so a group holding one item reads
   as complete instead of half-empty — the asymmetry is the finding. */
.signals { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0 28px; margin: 26px 0 0; align-items: start; }
.signal {
  padding: 16px 0 0;
  border-top: 3px solid var(--sig, var(--ink-3));
}
.signal--happening { --sig: var(--accent); }
.signal--attention { --sig: #f5732b; }
.signal--changing  { --sig: #2f9e6b; }
.signal-kicker {
  margin: 0 0 14px;
  font-size: 13px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--sig);
}
.signal-items { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.signal-items li { font-size: 15px; font-weight: 500; color: var(--ink-2); }
.signal-items li span { display: block; font-size: 13px; font-weight: 400; color: var(--ink-3); }
.signals-foot {
  margin: 26px 0 0;
  font-size: 15px; line-height: 1.55; color: var(--ink-2);
}

/* ── Decision stories ───────────────────────────────────────────────────── */
.decisions { display: grid; gap: 44px; margin-top: 8px; }
.decision-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 12px; }
.decision-num {
  flex: none;
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--card-inset); border: 1px solid var(--border-strong);
  color: var(--ink-2);
  font-size: 13px; font-weight: 700;
  display: grid; place-items: center;
}
.decision-title { margin: 0; font-size: 18px; font-weight: 600; color: var(--ink); }

/* From → to pairing, used for the grouping and trend decisions */
.transform { display: grid; grid-template-columns: 1fr auto 1fr; gap: 16px; align-items: stretch; }
.transform-arrow { color: var(--ink-3); flex: none; align-self: center; }
.transform-arrow svg { width: 22px; height: 22px; display: block; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.transform-pane { min-width: 0; display: flex; flex-direction: column; }
.transform-cap { margin: 0 0 9px; font-size: 12px; font-weight: 600; color: var(--ink-3); }
.transform-pane--to .transform-cap { color: var(--accent); }
.transform-box {
  flex: 1;
  display: flex; flex-direction: column; justify-content: center;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-inset);
  overflow: hidden;
}

/* ── Multi-screen composition ───────────────────────────────────────────────
   A focal screen beside one or two supporting ones, for figures that have to
   show more than a single surface at once. Stacks on narrow screens.        */
.compose { display: grid; grid-template-columns: 1.6fr 1fr; gap: 18px; align-items: start; }
.compose--even { grid-template-columns: 1fr 1fr; }
.compose-pane { min-width: 0; }
.compose-side { display: grid; gap: 18px; min-width: 0; }

/* Screens that back up the focal one rather than compete with it: inset, set a
   little further down the page, and labelled more quietly. */
.compose-support { width: 80%; margin: 10px auto 0; }
.compose-support .compare-label { font-size: 12px; font-weight: 600; color: var(--ink-3); }
.compose-support .compare-label::before { width: 6px; height: 6px; background: var(--border-strong); }

/* ── Row of cropped screens ─────────────────────────────────────────────────
   One small frame per stage of a workflow. Widths stay equal so no stage
   reads as more important than the others.                                  */
.figrow { display: grid; gap: 16px; align-items: stretch; }
.figrow-item { display: flex; flex-direction: column; }
.figrow-item > .compare-frame { flex: 1; display: grid; align-content: center; }
.figrow--2 { grid-template-columns: repeat(2, 1fr); }
.figrow--3 { grid-template-columns: repeat(3, 1fr); }
.figrow-item { min-width: 0; }
.figrow-step {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 10px;
  font-size: 13px; font-weight: 600; color: var(--ink-2);
}
.figrow-step span {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-size: 11px; font-weight: 700; color: var(--ink-3);
  border: 1px solid var(--border-strong); background: var(--card);
}
.figrow-note { margin: 9px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-3); }

/* ── Sequence variant ───────────────────────────────────────────────────────
   For a row of screens that is read as ordered steps: the number is filled so
   the order registers before the screens do, and a small chevron sits in the
   gap between frames. Rotates to point down once the row stacks.           */
.figrow--flow .figrow-step, .compare--flow .figrow-step { color: var(--ink); }
.figrow--flow .figrow-step span, .compare--flow .figrow-step span {
  background: var(--ink); border-color: var(--ink); color: var(--card);
}
.figrow--flow .figrow-item, .compare--flow .compare-pane { position: relative; }
.figrow--flow .figrow-item + .figrow-item::before,
.compare--flow .compare-pane + .compare-pane::before {
  content: ""; position: absolute; z-index: 1;
  top: 50%; left: -13px; width: 8px; height: 8px;
  border-top: 1.5px solid var(--ink-3); border-right: 1.5px solid var(--ink-3);
  transform: translateY(-50%) rotate(45deg);
}
.compare--flow .compare-pane + .compare-pane::before { left: -14px; }
/* Where a sequence wraps onto a second row, the turn gets its own marker so the
   order still reads straight through. */
.flow-turn { display: flex; justify-content: center; margin: 0 0 16px; color: var(--ink-3); }
.flow-turn svg { display: block; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }

@media (max-width: 860px) {
  .compose, .compose--even { grid-template-columns: 1fr; }
  .figrow--2, .figrow--3 { grid-template-columns: 1fr; }
  .compose-support { width: 100%; }
  /* Stacked, the sequence runs downwards, so the connector turns with it. */
  .figrow--flow .figrow-item + .figrow-item::before,
  .compare--flow .compare-pane + .compare-pane::before {
    top: -14px; left: 50%; transform: translateX(-50%) rotate(135deg);
  }
  .compare--flow .compare-pane + .compare-pane::before { top: -19px; }
}

/* ── Iteration strip ────────────────────────────────────────────────────── */
/* Explorations are stacked rather than tiled: a three-across strip would shrink
   the reconstructed UI below the point where its own labels stay readable. */
.iterations { display: grid; gap: 40px; margin-top: 8px; }
.iteration { min-width: 0; }
.iteration-frame {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-inset);
  padding: 12px;
  overflow: hidden;
}
.iteration-label {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin: 0 0 12px; font-size: 15px; line-height: 1.5; color: var(--ink-2);
}
.iteration-label strong {
  flex: none;
  padding: 4px 12px; border-radius: 999px;
  border: 1px solid var(--border-strong); background: var(--card-inset);
  color: var(--ink); font-weight: 600; font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.iteration--final .iteration-frame { border-color: var(--accent); }
.iteration--final .iteration-label strong { color: var(--accent); border-color: #bcd0f7; background: #eef3fe; }

/* ── Numbered annotations beside a large screen ─────────────────────────── */
.annolist { list-style: none; margin-top: 20px; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 12px 40px; }
.annolist li { display: flex; align-items: center; gap: 10px; font-size: 15px; line-height: 1.45; color: var(--ink-2); }
.annolist .anno-n {
  flex: none;
  min-width: 22px; height: 22px;
  border-radius: 6px;
  background: var(--card-inset); border: 1px solid var(--border-strong);
  color: var(--ink-3);
  font-size: 11px; font-weight: 700;
  display: grid; place-items: center;
  font-variant-numeric: tabular-nums;
}
.annolist strong { color: var(--ink); font-weight: 600; }

/* ── Restrained evidence layout (feedback, not testimonials) ────────────── */
.evidence { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 0; }
.evidence li {
  display: grid; grid-template-columns: 132px 1fr; gap: 20px;
  padding: 13px 0;
  border-top: 1px solid var(--border);
  font-size: 15px; line-height: 1.5; color: var(--ink-2);
}
.evidence li:last-child { border-bottom: 1px solid var(--border); }
.evidence-who { font-size: 13px; font-weight: 600; color: var(--ink-3); }

/* ── Results slot: metrics land here once verified ──────────────────────── */
/* One or two verified figures drop in here as a .stats grid when confirmed. */
.results-pending { margin: 0; }

/* ── Prototype provenance label ─────────────────────────────────────────── */
.recreated {
  display: inline-flex; align-items: center; gap: 7px;
  margin-bottom: 12px;
  padding: 5px 11px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--card-inset);
  font-size: 12px; font-weight: 600; color: var(--ink-2);
}
.recreated::before {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--ink-3);
}

@media (max-width: 900px) {
  .reqcard, .theme { grid-template-columns: 1fr; gap: 6px; }
  .signals { grid-template-columns: 1fr; gap: 0; }
  .signal { padding-bottom: 22px; }
  .annolist { grid-template-columns: 1fr; }
}
@media (max-width: 860px) {
  .case-bleed { width: 100%; margin-left: 0; transform: none; }
  .compare { grid-template-columns: 1fr; gap: 26px; }
  .transform { grid-template-columns: 1fr; }
  .transform-arrow { justify-self: center; transform: rotate(90deg); }
  .evidence li { grid-template-columns: 1fr; gap: 6px; }
}

/* Anchors hotspot percentages to the screen itself, not the whole figure */
.anno-frame { position: relative; }

/* Lightbox: a reconstructed screen opens as live markup at 1:1, not a bitmap */
.lightbox .lb-html {
  display: none;
  max-width: 95vw; max-height: 92vh;
  overflow: auto;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
}

/* Zoom controls sit on the screen they belong to, not the whole figure */
.compare-frame, .iteration-frame, .transform-box { position: relative; }
.compare-frame:hover .figure-zoom,
.iteration-frame:hover .figure-zoom,
.transform-box:hover .figure-zoom,
.anno-frame:hover .figure-zoom { opacity: 1; }

/* Remembered feedback, paraphrased. No quote marks, no attribution, no faces —
   the presentation has to signal 'observation', not 'testimonial'. */
.themes { display: grid; gap: 0; margin: 22px 0 0; }
.theme {
  display: grid; grid-template-columns: 224px 1fr; gap: 24px;
  padding: 16px 0;
  border-top: 1px solid var(--border);
}
.theme:last-child { border-bottom: 1px solid var(--border); }
.theme-title { margin: 0; font-size: 15px; font-weight: 600; color: var(--ink); }
.theme-body { margin: 0; font-size: 15px; line-height: 1.55; color: var(--ink-2); }

/* Caption for a whole section rather than a single figure */
.section-cap { margin: 6px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-3); text-align: center; }

/* ── Scaled stage (shared by every reconstructed product screen) ─────────────
   A reconstruction is laid out at its true pixel width, then scaled to fit the
   column it sits in — case.js measures both with a ResizeObserver. Without JS
   the stage falls back to a controlled horizontal scroll. Used by the
   BettorGames (.bg-*) and Once For All (.ofa-*) component sets.            */
.bg-stage { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; }
.bg-stage > * { transform-origin: top left; }
.bg-fit { position: relative; overflow: hidden; }
.bg-fit > * { transform-origin: top left; }
/* Below the legibility floor the screen no longer fits: pan it instead. */
.bg-stage { cursor: zoom-in; }
.bg-stage.is-panned { cursor: ew-resize; }
.bg-stage:not(.is-panned) { overflow: hidden; }

/* ── My story ───────────────────────────────────────────────────────────────
   A personal page rather than a case study, so it borrows the case study's
   reading column and prose scale (.case-h / .case-p / .case-callout) and adds
   only what the story itself needs: a hero that carries a portrait, a working
   model, and a strip of work fragments. Nothing here is decorative — every
   block is either the words or a picture of the thinking.                   */
.story { max-width: 820px; margin-inline: auto; }

/* Hero — text leads, portrait sits beside it rather than above it, so the page
   opens as a piece of writing and not as a profile card. */
.story-hero {
  display: grid;
  grid-template-columns: 1fr 216px;
  gap: 46px;
  align-items: start;
  padding-bottom: 42px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 52px;
}
.story-eyebrow {
  margin: 0 0 16px;
  font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3);
}
/* Lighter than a case title: this is a name for a page, not a headline. */
.story-title {
  margin: 0 0 22px;
  font-size: clamp(38px, 5vw, 58px);
  font-weight: 400;
  letter-spacing: -0.03em;
  line-height: 1.02;
  color: var(--ink);
  text-wrap: balance;
}
/* The break is set by hand for the two-line desktop title. Narrower than that
   it fights the column, so it is dropped and the balancer takes over. The
   source keeps a space after the tag, which the line start swallows on
   desktop and which keeps the words apart once the break is gone. */
@media (max-width: 760px) { .story-br { display: none; } }
.story-lede {
  margin: 0;
  font-size: clamp(18px, 2.1vw, 21px);
  line-height: 1.5;
  color: var(--ink-2);
}
.story-lede strong { color: var(--ink); font-weight: 600; }

.story-portrait { margin: 0; }
/* The portrait asset carries a lot of graphic decoration around the edges.
   Cropped in, it reads as a portrait on a quiet page instead of as an
   illustration; --pz is the only number to change to pull back out. */
.story-portrait-frame {
  --pz: 1.34;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  background: var(--card-inset);
}
.story-portrait-frame img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  transform: scale(var(--pz));
  transform-origin: 50% 40%;
}
.story-portrait figcaption {
  margin-top: 12px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink-3);
}
.story-portrait figcaption b { display: block; font-weight: 600; color: var(--ink-2); }

/* The questions behind a screen. Ruled rows rather than bullets — they are a
   checklist Cem actually runs, so they should read as a list of work. */
.qlist { list-style: none; margin: 22px 0 0; padding: 0; }
.qlist li {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 14px;
  padding: 13px 0;
  border-top: 1px solid var(--border);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink);
}
.qlist li:last-child { border-bottom: 1px solid var(--border); }
.qlist .qn {
  font-size: 13px; font-weight: 600;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  padding-top: 3px;
}

/* ── Working model ──────────────────────────────────────────────────────────
   Four stages on one continuous line. The only thing that changes across the
   row is the weight of the marker: faint at ambiguity, solid at delivery. That
   progression is the whole idea, so it does not need a box or an arrow.     */
.model { margin: 26px 0 0; }
.model-track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}
.model-stage {
  position: relative;
  padding: 28px 20px 0 0;
}
/* Segments meet edge to edge, so the four rules read as one line. */
.model-stage::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: var(--border-strong);
}
.model-stage::after {
  content: "";
  position: absolute;
  top: -4px; left: 0;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--mk, var(--ink-3));
}
.model-stage--1 { --mk: #cbc9be; }
.model-stage--2 { --mk: #a3a5ab; }
.model-stage--3 { --mk: #6c6f77; }
/* Delivery is the only filled marker: the point where the work becomes real. */
.model-stage--4 { --mk: var(--accent); }
.model-stage--4::after { background: var(--accent); }

.model-n {
  display: block;
  margin-bottom: 7px;
  font-size: 12px; font-weight: 600; letter-spacing: .08em;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.model-name { margin: 0 0 7px; font-size: 16px; font-weight: 600; color: var(--ink); }
.model-desc { margin: 0; font-size: 14px; line-height: 1.5; color: var(--ink-2); }
/* Left-aligned: it is an aside about the diagram, not a photo caption. */
.model > figcaption { text-align: left; margin-top: 22px; }

/* Stacked, the line turns and runs down the left edge. */
@media (max-width: 700px) {
  .model-track { grid-template-columns: 1fr; }
  .model-stage { padding: 0 0 22px 26px; }
  .model-stage:last-child { padding-bottom: 0; }
  .model-stage::before { top: 0; bottom: 0; left: 4px; right: auto; width: 1px; height: auto; }
  /* Stop the rail at the last marker instead of trailing past the text. */
  .model-stage:last-child::before { bottom: auto; height: 6px; }
  .model-stage::after { top: 2px; left: 0; }
}

/* ── Work fragments ─────────────────────────────────────────────────────────
   Deliberately cropped: these are pieces of real project artefacts, shown at
   the size of a glance rather than as evidence. Anyone who wants the whole
   thing has the case studies. The crop point is set per fragment with --x/--y,
   both relative to the frame, so the framing holds at every width.          */
.frags {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin: 26px 0 0;
}
.frag { margin: 0; min-width: 0; }
/* Square, not letterboxed: at 4:3 the crops skimmed the artefacts rather than
   framing them. --x/--y are both percentages of the frame, so a change of
   aspect ratio here means recomputing --y on each image in the markup. */
.frag-frame {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--card-inset);
}
.frag-frame img {
  position: absolute;
  width: 340%;
  max-width: none;
  left: var(--x, -90%);
  top: var(--y, -60%);
  display: block;
}
.frag figcaption { margin-top: 10px; font-size: 13px; line-height: 1.4; color: var(--ink-3); }
.frag figcaption b { display: block; font-weight: 600; color: var(--ink-2); }

@media (max-width: 860px) { .frags { grid-template-columns: repeat(2, 1fr); } }
/* Stays two across even on a phone: stacked, four crops become a gallery
   rather than the glance they are meant to be. */
@media (max-width: 340px) { .frags { grid-template-columns: 1fr; } }

/* Closing links back into the work */
.story-next { margin-top: 8px; padding-top: 36px; border-top: 1px solid var(--border); }
.story-next-label {
  margin: 0 0 4px;
  font-size: 12px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3);
}
.story-links { display: grid; margin: 0; }
.story-link {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 20px;
  padding: 18px 0;
  border-bottom: 1px solid var(--border);
}
.story-link:first-child { border-top: 1px solid var(--border); }
.story-link-title {
  display: block;
  font-size: 18px; font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  transition: color .15s ease;
}
.story-link:hover .story-link-title { color: var(--accent); }
/* Year and theme, in the same dot-and-label language as the case-study index,
   so a row reads as a recommendation with provenance rather than a link. */
.story-link-meta {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 6px 10px;
  margin-top: 6px;
  font-size: 13px;
  color: var(--ink-3);
}
.story-link-year { font-variant-numeric: tabular-nums; }
.story-link-tag { display: inline-flex; align-items: center; gap: 6px; }
/* Separator between the two, drawn rather than typed so it never wraps alone */
.story-link-year + .story-link-tag::before {
  content: "";
  width: 1px; height: 11px;
  background: var(--border-strong);
  margin-right: 4px;
}
.story-link-why { display: block; margin-top: 8px; font-size: 15px; line-height: 1.5; color: var(--ink-2); }
.story-link-go { font-size: 14px; font-weight: 600; color: var(--ink-3); white-space: nowrap; }
.story-link:hover .story-link-go { color: var(--accent); }

@media (max-width: 760px) {
  .story-hero { grid-template-columns: 1fr; gap: 32px; }
  /* Portrait ahead of the words would make it a profile page, so it stays
     after them and shrinks to a size that reads as an aside. */
  .story-portrait { max-width: 176px; }
}

/* ── Photography ────────────────────────────────────────────────────────────
   A justified gallery: every figure keeps its native aspect ratio, and the
   row works out the heights. Each figure grows in proportion to its own
   ratio (--ar = width / height), so a row of mixed portraits and landscapes
   lands on one shared height without a single image being cropped. Rows are
   composed by hand rather than generated, which is why the item counts and
   the inset row vary down the page. */
.pg-intro { max-width: 720px; margin: 0 0 40px; }
.pg-title {
  margin: 0 0 20px;
  font-size: clamp(32px, 4.4vw, 52px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.06;
  color: var(--ink);
}
.pg-lede { margin: 0; font-size: 17px; line-height: 1.65; color: var(--ink-2); }

.pg-hero { margin: 0 0 60px; }
.pg-hero-frame {
  aspect-ratio: 24 / 10;
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  background: var(--card-inset);
}
.pg-hero-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
.pg-hero figcaption { margin-top: 12px; font-size: 13px; color: var(--ink-3); }

.pg-section { margin: 0 0 60px; }
.pg-section-head { max-width: 620px; margin: 0 0 22px; }
.pg-section-head .case-h { margin-bottom: 10px; }
.pg-section-note { margin: 0; font-size: 15px; line-height: 1.55; color: var(--ink-2); }

.pg-row { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 16px; }
.pg-row:last-child { margin-bottom: 0; }
/* One narrower row per page keeps the grid from settling into a single
   repeating measure. */
.pg-row--inset { max-width: 880px; margin-inline: auto; }

.pg-fig { flex-grow: calc(var(--ar) * 100); flex-shrink: 1; flex-basis: 0; min-width: 0; margin: 0; }

.pg-frame {
  display: block;
  width: 100%;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--card-inset);
  cursor: zoom-in;
  box-shadow: var(--shadow-card);
}
.pg-frame img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform .5s cubic-bezier(.4, 0, .2, 1);
}
.pg-frame:hover img, .pg-frame:focus-visible img { transform: scale(1.02); }
.pg-frame:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.pg-cap { margin-top: 10px; }
.pg-cap-text { display: block; font-size: 13px; line-height: 1.45; color: var(--ink-2); }
.pg-cap-place {
  display: block;
  margin-top: 3px;
  font-size: 12px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3);
}

/* ── Photograph viewer ──────────────────────────────────────────────────────
   Opens the same file at full size; there is no larger original to fetch. */
.pg-lb {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  padding: 40px 72px;
  background: rgba(12, 13, 16, .93);
}
.pg-lb-stage { display: flex; flex-direction: column; align-items: center; gap: 14px; margin: 0; max-height: 100%; }
.pg-lb-stage img { max-width: 100%; max-height: calc(100vh - 140px); object-fit: contain; border-radius: 6px; }
.pg-lb-cap { max-width: 620px; text-align: center; font-size: 13px; line-height: 1.5; color: rgba(255, 255, 255, .68); }
.pg-lb-btn {
  position: absolute;
  display: grid; place-items: center;
  width: 44px; height: 44px;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 50%;
  background: rgba(255, 255, 255, .06);
  color: #fff;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.pg-lb-btn:hover { background: rgba(255, 255, 255, .16); border-color: rgba(255, 255, 255, .4); }
.pg-lb-btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.pg-lb-btn svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.pg-lb-close { top: 22px; right: 22px; }
.pg-lb-prev { left: 18px; top: 50%; transform: translateY(-50%); }
.pg-lb-next { right: 18px; top: 50%; transform: translateY(-50%); }
.pg-lb-count {
  position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%);
  font-size: 12px; letter-spacing: .08em; font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, .5);
}

/* Below the justified width the flex maths starts producing slivers, so the
   rows become a plain two-up and then a single column. Aspect ratio moves
   onto the frame to keep the images uncropped. */
@media (max-width: 900px) {
  .pg-row { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .pg-row--inset { max-width: none; }
  .pg-frame { aspect-ratio: var(--ar); }
  .pg-frame img { height: 100%; object-fit: cover; }
  .pg-hero-frame { aspect-ratio: 16 / 10; }
  .pg-hero { margin-bottom: 44px; }
  .pg-section { margin-bottom: 44px; }
}

@media (max-width: 560px) {
  .pg-row { grid-template-columns: 1fr; }
  .pg-hero-frame { aspect-ratio: 4 / 3; }
  .pg-lb { padding: 16px; }
  .pg-lb-prev { left: 8px; }
  .pg-lb-next { right: 8px; }
  .pg-lb-stage img { max-height: calc(100vh - 170px); }
}

@media (prefers-reduced-motion: reduce) {
  .pg-frame img { transition: none; }
  .pg-frame:hover img, .pg-frame:focus-visible img { transform: none; }
}

/* ── Source-order correction ────────────────────────────────────────────────
   .theme is defined further up the file than the 900px block that collapses
   it to one column, so the two-column rule won its own override and the
   feedback themes on Case 04 pushed the page sideways on a phone. Re-declared
   here, after both, so the narrow layout applies.                          */
@media (max-width: 900px) {
  .theme { grid-template-columns: 1fr; gap: 6px; }
}

/* ── Small-screen notice ────────────────────────────────────────────────────
   The case studies carry interactive prototypes and full product screens that
   a phone cannot show honestly, so below 720px the site hands the visitor a
   notice instead. The page itself stays in the document underneath: the
   notice is an overlay, not a replacement, so the content is still there for
   anyone who continues past it and for crawlers reading the markup.
   To change where it starts, edit the one breakpoint below. To retire it,
   delete this block and the mobile-notice section of app.js.              */
.gate {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 200;
  padding: 28px 22px;
  background: var(--paper);
  overflow-y: auto;
  overscroll-behavior: contain;
}

@media (max-width: 720px) {
  .gate { display: grid; align-content: center; justify-items: start; }
  html.gate-open, html.gate-open body { overflow: hidden; }
}

.gate-inner {
  width: 100%;
  max-width: 420px;
  margin-inline: auto;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 30px 26px 26px;
}

.gate-id { display: flex; align-items: center; gap: 12px; margin-bottom: 26px; }
.gate-id .avatar { width: 42px; height: 42px; font-size: 18px; }
.gate-name { font-weight: 600; font-size: 15px; color: var(--ink); line-height: 1.25; }
.gate-role { font-size: 13px; color: var(--ink-3); line-height: 1.25; }

/* A paragraph rather than a heading: the page already has its own h1 and the
   notice should not compete with it in the document outline. */
.gate-title {
  margin: 0 0 14px;
  font-size: 27px;
  line-height: 1.2;
  letter-spacing: -0.015em;
  font-weight: 600;
  color: var(--ink);
}
.gate-text { margin: 0 0 12px; font-size: 15px; line-height: 1.55; color: var(--ink-2); }
.gate-text:last-of-type { margin-bottom: 26px; }

.gate-actions { display: grid; gap: 9px; }

.gate-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  min-height: 46px;
  padding: 0 18px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  background: var(--card-inset);
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  font-size: 15px;
  cursor: pointer;
  appearance: none;
  text-align: center;
  /* The last-resort state prints the address in here, so let it wrap
     rather than run out of the button. */
  padding-block: 12px;
  overflow-wrap: anywhere;
}
.gate-btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.gate-btn .ic {
  width: 18px; height: 18px; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.9;
  stroke-linecap: round; stroke-linejoin: round;
}

.gate-foot {
  margin: 22px 0 0;
  text-align: center;
  font-size: 13px;
  color: var(--ink-3);
}
.gate-foot button {
  appearance: none; border: 0; background: none; padding: 0;
  font: inherit; color: var(--ink-3); cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.gate-foot button:hover { color: var(--ink-2); }

/* ── Password gate on the case studies ──────────────────────────────────────
   Stands in the content column where a case study would be. The card is
   deliberately quiet: a locked door is not the interesting part of the visit,
   so it states what is behind it and gets out of the way.                   */
.lock {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 62vh;
  padding: 40px 20px;
}

.lock-card {
  width: 100%;
  max-width: 460px;
  padding: 38px 36px 34px;
  border-radius: var(--radius-lg);
  background: var(--card);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  text-align: center;
}

.lock-icon {
  width: 58px;
  height: 58px;
  margin: 0 auto 20px;
  border-radius: 18px;
  display: grid;
  place-items: center;
  background: var(--card-inset);
  border: 1px solid var(--border);
}
.lock-icon svg {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.lock-eyebrow {
  margin: 0 0 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--accent);
}

.lock-title {
  margin: 0 0 12px;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
}

.lock-text {
  margin: 0 0 12px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-2);
}
.lock-text:last-of-type { margin-bottom: 26px; }

.lock-form { display: grid; gap: 9px; text-align: left; }

/* The label is for screen readers and for anyone who has zoomed in far enough
   that the heading has scrolled away; visually the field speaks for itself. */
.lock-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-2);
}

.lock-input {
  width: 100%;
  min-height: 46px;
  padding: 0 15px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong);
  background: var(--card-inset);
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  appearance: none;
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.lock-input:focus {
  outline: none;
  background: var(--card);
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
}

.lock-error {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: #b42318;
}

.lock-btn {
  min-height: 46px;
  margin-top: 3px;
  padding: 0 18px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  appearance: none;
  transition: background .15s ease, border-color .15s ease;
}
.lock-btn:hover { background: #1d4ed8; border-color: #1d4ed8; }
.lock-btn:disabled { opacity: .65; cursor: default; }

.lock-note {
  margin: 0;
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  background: var(--card-inset);
  border: 1px solid var(--border);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
  text-align: left;
}
.lock-note a { color: var(--accent); font-weight: 600; }

.lock-foot {
  margin: 20px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-3);
}
.lock-foot a { color: var(--ink-2); text-decoration: underline; text-underline-offset: 3px; }
.lock-foot a:hover { color: var(--ink); }

.lock-back {
  display: inline-block;
  margin-top: 18px;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
}
.lock-back:hover { text-decoration: underline; }

/* The badge on a card that leads to a locked page, so the password is not a
   surprise that arrives after the click. */
.cs-lock {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--card-inset);
  border: 1px solid var(--border);
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-3);
}
.cs-lock svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Same badge on the two featured cards at home, where it sits under the
   description rather than in a row of tags. */
.cs-lock--inline { margin-top: 12px; }

/* ── Analytics consent ──────────────────────────────────────────────────────
   A question, asked once, at the foot of the page. It sits below the
   small-screen notice in the stack, so on a phone the notice is still the
   first thing answered.                                                     */
.cc {
  position: fixed;
  left: 20px;
  right: 20px;
  bottom: 20px;
  z-index: 150;
  display: flex;
  justify-content: center;
  pointer-events: none;
}

.cc-inner {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 20px;
  max-width: 640px;
  padding: 16px 20px;
  border-radius: var(--radius-md);
  background: var(--card);
  border: 1px solid var(--border-strong);
  box-shadow: 0 4px 24px rgba(20, 24, 29, 0.10);
}

.cc-text {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-2);
}

.cc-actions { display: flex; gap: 8px; flex: none; }

.cc-btn {
  min-height: 36px;
  padding: 0 16px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  background: var(--card);
  color: var(--ink-2);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  appearance: none;
  white-space: nowrap;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.cc-btn:hover { background: var(--card-inset); color: var(--ink); }
.cc-btn--primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.cc-btn--primary:hover { background: #1d4ed8; border-color: #1d4ed8; color: #fff; }

/* Narrow enough that the two buttons would crowd the sentence: stack them. */
@media (max-width: 700px) {
  .cc-inner { flex-direction: column; align-items: stretch; gap: 14px; }
  .cc-actions { justify-content: flex-end; }
}

/* The way back to the question is a button, but it belongs to the rail and
   should carry none of a button's own styling. */
.cc-link {
  appearance: none;
  border: 0;
  background: none;
  width: 100%;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* ── Footer toys ────────────────────────────────────────────────
   A small toy at the end of a case study, always below the
   Previous/Next links so the reflection still closes the argument, and
   always the same panel so the toys read as one running habit rather
   than four separate experiments. Nothing any of them does is stored,
   scored or sent anywhere.

   Each toy's script un-hides its own panel, so with JavaScript off the
   page simply ends at the links. The explicit [hidden] rule is required
   because .toy sets its own display, which the UA stylesheet's [hidden]
   would otherwise lose to. */
.toy {
  display: block;
  margin: 56px 0 0;
  padding: 30px 32px 32px;
  background: var(--card-inset);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.toy[hidden] { display: none; }

.toy-eyebrow {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.toy-title {
  margin: 0 0 14px;
  font-size: 21px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.toy-copy {
  margin: 0 0 26px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-2);
}

/* ── Case 02: three reels, nothing at stake ─────────────────── */

.slot-machine {
  --slot-cell: 66px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 22px;
}

.slot-reels {
  display: flex;
  gap: 8px;
  padding: 10px;
  background: var(--card);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: inset 0 1px 3px rgba(20, 24, 29, 0.05);
  transition: box-shadow .35s ease;
}
/* The only thing three-of-a-kind does. */
.slot-reels.is-hit { box-shadow: inset 0 1px 3px rgba(20, 24, 29, 0.05), 0 0 0 3px rgba(37, 99, 235, 0.18); }

.slot-reel {
  position: relative;
  width: var(--slot-cell);
  height: var(--slot-cell);
  overflow: hidden;
  background: var(--card-inset);
  border: 1px solid var(--border);
  border-radius: 10px;
}
/* Softens the cut at the top and bottom of the window so symbols read as
   arriving from somewhere rather than being clipped. */
.slot-reel::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(250, 249, 245, 0.92) 0%, rgba(250, 249, 245, 0) 26%,
    rgba(250, 249, 245, 0) 74%, rgba(250, 249, 245, 0.92) 100%);
}

.slot-strip { will-change: transform; }

.slot-cell {
  display: grid;
  place-items: center;
  height: var(--slot-cell);
}
.slot-cell svg {
  width: 30px;
  height: 30px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.slot-spin {
  flex: none;
  height: 44px;
  padding: 0 26px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  appearance: none;
  transition: background .15s ease, opacity .15s ease;
}
.slot-spin:hover { background: #2b2f37; }
.slot-spin:disabled { opacity: 0.45; cursor: default; }

.slot-result {
  margin: 18px 0 0;
  min-height: 21px;          /* holds the line so a spin cannot shift the page */
  text-align: center;
  font-size: 14px;
  color: var(--ink-3);
}

/* Side by side the reels and the button crowd each other on a phone. */
@media (max-width: 560px) {
  .toy { padding: 24px 20px 26px; }
  .slot-machine { flex-direction: column; gap: 18px; }
}

/* ── Case 03: assess yourself ───────────────────────────────────
   Three sliders in the voice of the assessment tool the case study is
   about, with the reader in the assessed seat. The answers exist only
   in this DOM: nothing is posted, persisted or counted, which the copy
   says plainly before the first question rather than after the last. */
.review-form { margin: 0; }

.review-q {
  display: grid;
  grid-template-columns: 1fr minmax(180px, 240px);
  align-items: center;
  gap: 10px 24px;
  padding: 14px 0;
  border-top: 1px solid var(--border);
}
.review-q:first-child { border-top: 0; padding-top: 0; }

.review-label {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.review-hint {
  display: block;
  margin-top: 2px;
  font-size: 14px;
  font-weight: 400;
  color: var(--ink-2);
}

.review-scale { display: flex; align-items: center; gap: 12px; }

/* Marking your own homework should feel like one drag, not a form. */
.review-range {
  flex: 1;
  min-width: 0;
  appearance: none;
  height: 4px;
  border-radius: 999px;
  background: var(--border-strong);
  cursor: pointer;
}
.review-range::-webkit-slider-thumb {
  appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 0;
  background: var(--ink);
  cursor: pointer;
}
.review-range::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 0;
  background: var(--ink);
  cursor: pointer;
}
.review-range:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.review-value {
  flex: none;
  width: 26px;
  text-align: center;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.review-submit {
  margin-top: 22px;
  height: 44px;
  padding: 0 26px;
  border: 0;
  border-radius: 999px;
  background: var(--ink);
  color: #fff;
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  appearance: none;
  transition: background .15s ease;
}
.review-submit:hover { background: #2b2f37; }

/* ── The result ── */
.review-result { margin-top: 26px; padding-top: 24px; border-top: 1px solid var(--border); }
.review-result[hidden] { display: none; }

.review-bar { display: grid; grid-template-columns: 96px 1fr 26px; align-items: center; gap: 14px; margin-bottom: 10px; }
.review-bar-name { font-size: 14px; color: var(--ink-2); }
.review-bar-track { height: 10px; border-radius: 999px; background: var(--border); overflow: hidden; }
.review-bar-fill {
  display: block;
  width: 0;
  height: 100%;
  border-radius: 999px;
  background: var(--accent);
  transition: width .7s cubic-bezier(.2,.8,.2,1);
}
.review-bar:nth-child(2) .review-bar-fill { background: var(--orange); }
.review-bar:nth-child(3) .review-bar-fill { background: var(--pink); }
.review-bar-value { font-size: 14px; font-weight: 600; color: var(--ink); text-align: right; font-variant-numeric: tabular-nums; }

.review-score {
  margin: 22px 0 6px;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.review-score span { font-size: 15px; font-weight: 500; color: var(--ink-3); }

.review-verdict { margin: 0 0 18px; font-size: 15px; line-height: 1.6; color: var(--ink-2); }

/* The bars say this visually; a screen reader reading the live region
   gets the same figures as words, ahead of the verdict. */
.review-readout {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.review-again {
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
.review-again:hover { text-decoration: underline; }

/* The two-column question row has nowhere to go on a phone. */
@media (max-width: 620px) {
  .review-q { grid-template-columns: 1fr; gap: 12px; }
  .review-bar { grid-template-columns: 78px 1fr 26px; gap: 10px; }
}

@media (prefers-reduced-motion: reduce) {
  .review-bar-fill { transition: none; }
}

/* ── Case 01: hit something ─────────────────────────────────────
   A hammer, a nail and a plank at the end of a case study about
   verifying construction compliance. The marker sweeps on a CSS
   animation rather than a JavaScript loop, and its position is read
   off the DOM at the moment of the click, so nothing runs between
   swings. There is no way to lose: a mistimed swing is simply worth
   less, and the nail only ever goes in. */
.hammer { display: flex; flex-direction: column; align-items: center; }

/* No card behind the scene: the shapes sit straight on the panel, the
   way the reels sit on theirs. */
.hammer-stage {
  appearance: none;
  display: block;
  width: 100%;
  max-width: 380px;
  padding: 4px 16px 8px;
  border: 0;
  border-radius: var(--radius-md);
  background: none;
  cursor: pointer;
  font: inherit;
}
.hammer-stage:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.hammer-stage:disabled { cursor: default; }

.hammer-scene { display: block; width: 100%; height: auto; }

/* Same palette as the reels on Case 02, so the two toys look related. */
.hammer-plank { fill: #e2c9a1; }
.hammer-plank-face { fill: #eddcc0; }
.hammer-knot { fill: #cfb287; }
.hammer-shaft { fill: var(--ink-3); }
.hammer-nailhead { fill: var(--pink); }
.hammer-handle { fill: var(--orange); }
.hammer-head { fill: var(--blue); }

/* A little overshoot on the way in, so the nail lands rather than slides. */
.hammer-nail { transition: transform .18s cubic-bezier(.25,1.5,.45,1); }

/* Rest is raised and to the right; the swing brings it down onto the
   nail. Rotating about the foot of the handle is what sells it. */
.hammer-tool {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  transform: rotate(22deg);
  transition: transform .13s cubic-bezier(.3,1.3,.5,1);
}
.hammer-tool.is-swinging { transform: rotate(-54deg); }

.hammer-spark { opacity: 0; }
.hammer-spark.is-lit { opacity: 1; transition: opacity .05s linear; }
.hammer-spark-line { stroke: var(--yellow); stroke-width: 4; stroke-linecap: round; fill: none; }
.hammer-spark-dot { fill: var(--pink); }

[data-hammer-shake] { transition: transform .06s ease-out; }
[data-hammer-shake].is-struck { transform: translateY(3px); }

/* ── The timing meter ── */
.hammer-meter {
  position: relative;
  display: block;
  height: 8px;
  margin-top: 14px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}
/* .hammer-meter sets its own display, so the UA stylesheet's [hidden]
   would lose to it and the track would stay on screen after the nail is
   home. Same trap as .toy[hidden]. */
.hammer-meter[hidden] { display: none; }

.hammer-zone {
  position: absolute;
  left: 41%;
  width: 18%;
  top: 0;
  bottom: 0;
  background: var(--accent);
  opacity: 0.28;
}
.hammer-marker {
  position: absolute;
  top: -3px;
  left: 0;
  width: 6px;
  height: 14px;
  border-radius: 3px;
  background: var(--ink);
  animation: hammer-sweep 1.15s linear infinite alternate;
}
/* `left` rather than a transform: a percentage translateX would resolve
   against the marker's own 6px width, not the track's. */
@keyframes hammer-sweep {
  from { left: 0; }
  to   { left: calc(100% - 6px); }
}

.hammer-result {
  margin: 16px 0 0;
  min-height: 21px;
  text-align: center;
  font-size: 14px;
  color: var(--ink-3);
}
.hammer-result strong { color: var(--ink); font-weight: 600; }

.hammer-again {
  margin-top: 10px;
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
.hammer-again:hover { text-decoration: underline; }
.hammer-again[hidden] { display: none; }

/* No sweeping marker to time, so every swing lands square instead. */
@media (prefers-reduced-motion: reduce) {
  .hammer-marker { animation: none; left: calc(50% - 3px); }
  .hammer-nail, .hammer-tool, [data-hammer-shake] { transition: none; }
}

/* ── Case 04: tidy the dashboard ────────────────────────────────
   Six tiles that start scattered and click into a grid. The grid does
   the placing, so each tile only ever carries a scatter transform and
   clicking clears it. Nothing can be put in the wrong place and there is
   no timer, which is the whole point: the satisfaction is the reward. */
.tidy { display: flex; flex-direction: column; align-items: center; }

.tidy-stage {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  width: 100%;
  max-width: 380px;
  padding: 22px 4px;
}

.tidy-tile {
  appearance: none;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 7px;
  aspect-ratio: 16 / 11;
  padding: 9px;
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  background: var(--card);
  box-shadow: var(--shadow-pill);
  cursor: pointer;
  font: inherit;
  transform: translate(var(--dx), var(--dy)) rotate(var(--r));
  transition: transform .5s cubic-bezier(.2, 1.25, .35, 1), box-shadow .2s ease;
}
.tidy-tile:hover { box-shadow: 0 1px 2px rgba(20, 24, 29, .08), 0 6px 16px rgba(20, 24, 29, .1); }
.tidy-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* Placed: square to the grid, quiet, and out of the way of the rest. */
.tidy-tile.is-placed {
  transform: none;
  cursor: default;
  box-shadow: var(--shadow-pill);
}

/* A scattered tile should overlap its neighbours; a placed one should not. */
.tidy-tile { z-index: 2; }
.tidy-tile.is-placed { z-index: 1; }

.tidy-cap {
  width: 46%;
  height: 5px;
  border-radius: 999px;
  background: var(--border-strong);
}
.tidy-bars {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 30px;
}
.tidy-bars i {
  flex: 1;
  border-radius: 3px 3px 1px 1px;
  background: var(--tone);
  opacity: 0.85;
}

.tidy-result {
  margin: 6px 0 0;
  min-height: 21px;
  text-align: center;
  font-size: 14px;
  color: var(--ink-3);
}
.tidy-result strong { color: var(--ink); font-weight: 600; }

.tidy-again {
  margin-top: 10px;
  appearance: none;
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  color: var(--accent);
  cursor: pointer;
}
.tidy-again:hover { text-decoration: underline; }
.tidy-again[hidden] { display: none; }

@media (prefers-reduced-motion: reduce) {
  .tidy-tile { transition: none; }
}
