/* ==========================================================================
   Manahari Dahal portfolio: shared styles
   One design system for every page. Layout uses grid and flexbox only.
   Sections:
     1. Tokens (light and dark)
     2. Base and typography
     3. Layout helpers
     4. Header and menu
     5. Buttons, chips and tabs
     6. Section blocks and the tinted band
     7. Cards, callouts and notes
     8. Figures and tables
     9. Footer
    10. Motion
   ========================================================================== */

/* 1. Tokens ---------------------------------------------------------------- */
:root {
  color-scheme: light;

  /* color */
  --bg: #f9f9f6;
  --surface: #f1f1ec;
  --surface-2: #e9e9e4;
  --ink: #1a1a1e;
  --text: #4a4a4a;
  --outline-dim: #717170; /* inactive outline links: 4.6:1 on the page */
  --line: rgba(26, 26, 30, 0.14);
  /* orange: #e65f2e for fills and marks; text in the accent uses a darker
     shade (#b0441c, 5.4:1 on the page) and filled buttons use dark text
     (#1a1a1e, 4.9:1), since the bright orange is too light for small text */
  --accent: #e65f2e;
  --accent-text: #b0441c;
  --on-accent: #1a1a1e;
  /* see-through, so the paper grain shows through the tinted band */
  --band: color-mix(in srgb, var(--accent) 9%, transparent);
  --stage: color-mix(in srgb, var(--accent) 15%, #ffffff);
  --frame: #0f0f11;
  --frame-2: #17171a;
  --frame-line: rgba(255, 255, 255, 0.1);
  --header-line: #d9d9d2;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.22);
  --ok: #1a8a42;
  --warn: #9a6a00;

  /* type */
  --heading-font: "Antonio", "Arial Narrow", Impact, sans-serif;
  --body-font: "Inter", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Type scale, largest to smallest, so the size of a heading always matches
     its level: h1 page title > h2 stage title > section title > subhead >
     card title > body. Sizes are in rem so they follow the reader's own font
     size setting and grow with zoom (WCAG 1.4.4); the fluid ones grow with
     the screen between a floor and a ceiling. Body text is 18px (16px on
     phones) and nothing reading-length is under 16px. */
  --fs-small: 1rem; /* 16 */
  --fs-body: 1.125rem; /* 18 */
  --fs-lead: 1.375rem; /* 22 */
  --fs-h3: 1.25rem; /* 20: card and list titles */
  --fs-sub: clamp(1.25rem, 1.1rem + 0.45vw, 1.5rem); /* 20-24: subheads */
  --fs-h2: clamp(1.75rem, 1.35rem + 1.3vw, 2.5rem); /* 28-40: section titles */
  --fs-stage: clamp(2.25rem, 1.6rem + 2.2vw, 3.75rem); /* 36-60: stage titles */
  --fs-statement: clamp(1.5rem, 1.2rem + 1.1vw, 2.25rem); /* 24-36: pull statements */
  --lh-body: 1.6;

  /* space and shape */
  --gx: clamp(16px, calc(44px + (100vw - 1100px) * 0.12), 88px);
  --max: 1560px;
  --indent: clamp(0px, calc((100vw - 860px) * 0.2), 88px);
  --r-sm: 8px;
  --r: 10px;
  --r-md: 16px;
  --r-lg: 20px;
  --r-xl: 24px;
  --r-pill: 999px;
  --header-h: 66px;
  --header-top: 14px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #0f0f11;
    --surface: #18181b;
    --surface-2: #212125;
    --ink: #e6e6e1;
    --text: #b5b5b5;
    --outline-dim: #7d7d7e;
    --line: rgba(230, 230, 225, 0.14);
    --accent: #ff7a45;
    --accent-text: #ff9d73;
    --on-accent: #0b0b0c;
    --stage: color-mix(in srgb, var(--accent) 15%, var(--bg));
    --header-line: #2a2a2e;
    --shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
    --ok: #5dd68a;
    --warn: #e0a93b;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0f0f11;
  --surface: #18181b;
  --surface-2: #212125;
  --ink: #e6e6e1;
  --text: #b5b5b5;
  --outline-dim: #7d7d7e;
  --line: rgba(230, 230, 225, 0.14);
  --accent: #ff7a45;
  --accent-text: #ff9d73;
  --on-accent: #0b0b0c;
  --stage: color-mix(in srgb, var(--accent) 15%, var(--bg));
  --header-line: #2a2a2e;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
  --ok: #5dd68a;
  --warn: #e0a93b;
}

@media (max-width: 860px) {
  :root {
    --fs-body: 1rem;
    --fs-lead: 1.25rem;
  }
}

/* 2. Base and typography ---------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + var(--header-top) + 16px);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body-font);
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  overflow-x: clip;
}

img,
svg {
  display: block;
  max-width: 100%;
}
img {
  height: auto;
}

h5,
h6 {
  font-size: var(--fs-small);
}
h1,
h2,
h3,
h4,
h5,
h6 {
  margin: 0;
  font-family: var(--heading-font);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
  text-wrap: balance;
}

p,
ul,
ol,
dl,
dd,
figure {
  margin: 0;
}
ul,
ol {
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
}

button {
  font: inherit;
  color: inherit;
}

/* Keyboard focus: a neutral ink ring everywhere, so the accent stays for
   the few marks that need it; ink keeps full contrast on the paper */
:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

b,
strong {
  font-weight: 600;
}

.lead {
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--text);
  max-width: 34ch;
}

.body-text {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text);
  max-width: 36em;
}

.eyebrow {
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-text);
}
.eyebrow--muted {
  color: var(--text);
}

.sr-only {
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  display: inline-block;
  margin: -1px;
}

.skip-link {
  position: fixed;
  top: 12px;
  left: 16px;
  z-index: 100;
  padding: 12px 16px;
  border-radius: 6px;
  background: var(--ink);
  color: var(--bg);
  font-weight: 500;
  text-decoration: none;
  translate: 0 -200%;
}
.skip-link:focus {
  translate: 0 0;
}

/* 3. Layout helpers --------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gx);
}

.stack {
  display: flex;
  flex-direction: column;
  gap: var(--stack-gap, 16px);
}

.grid-2,
.grid-3{
  display: grid;
  gap: var(--grid-gap, 32px);
}
.grid-2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid-3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 860px) {
  .grid-3{
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 640px) {
  .grid-2,
  .grid-3{
    grid-template-columns: minmax(0, 1fr);
  }
}

/* 4. Header and menu -------------------------------------------------------- */

.icon-button {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--header-line);
  border-radius: 50%;
  background: var(--bg);
  cursor: pointer;
}
.icon-button svg {
  width: 18px;
  height: 18px;
}
.icon-button {
  color: var(--ink);
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.icon-button:hover {
  border-color: var(--ink);
  background: color-mix(in srgb, var(--ink) 8%, var(--bg));
}
.icon-button:active {
  translate: 0 1px;
}
.icon-button:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
}

/* theme icon: show the moon in light mode and the sun in dark mode */
.theme-toggle .icon-sun {
  display: none;
}
:root[data-theme="dark"] .theme-toggle .icon-sun {
  display: block;
}
:root[data-theme="dark"] .theme-toggle .icon-moon {
  display: none;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun {
    display: block;
  }
  :root:not([data-theme="light"]) .theme-toggle .icon-moon {
    display: none;
  }
}

/* 5. Buttons, chips and tabs ----------------------------------------------- */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 50px;
  padding: 0 18px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: transparent;
  color: var(--ink);
  font-weight: 500;
  line-height: 1.5;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.2s, border-color 0.2s, transform 0.2s;
}
/* Hover states: every button answers the pointer clearly, by more than a
   hairline; pressing nudges it down a touch. */
.button:hover {
  border-color: var(--ink);
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.button:active {
  translate: 0 1px;
}
.button--primary {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--on-accent);
}
.button--primary:hover {
  border-color: var(--accent);
  /* lighter, so the dark label gains contrast (6.2:1 light, 9:1 dark) */
  background: color-mix(in srgb, var(--accent) 82%, #fff);
}
.button svg {
  width: 18px;
  height: 18px;
}

.text-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-weight: 500;
  color: var(--accent-text);
  text-decoration: none;
}
.text-link svg {
  flex: none;
  width: 18px;
  height: 18px;
}
.text-link:hover {
  text-decoration: underline;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.chip {
  display: inline-flex;
  align-items: center;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-weight: 400;
}
.chip--pill {
  border-radius: var(--r-pill);
  font-weight: 500;
}

/* tabs: buttons with role="tab" inside role="tablist" */
.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.tabs [role="tab"] {
  min-height: 44px;
  padding: 0 20px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.18);
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.2s, border-color 0.2s, translate 0.2s;
}
.tabs [role="tab"]:hover {
  border-color: var(--ink);
  translate: 0 -1px;
}
.tabs [role="tab"][aria-selected="true"] {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--bg);
}
.tabs--pill [role="tab"] {
  border-radius: var(--r-pill);
}

.tabs--quiet [role="tab"] {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
}

/* hidden means hidden, whatever display a component sets */
[hidden] {
  display: none !important;
}

/* 6. Section blocks and the tinted band ----------------------------------- */
/* A block is an eyebrow, a heading and a body. A full-width tinted band starts
   behind the lower half of the heading, so the heading sits on its top edge.
   The band is short: it covers the opening text of the body, or the top part of
   an opening image or card row, which then hangs out below it. site.js sets
   --band-h from the body's first element; the value here is the fallback. */
.block {
  --title-lh: calc(var(--fs-h2) * 1.15);
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: clamp(28px, 4.5vh, 44px);
}

.block__title {
  position: relative;
  z-index: 1;
  font-size: var(--fs-h2);
  line-height: 1.15;
  letter-spacing: -0.015em;
}

.block__body {
  display: flex;
  flex-direction: column;
  gap: 27px;
  margin-top: calc(var(--title-lh) * -0.45 - 12px);
  padding: calc(var(--title-lh) * 0.45 + 39px) 0 clamp(40px, 6vh, 64px) var(--indent);
  /* the outset stretches the band to the screen edges without adding width */
  border-image: linear-gradient(var(--band) 20px, transparent var(--band-h, calc(var(--title-lh) * 0.45 + 200px)))
    fill 0 / 0 / 0 100vmax;
}

.block--plain .block__body {
  border-image: none;
}

.principles {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: -2px;
  position: relative;
  z-index: 1;
  color: var(--text);
}
.principles a {
  padding: 0 4px;
  font-weight: 600;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 3px;
  text-underline-offset: 5px;
}

.subhead {
  font-size: var(--fs-sub);
  line-height: 1.25;
  margin-top: 29px;
}

/* 7. Cards, callouts and notes --------------------------------------------- */
.card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}
.card__num {
  font-weight: 600;
  color: var(--accent-text);
}
.card__label {
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text);
}
.card h3,
.card h4 {
  font-size: var(--fs-h3);
  line-height: 1.3;
}
.card p {
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--text);
}

.callout {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 648px;
}
.callout .eyebrow {
  color: var(--text);
}
.callout p {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
.callout p + p {
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--text);
}

.note-line {
  max-width: 648px;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text);
}

.notice {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 24px;
  border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
  border-left-width: 4px;
  border-left-color: var(--accent);
  border-radius: var(--r);
  background: color-mix(in srgb, var(--accent) 8%, transparent);
}
.notice svg {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--accent-text);
}
.notice__label {
  flex: none;
  padding-right: 14px;
  border-right: 1px solid var(--line);
  font-weight: 600;
  letter-spacing: 0.12em;
}

.dot-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.dot-list li {
  display: grid;
  grid-template-columns: 6px 1fr;
  gap: 12px;
  align-items: baseline;
  color: var(--text);
  line-height: 1.5;
}
.dot-list li::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  translate: 0 -2px;
}

/* 8. Figures and tables ---------------------------------------------------- */
.figure {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.figure__media {
  overflow: hidden;
  border-radius: var(--r-xl);
  background: var(--frame);
}
.figure__media img {
  width: 100%;
}
.figure figcaption {
  max-width: 36em;
  font-size: var(--fs-small);
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: var(--text);
}
.figure__tag {
  font-size: var(--fs-small);
  letter-spacing: 0.06em;
  color: var(--ink);
}

/* drawn diagrams: inline SVG in a dark frame, scales with the column */
.drawing {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.drawing svg {
  width: 100%;
  height: auto;
  border: 1px solid var(--frame-line);
  border-radius: 12px;
  background: var(--frame-2);
}

.table-wrap {
  overflow-x: auto;
}
.table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  border-top: 1px solid var(--line);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--text);
}
.table th,
.table td {
  padding: 11px 12px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.table th {
  font-weight: 600;
}
.table thead th {
  color: var(--text);
}
.table tbody th {
  color: var(--ink);
}

/* 9. Paper and footer ------------------------------------------------------ */
/* Paper: a fine grain baked into the backgrounds, in both themes, with no
   blend modes or overlays, so it reads the same in every browser. Light mode
   has dark specks, dark mode faint light ones; the grain is in the SVG's
   alpha, so it simply sits over the colour beneath. */
:root {
  --paper: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.09 0 0 0 0.09'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.13 0 0 0 -0.035'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  }
}
:root[data-theme="dark"] {
  --paper: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0.13 0 0 0 -0.035'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
body,
.page {
  background: var(--paper) 0 0 / 240px auto, var(--bg);
}

/* The page content sits above the footer and scrolls away to reveal it. */
.page {
  position: relative;
  z-index: 1;
}

/* Footer, in the document's voice: compact, on the same paper one step
   darker (the surface colour). The contact line is set like a stage title,
   the labels are the small grey capitals used across the site, and the one
   orange thing is the Email me button. It waits under the page and is
   revealed at the bottom. */
.site-footer {
  position: sticky;
  bottom: 0;
  z-index: 0;
  padding-top: clamp(40px, 5vw, 64px);
  border-top: 1px solid var(--line);
  background: var(--paper) 0 0 / 240px auto, var(--surface);
  color: var(--text);
}
.site-footer__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
  align-items: start;
  gap: 32px 24px;
}
.site-footer__label {
  margin: 0 0 6px;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted, var(--text));
}
.site-footer h2 {
  font-size: clamp(1.75rem, 1.4rem + 1.1vw, 2.375rem);
  line-height: 1.05;
  color: var(--ink);
}
.site-footer__note {
  margin-top: 8px;
  color: var(--text);
}
.site-footer__cta {
  min-height: 44px;
  margin-top: 16px;
}
.site-footer__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
.site-footer__col a {
  color: var(--ink);
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  transition: background-size 0.25s ease;
}
.site-footer__col a:hover,
.site-footer__col a:focus-visible {
  background-size: 100% 1px;
}
.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px;
  margin-top: clamp(32px, 4vw, 48px);
  padding: 16px 0 20px;
  border-top: 1px solid var(--line);
  font-size: 0.875rem;
}
.site-footer__legal a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ink);
  text-decoration: none;
}
.site-footer__legal svg {
  width: 16px;
  height: 16px;
  transition: translate 0.2s ease;
}
.site-footer__legal a:hover svg {
  translate: 0 -3px;
}
@media (max-width: 860px) {
  .site-footer__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .site-footer__grid > :first-child {
    grid-column: 1 / -1;
  }
}

/* 10. Motion --------------------------------------------------------------- */
/* Moving between pages of the site cross-fades in place (cross-document view
   transitions) instead of blanking and repainting like a fresh load; the top
   bar stays put. Browsers without it navigate as before. */
@view-transition {
  navigation: auto;
}
.cp-bar {
  view-transition-name: top-bar;
}
@media (prefers-reduced-motion: reduce) {
  @view-transition {
    navigation: none;
  }
}

/* Scroll text: text eases in as it scrolls into view, pure CSS (each
   element's own view timeline), with a different entrance per kind of text
   so it does not feel repeated:
     section titles    rise out of a mask
     eyebrows, labels  wipe in from the left
     subheads          slide in from the left
     paragraphs        drift up out of a soft blur
     quotes, statements  grow in from a little smaller
     list items        come up with a slight tilt, alternating sides
   Each finishes within the first ~220px of scrolling, so nothing is half
   faded while you read it. Text already on screen at load shows as is.
   Pinned (sticky) text, like the About chapters, is left out: its view
   timeline stops while it is pinned. Skipped for reduced motion, while motion is paused (.motion-paused), and
   in browsers without scroll-driven animations (text just shows). Decorative
   or interactive areas with their own motion are left alone. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* text sliding in from the side must not widen the page */
    main {
      overflow-x: clip;
    }
    :root:not(.motion-paused) main :is(h2, h3, h4, p, li, blockquote, dt, dd):not(:is(.hero, .sandbox-wrap, .badge, .shelves, .spot, .console, .cp-outline, nav, figure, table, .tabs, [role="tablist"], .seasons, .motion, .lightbox, .skills3d, li, .chapter) *):not(.hero *),
    :root:not(.motion-paused) main :is(.shelf__name, .shelf__tags) {
      animation: st-up linear both;
      animation-timeline: view();
      animation-range: entry 0px entry 220px;
    }
    :root:not(.motion-paused) main :is(h2, .doc-head__title, .block__title, .cp-sec__label):not(:is(.sandbox-wrap, .badge, .shelves) *) {
      animation-name: st-rise;
    }
    :root:not(.motion-paused) main :is(.eyebrow, .label, .cp-label, .card__label, .timeline-group__title):not(:is(.sandbox-wrap, .badge, .seasons) *) {
      animation: st-wipe linear both;
      animation-timeline: view();
      animation-range: entry 0px entry 200px;
    }
    :root:not(.motion-paused) main :is(h3, h4):not(:is(.sandbox-wrap, .badge, .shelves, .spot, .console, figure, table, nav, li, .chapter) *) {
      animation-name: st-slide;
    }
    :root:not(.motion-paused) main .shelf__tags {
      animation-name: st-wipe;
    }
    :root:not(.motion-paused) main :is(blockquote, .statement, [class*="quote"]):not(:is(.sandbox-wrap, .badge) *) {
      animation-name: st-zoom;
    }
    :root:not(.motion-paused) main li:not(:is(.sandbox-wrap, .badge, .shelves, .spot, .console, .cp-outline, nav, figure, table, .seasons, .chapter) *):nth-child(odd) {
      animation-name: st-tilt-l;
    }
    :root:not(.motion-paused) main li:not(:is(.sandbox-wrap, .badge, .shelves, .spot, .console, .cp-outline, nav, figure, table, .seasons, .chapter) *):nth-child(even) {
      animation-name: st-tilt-r;
    }
  }
}
@keyframes st-up {
  from {
    opacity: 0;
    transform: translateY(26px);
    filter: blur(5px);
  }
}
@keyframes st-rise {
  from {
    opacity: 0;
    transform: translateY(0.45em);
    clip-path: inset(0 0 100% 0);
  }
  to {
    clip-path: inset(-1em -100vw -0.5em -100vw);
  }
}
@keyframes st-wipe {
  from {
    opacity: 0;
    transform: translateX(-8px);
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(-1em -100vw -1em -1em);
  }
}
@keyframes st-slide {
  from {
    opacity: 0;
    transform: translateX(-32px);
  }
}
@keyframes st-zoom {
  from {
    opacity: 0;
    transform: scale(0.94);
    filter: blur(3px);
  }
}
@keyframes st-tilt-l {
  from {
    opacity: 0;
    transform: translate(-14px, 18px) rotate(-1.5deg);
  }
}
@keyframes st-tilt-r {
  from {
    opacity: 0;
    transform: translate(14px, 18px) rotate(1.5deg);
  }
}

.reveal {
  opacity: 0;
  translate: 0 24px;
  transition: opacity 0.7s ease, translate 0.7s ease;
}
.reveal.is-in {
  opacity: 1;
  translate: 0 0;
}

.split-word {
  display: inline-block;
  white-space: pre;
}
.split-letter {
  display: inline-block;
  opacity: 0;
  translate: 0 0.4em;
  transition: opacity 0.5s ease, translate 0.5s ease;
  transition-delay: calc(var(--i) * 18ms);
}
.is-in .split-letter {
  opacity: 1;
  translate: 0 0;
}

.cursor-ring {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 90;
  width: 34px;
  height: 34px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s, width 0.2s, height 0.2s;
}
.cursor-ring.is-on {
  opacity: 1;
}
.cursor-ring.is-link {
  width: 54px;
  height: 54px;
}
@media (hover: none) {
  .cursor-ring {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal,
  .split-letter {
    opacity: 1;
    translate: none;
  }
  .cursor-ring {
    display: none;
  }
}

/* ID badge ------------------------------------------------------------------ */
/* ID badge on a lanyard (Home's About me section and the About page). A strap and
   a clip hold a portrait card that sways gently. Hovering (home.js adds
   .is-open), the "Flip my ID" button, or tabbing into the links on the back
   straightens it and turns it over: the front has the photo, name, role and
   status, the back has the details and links. Both faces share the card's
   single grid cell; the card turns in 3D, so nothing on it may set opacity,
   filter or overflow (that would flatten it). Grid and flex only. */
.badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}
.badge__swing {
  display: flex;
  flex-direction: column;
  align-items: center;
  perspective: 1400px;
  transform-origin: 50% 0;
  animation: badge-sway 3.6s ease-in-out infinite alternate;
  transition: rotate 0.5s ease;
}
.badge__strap {
  width: 18px;
  height: clamp(60px, 8vw, 120px);
  border-radius: 0 0 4px 4px;
  background:
    repeating-linear-gradient(180deg, transparent 0 10px, rgb(255 255 255 / 0.18) 10px 12px),
    var(--accent);
}
.badge__clip {
  width: 36px;
  height: 20px;
  margin-top: -4px;
  border: 2px solid var(--line);
  border-radius: 6px;
  background: var(--surface-2);
}
.badge__card {
  display: grid;
  width: clamp(250px, 22vw, 300px);
  margin-top: -6px;
  transform-style: preserve-3d;
  transition: transform 0.8s cubic-bezier(0.65, 0, 0.35, 1);
}
.badge__face {
  grid-area: 1 / 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 16px 16px 20px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--shadow);
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.badge__front {
  align-items: center;
  text-align: center;
}
.badge__back {
  justify-content: center;
  transform: rotateY(180deg);
}
/* the slot the clip goes through */
.badge__slot {
  width: 44px;
  height: 9px;
  border-radius: 99px;
  background: var(--bg);
  box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.25);
}
.badge__photo {
  width: 100%;
  aspect-ratio: 4 / 4.4;
  object-fit: cover;
  border-radius: var(--r-md);
  background: #fbfcfe;
}
.badge__name {
  margin-top: 4px;
  font-size: 1.75rem;
  line-height: 1.05;
}
.badge__role {
  margin-top: -6px;
  color: var(--text);
}
.badge__status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 99px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent-text);
  font-size: var(--fs-small);
  font-weight: 600;
}
.badge__about {
  color: var(--ink);
}
.badge__facts {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 12px;
  border-top: 1px dashed var(--line);
  font-weight: 500;
}
.badge__facts div {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 6px;
}
.badge__facts dt {
  color: var(--text);
  font-weight: 400;
}
.badge__links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-top: 6px;
}
.badge__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--bg);
}
.badge__icon svg {
  width: 20px;
  height: 20px;
}
.badge__more {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 14px;
  border-radius: var(--r);
  background: var(--ink);
  color: var(--bg);
  font-weight: 500;
  text-decoration: none;
}
.badge__more svg {
  width: 16px;
  height: 16px;
}
.badge__flip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: 99px;
  background: none;
  color: var(--ink);
  font-weight: 500;
  cursor: pointer;
}
.badge__flip:hover {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
/* straighten and turn over: on hover/button (.is-open) or when a link on the
   back has keyboard focus */
.peek.is-open .badge__swing,
.peek:has(.badge__back :focus-visible) .badge__swing {
  animation: none;
  rotate: 0deg;
}
.peek.is-open .badge__card,
.peek:has(.badge__back :focus-visible) .badge__card {
  transform: rotateY(180deg);
}
@keyframes badge-sway {
  from {
    rotate: -3deg;
  }
  to {
    rotate: 3deg;
  }
}
@media (prefers-reduced-motion: reduce) {
  .badge__swing {
    animation: none;
  }
}
@media (max-width: 860px) {
  .badge__card {
    width: min(300px, 80vw);
  }
}

/* Top bar, shared by Home and About (the case study pages have their own
   copy in compact.css): the breadcrumb on the left; a few links and the
   switches on the right. It sticks to the top and the page scrolls under
   it, on the same paper. */
:root {
  --bar-h: 60px;
  --muted: color-mix(in srgb, var(--text) 80%, var(--bg));
}
html {
  scroll-padding-top: calc(var(--bar-h) + 24px);
}
.cp-bar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: var(--bar-h);
  padding-inline: max(var(--gx), calc((100% - var(--max)) / 2 + var(--gx)));
  border-bottom: 1px solid var(--line);
  background: var(--paper) 0 0 / 240px auto, var(--bg);
}
/* left: the "md." mark (home) and the three page links; right: the icon
   buttons. The page you are on is marked in the accent. */
.cp-bar__start {
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 36px);
  min-width: 0;
}
.bar-mark {
  font-family: var(--heading-font);
  font-size: 1.5rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
}
.bar-mark i {
  font-style: normal;
  color: var(--accent);
}
.cp-bar__end {
  display: flex;
  align-items: center;
  gap: clamp(8px, 2vw, 20px);
}
.cp-bar__links {
  display: flex;
  gap: clamp(14px, 2.4vw, 28px);
}
.cp-bar__links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 0.875rem;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s ease;
}
.cp-bar__links a:hover {
  color: var(--ink);
}
.cp-bar__links a[aria-current] {
  color: var(--accent-text);
}
.cp-bar a:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  border-radius: 4px;
}
/* from laptop width the page outline on the left does the navigating
   (home and case studies), so the top bar keeps only the mark and buttons */
@media (min-width: 1101px) {
  body:has(.cp-outline) .cp-bar__links {
    display: none;
  }
}
/* phones: smaller round buttons, so the mark, the four links and the
   buttons share one row */
@media (max-width: 520px) {
  .cp-bar .icon-button {
    width: 40px;
    height: 40px;
  }
  .cp-bar__end {
    gap: 6px;
  }
}
/* Hamburger: below laptop width the links move into a menu that covers the
   whole screen under the top bar. The three lines turn into an X. */
.cp-bar .menu-button {
  display: none;
  place-items: center;
  padding: 0;
}
.menu-button__lines {
  display: grid;
  gap: 4px;
  width: 18px;
}
.menu-button__lines i {
  display: block;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.3s ease, opacity 0.2s ease;
}
.menu-button[aria-expanded="true"] .menu-button__lines i:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.menu-button[aria-expanded="true"] .menu-button__lines i:nth-child(2) {
  opacity: 0;
}
.menu-button[aria-expanded="true"] .menu-button__lines i:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}
@media (max-width: 1100px) {
  .cp-bar__links {
    display: none;
  }
  .cp-bar .menu-button {
    display: inline-grid;
  }
}
/* The menu covers the whole screen under the top bar (so the X stays in
   reach): the links in large type, numbered, sliding in one after another,
   with email and socials at the bottom. */
.menu {
  position: fixed;
  inset: 0;
  z-index: 35;
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 32px;
  height: 100vh;
  height: 100dvh;
  padding: calc(var(--bar-h) + 32px) var(--gx) max(32px, env(safe-area-inset-bottom));
  background: var(--paper) 0 0 / 240px auto, var(--bg);
  overflow-y: auto;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.3s, visibility 0.3s;
}
.menu.is-open {
  visibility: visible;
  opacity: 1;
}
.menu__links {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.menu__links a {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-block: 10px;
  border-bottom: 1px solid var(--line);
  font-family: var(--heading-font);
  font-size: clamp(2.5rem, 11vw, 4rem);
  font-weight: 600;
  line-height: 1.1;
  color: var(--ink);
  text-decoration: none;
  transform: translateY(16px);
  opacity: 0;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.45s ease, color 0.2s ease;
}
.menu.is-open .menu__links a {
  transform: none;
  opacity: 1;
}
.menu.is-open .menu__links a:nth-child(2) { transition-delay: 0.05s; }
.menu.is-open .menu__links a:nth-child(3) { transition-delay: 0.1s; }
.menu.is-open .menu__links a:nth-child(4) { transition-delay: 0.15s; }
.menu.is-open .menu__links a:nth-child(5) { transition-delay: 0.2s; }
.menu__links a:hover,
.menu__links a[aria-current] {
  color: var(--accent-text);
}
.menu__links small {
  font-family: var(--body-font);
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--accent-text);
}
.menu__foot,
.menu__foot span {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
}
.menu__foot a {
  color: var(--ink);
  text-decoration-color: var(--accent);
  text-underline-offset: 4px;
}
@media (min-width: 1101px) {
  .menu {
    display: none;
  }
}

/* The way back on the detail pages, under the top bar: an arrow and the
   parent page, then the page you are on ("<- Projects / Luna"). On the
   case studies it heads the outline column, lined up with the stages; on
   About it lines up with the page. */
.cp-crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 8px;
  font-size: 0.875rem;
  color: var(--muted);
}
.cp-crumbs a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 32px;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.2s ease;
}
.cp-crumbs a svg {
  width: 15px;
  height: 15px;
  transition: translate 0.2s ease;
}
.cp-crumbs a:hover {
  color: var(--ink);
}
.cp-crumbs a:hover svg {
  translate: -3px 0;
}
.cp-crumbs [aria-current] {
  color: var(--ink);
}
.cp-crumbs a:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 2px;
  border-radius: 4px;
}
.page-crumbs {
  padding-top: 20px;
}
@media (prefers-reduced-motion: reduce) {
  .cp-crumbs a,
  .cp-crumbs a svg {
    transition: none;
  }
}
