/* ============================================================
   Book Site — single global stylesheet
   Layers keep specificity predictable.
   ============================================================ */
@layer reset, tokens, base, layout, components, utilities;

/* ---------- reset ---------- */
@layer reset {
  *, *::before, *::after { box-sizing: border-box; }
  * { margin: 0; }
  html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
  body { min-height: 100svh; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
  img, picture, svg, video { display: block; max-width: 100%; height: auto; }
  input, button, textarea, select { font: inherit; color: inherit; }
  button { cursor: pointer; background: none; border: none; }
  a { color: inherit; text-decoration: none; }
  ul[role="list"], ol[role="list"] { list-style: none; padding: 0; }
  :target { scroll-margin-top: 5rem; }
}

/* ---------- tokens ---------- */
@layer tokens {
  :root {
    color-scheme: light dark;

    /* spacing — 4px base */
    --space-1: .25rem;  --space-2: .5rem;   --space-3: .75rem;  --space-4: 1rem;
    --space-5: 1.25rem; --space-6: 1.5rem;  --space-8: 2rem;    --space-10: 2.5rem;
    --space-12: 3rem;   --space-16: 4rem;   --space-20: 5rem;   --space-24: 6rem;
    --space-32: 8rem;

    /* type scale (1.25) */
    --text-xs: .8125rem; --text-sm: .9375rem; --text-base: 1.0625rem;
    --text-lg: 1.25rem;  --text-xl: 1.5rem;   --text-2xl: 1.875rem;
    --text-3xl: 2.25rem; --text-4xl: 3rem;    --text-5xl: 3.75rem;

    --leading-tight: 1.15;
    --leading-snug: 1.3;
    --leading-normal: 1.6;

    /* radii */
    --radius-sm: 6px; --radius: 8px; --radius-lg: 12px; --radius-xl: 20px; --radius-full: 9999px;

    /* containers */
    --prose: 68ch;
    --layout: 1180px;

    /* Motion system — one easing for entrances, one for hover, one for the
       subtle button bounce. Durations are deliberate and quoted as the only
       allowed values so the whole site has a single rhythm. */
    --ease: cubic-bezier(.2, 0, 0, 1);
    --ease-soft: cubic-bezier(.22, 1, .36, 1);            /* primary entrance */
    --ease-formal: cubic-bezier(.4, 0, .2, 1);            /* hover transitions */
    --ease-bounce-soft: cubic-bezier(.34, 1.14, .64, 1);  /* very subtle overshoot — buttons */
    --ease-spring: cubic-bezier(.34, 1.3, .64, 1);
    --dur-snap: 220ms;            /* hover micro */
    --dur-hover: 240ms;
    --dur-quick: 480ms;           /* small transitions */
    --dur-enter: 1000ms;          /* main content entrance */
    --dur-enter-slow: 1400ms;     /* hero / intro panel */
    --dur-stagger: 130ms;         /* gap between siblings */
    --dur-modal: 360ms;

    /* fonts (overridable by theme block) */
    --font-head: "Newsreader", Georgia, "Times New Roman", serif;
    --font-body: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

    /* default accent (palette blocks override) */
    --accent: #B5462E;
    --accent-hover: #9B3B25;
    --accent-contrast: #ffffff;
  }

  /* ----- palettes (data-palette on <html>) ----- */
  /* Anatomy — warm cream + arterial terracotta (default) */
  :root, [data-palette="anatomy"] {
    --bg: #FAF7F2; --bg-elevated: #FFFFFF; --surface-sunk: #F1ECE3;
    --border: #E7E0D2; --border-strong: #D6CDBB;
    --text: #1F1B16; --text-muted: #6B6357;
    --accent: #B5462E; --accent-hover: #9B3B25; --accent-soft: #F4E3DC; --accent-contrast: #fff;
    --shadow: 0 1px 2px rgba(31,27,22,.05), 0 8px 24px rgba(31,27,22,.06);
  }
  [data-palette="clinical"] {
    --bg: #F6F8F6; --bg-elevated: #FFFFFF; --surface-sunk: #EAF0EC;
    --border: #DCE5DE; --border-strong: #C6D3C9;
    --text: #182019; --text-muted: #5C6A60;
    --accent: #2F7D5B; --accent-hover: #266649; --accent-soft: #DCEDE3; --accent-contrast: #fff;
    --shadow: 0 1px 2px rgba(24,32,25,.05), 0 8px 24px rgba(24,32,25,.06);
  }
  [data-palette="amber"] {
    --bg: #FBF8F3; --bg-elevated: #FFFFFF; --surface-sunk: #F3ECE0;
    --border: #E8DFCE; --border-strong: #D8CBB2;
    --text: #1E1A12; --text-muted: #6B6149;
    --accent: #C2691B; --accent-hover: #A4570F; --accent-soft: #F6E6D2; --accent-contrast: #fff;
    --shadow: 0 1px 2px rgba(30,26,18,.05), 0 8px 24px rgba(30,26,18,.06);
  }
  [data-palette="slate"] {
    --bg: #F7F8FA; --bg-elevated: #FFFFFF; --surface-sunk: #ECEEF2;
    --border: #DDE1E7; --border-strong: #C5CBD3;
    --text: #14181E; --text-muted: #5C6470;
    --accent: #2E5BB8; --accent-hover: #234999; --accent-soft: #DEE7F7; --accent-contrast: #fff;
    --shadow: 0 1px 2px rgba(20,24,30,.05), 0 8px 24px rgba(20,24,30,.06);
  }
  [data-palette="coastal"] {
    --bg: #F4F8FA; --bg-elevated: #FFFFFF; --surface-sunk: #E5EFF3;
    --border: #D2DFE5; --border-strong: #B5C7D0;
    --text: #142028; --text-muted: #51626B;
    --accent: #1F7591; --accent-hover: #195F77; --accent-soft: #D6EBF1; --accent-contrast: #fff;
    --shadow: 0 1px 2px rgba(20,32,40,.05), 0 8px 24px rgba(20,32,40,.06);
  }
  [data-palette="sage"] {
    --bg: #F7F8F4; --bg-elevated: #FFFFFF; --surface-sunk: #ECEFE5;
    --border: #DDE1D3; --border-strong: #C4C9B7;
    --text: #1B1F12; --text-muted: #5E6650;
    --accent: #5D7838; --accent-hover: #4A622B; --accent-soft: #E5EDD4; --accent-contrast: #fff;
    --shadow: 0 1px 2px rgba(20,24,18,.05), 0 8px 24px rgba(20,24,18,.06);
  }
  [data-palette="rose"] {
    --bg: #FBF6F7; --bg-elevated: #FFFFFF; --surface-sunk: #F2E8EB;
    --border: #EADAE0; --border-strong: #D7BBC6;
    --text: #1F1418; --text-muted: #6B5A60;
    --accent: #B83A6B; --accent-hover: #9C2E59; --accent-soft: #F5DAE5; --accent-contrast: #fff;
    --shadow: 0 1px 2px rgba(31,20,24,.05), 0 8px 24px rgba(31,20,24,.06);
  }
  [data-palette="charcoal"] {
    --bg: #16171A; --bg-elevated: #1E2024; --surface-sunk: #101114;
    --border: #2A2C32; --border-strong: #3A3D45;
    --text: #E8E9EC; --text-muted: #9CA0AA;
    --accent: #E89B5B; --accent-hover: #F0AC76; --accent-soft: #3A2C1F; --accent-contrast: #16171A;
    --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
  }

  @media (prefers-color-scheme: dark) {
    :root, [data-palette="anatomy"] {
      --bg: #1A1714; --bg-elevated: #221E1A; --surface-sunk: #14110E;
      --border: #322C25; --border-strong: #463E34;
      --text: #ECE6DA; --text-muted: #A89E8E;
      --accent: #E8896E; --accent-hover: #F09B82; --accent-soft: #3A271F; --accent-contrast: #1A1714;
      --shadow: 0 1px 2px rgba(0,0,0,.3), 0 8px 24px rgba(0,0,0,.35);
    }
    [data-palette="clinical"] {
      --bg: #131814; --bg-elevated: #1B221D; --surface-sunk: #0E120F;
      --border: #28332B; --border-strong: #39473C;
      --text: #E4EAE5; --text-muted: #95A398;
      --accent: #5FBF8E; --accent-hover: #74CF9F; --accent-soft: #1E2E25; --accent-contrast: #0E120F;
    }
    [data-palette="amber"] {
      --bg: #1A160F; --bg-elevated: #221D14; --surface-sunk: #130F09;
      --border: #322A1D; --border-strong: #463B28;
      --text: #ECE3D2; --text-muted: #A99B7E;
      --accent: #E8A05A; --accent-hover: #F2B070; --accent-soft: #3A2C18; --accent-contrast: #1A160F;
    }
  }

  /* fonts (data-font on <html>) */
  [data-font="source"]    { --font-head: "Source Serif 4", Georgia, serif; --font-body: "Source Sans 3", system-ui, sans-serif; }
  [data-font="lora"]      { --font-head: "Lora", Georgia, serif; --font-body: "Inter", system-ui, sans-serif; }
  [data-font="playfair"]  { --font-head: "Playfair Display", Georgia, serif; --font-body: "Inter", system-ui, sans-serif; }
  [data-font="cormorant"] { --font-head: "Cormorant Garamond", Georgia, serif; --font-body: "Lato", system-ui, sans-serif; }
  [data-font="ebgaramond"]{ --font-head: "EB Garamond", Georgia, serif; --font-body: "Inter", system-ui, sans-serif; }
  [data-font="merriweather"]{ --font-head: "Merriweather", Georgia, serif; --font-body: "Open Sans", system-ui, sans-serif; }

  /* density (data-density on <html>) — scales section padding + radii */
  [data-density="compact"] { --section-pad: 2.5rem; --hero-pad: 3rem; --radius-multiplier: 0.75; }
  [data-density="airy"]    { --section-pad: 6rem;   --hero-pad: 7rem; --radius-multiplier: 1.25; }
  [data-density="normal"]  { --section-pad: 4rem;   --hero-pad: 5rem; --radius-multiplier: 1; }
}

/* ---------- base ---------- */
@layer base {
  body {
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-normal);
    color: var(--text);
    background: var(--bg);
  }
  h1, h2, h3, h4 { font-family: var(--font-head); font-weight: 600; line-height: var(--leading-tight); letter-spacing: -.01em; color: var(--text); }
  h1 { font-size: clamp(2.4rem, 5vw, var(--text-5xl)); letter-spacing: -.02em; }
  h2 { font-size: clamp(1.6rem, 3vw, var(--text-3xl)); }
  h3 { font-size: var(--text-xl); }
  p { text-wrap: pretty; }
  a:hover { color: var(--accent); }
  strong { font-weight: 600; }
  ::selection { background: var(--accent-soft); color: var(--text); }

  *:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
  }
}

/* ---------- layout ---------- */
@layer layout {
  .layout { width: 100%; max-width: var(--layout); margin-inline: auto; padding-inline: var(--space-5); }
  .prose { max-width: var(--prose); }
  .prose p + p { margin-top: var(--space-5); }
  .section { padding-block: var(--section-pad, 4rem); }
  .section-lg { padding-block: var(--space-24); }
  .hero { padding-block: var(--hero-pad, 5rem) var(--space-12); }
  .stack > * + * { margin-top: var(--space-4); }
  .center { text-align: center; }

  @media (min-width: 720px) {
    .layout { padding-inline: var(--space-8); }
  }
}

/* ---------- components ---------- */
@layer components {
  /* nav */
  .nav {
    position: sticky; top: 0; z-index: 50;
    height: 64px; display: flex; align-items: center;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: blur(14px) saturate(150%);
    -webkit-backdrop-filter: blur(14px) saturate(150%);
    /* Always show a subtle bottom border to visually separate nav from page */
    border-block-end: 1px solid var(--border);
    box-shadow: 0 1px 0 color-mix(in srgb, var(--text) 4%, transparent);
    transition: border-color var(--dur-hover) var(--ease), transform .3s var(--ease), box-shadow var(--dur-hover) var(--ease);
  }
  .nav[data-scrolled="true"] {
    border-block-end-color: color-mix(in srgb, var(--text) 14%, var(--border));
    box-shadow: 0 2px 8px color-mix(in srgb, var(--text) 6%, transparent);
  }
  .nav[data-hidden="true"] { transform: translateY(-100%); }
  /* Brand on the LEFT, Cover/Gallery on the right — both vertically centered. */
  .nav .layout {
    display: flex; align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
  }
  .brand { font-family: var(--font-head); font-size: var(--text-lg); font-weight: 600; letter-spacing: -.01em; }
  .nav-links { display: flex; align-items: center; gap: var(--space-2); }
  .nav-links a, .nav-links .nav-link {
    padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm);
    font-size: var(--text-sm); color: var(--text-muted); font-weight: 500;
    transition: color var(--dur-hover) var(--ease), background var(--dur-hover) var(--ease);
    background: transparent; border: 0; cursor: pointer;
    font-family: inherit;
  }
  .nav-links a:hover, .nav-links .nav-link:hover { color: var(--text); background: var(--surface-sunk); }
  .nav-links a[aria-current="page"], .nav-links .nav-link[aria-current="page"] { color: var(--accent); }
  /* In edit mode the brand becomes a button — strip default button look */
  .brand-btn { background: transparent; border: 0; cursor: pointer; padding: 0; font: inherit; color: inherit; }
  /* In edit mode the footer Explore links become buttons too */
  .foot-link {
    display: block; text-align: left; padding: 0;
    background: transparent; border: 0; cursor: pointer;
    color: var(--text-muted); font-size: var(--text-sm);
    font-family: inherit;
  }
  .foot-link:hover { color: var(--accent); }
  .nav-toggle { display: none; padding: var(--space-2); border-radius: var(--radius-sm); color: var(--text); }

  @media (max-width: 640px) {
    .nav-toggle { display: inline-flex; }
    .nav-links {
      position: absolute; inset-inline: 0; top: 56px;
      flex-direction: column; align-items: stretch; gap: 0;
      background: var(--bg-elevated); border-block-end: 1px solid var(--border);
      padding: var(--space-2); box-shadow: var(--shadow);
      display: none;
    }
    .nav-links[data-open="true"] { display: flex; }
    .nav-links a { padding: var(--space-3); font-size: var(--text-base); }
  }

  .skip-link {
    position: absolute; left: -9999px; top: var(--space-2);
    background: var(--accent); color: var(--accent-contrast);
    padding: var(--space-2) var(--space-4); border-radius: var(--radius); z-index: 100;
  }
  .skip-link:focus { left: var(--space-4); }

  /* buttons */
  .btn {
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    height: 44px; padding-inline: var(--space-5);
    border-radius: var(--radius); font-size: var(--text-sm); font-weight: 600;
    transition: background var(--dur-hover) var(--ease), border-color var(--dur-hover) var(--ease),
                transform var(--dur-hover) var(--ease), color var(--dur-hover) var(--ease);
    white-space: nowrap;
  }
  .btn:active { transform: translateY(1px); }
  .btn-primary { background: var(--accent); color: var(--accent-contrast); }
  .btn-primary:hover { background: var(--accent-hover); color: var(--accent-contrast); }
  .btn-secondary { border: 1px solid var(--border-strong); color: var(--text); }
  .btn-secondary:hover { border-color: var(--text-muted); color: var(--text); background: var(--surface-sunk); }
  .btn-lg { height: 50px; padding-inline: var(--space-6); font-size: var(--text-base); }

  /* hero */
  .hero { padding-block: var(--space-16) var(--space-12); }
  .hero-grid { display: grid; gap: var(--space-10); align-items: center; }
  .hero-cover {
    border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow);
    background: var(--surface-sunk); max-height: 72vh; width: fit-content; margin-inline: auto;
  }
  .hero-cover img { max-height: 72vh; width: auto; object-fit: contain; }
  .hero-placeholder {
    aspect-ratio: 3/4; width: min(320px, 70vw); display: grid; place-items: center;
    color: var(--text-muted); font-size: var(--text-sm); padding: var(--space-6); text-align: center;
  }
  .hero h1 { margin-bottom: var(--space-4); }
  .hero .subtitle { font-size: var(--text-lg); color: var(--text-muted); margin-bottom: var(--space-3); }
  .hero .byline { font-size: var(--text-base); color: var(--text-muted); font-style: italic; margin-bottom: var(--space-6); }
  .hero .intro { font-size: var(--text-lg); margin-bottom: var(--space-8); }
  .hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); }

  @media (min-width: 880px) {
    .hero-grid { grid-template-columns: 1fr 1.1fr; gap: var(--space-16); }
    .hero-grid-reverse { grid-template-columns: 1.1fr 1fr; gap: var(--space-16); }
    .hero-cover { margin-inline: 0; }
  }
  .hero-stack { display: grid; gap: var(--space-10); justify-items: center; text-align: center; }
  .hero-stack[data-hero-layout="centered"] .hero-cover { max-width: 360px; }
  .hero-stack[data-hero-layout="stacked"] .hero-cover img { max-height: 50vh; }
  .hero-text[data-hero-align="center"] { text-align: center; }
  .hero-text[data-hero-align="center"] .hero-actions { justify-content: center; }
  .hero-text[data-hero-align="center"] .intro { margin-inline: auto; max-width: 56ch; }

  /* generic content section */
  .content h2 { margin-bottom: var(--space-4); }
  .takeaways { margin-top: var(--space-6); display: grid; gap: var(--space-3); }
  .takeaway {
    display: flex; gap: var(--space-4); align-items: flex-start;
    padding: var(--space-4) var(--space-5); background: var(--bg-elevated);
    border: 1px solid var(--border); border-radius: var(--radius-lg);
  }
  .takeaway .num {
    flex: none; width: 28px; height: 28px; border-radius: var(--radius-full);
    background: var(--accent-soft); color: var(--accent); font-weight: 600;
    font-size: var(--text-sm); display: grid; place-items: center; font-family: var(--font-body);
  }

  .divider { border: 0; border-top: 1px solid var(--border); margin-block: var(--space-12); }

  /* content blocks (cover.blocks[]) */
  .blocks-list { display: flex; flex-direction: column; gap: var(--space-6); }
  .block { position: relative; }
  .block-text { font-size: var(--text-lg); line-height: var(--leading-normal); margin: 0; }
  .block-heading h2, .block-heading h3 { margin: var(--space-4) 0 var(--space-2); }
  .block-quote {
    margin: 0; padding: var(--space-5) var(--space-6);
    border-left: 4px solid var(--accent);
    background: var(--surface-sunk); border-radius: var(--radius);
    font-family: var(--font-head); font-size: var(--text-xl); font-style: italic; line-height: var(--leading-snug);
  }
  .block-cite { display: block; margin-top: var(--space-3); font-size: var(--text-sm); font-style: normal; color: var(--text-muted); font-family: var(--font-body); }
  .block-image { margin: 0; }
  .block-image img { width: 100%; height: auto; border-radius: var(--radius); display: block; }
  .block-image figcaption { margin-top: var(--space-2); font-size: var(--text-sm); color: var(--text-muted); }
  .block-image-small img  { max-width: 360px; margin-inline: auto; }
  .block-image-medium img { max-width: 560px; margin-inline: auto; }
  .block-image-large img  { width: 100%; }
  .block-image-empty { padding: var(--space-8); border: 2px dashed var(--border-strong); border-radius: var(--radius); text-align: center; color: var(--text-muted); }
  .block-cta { text-align: center; margin-block: var(--space-4); }
  .block-divider { margin-block: var(--space-6); border: 0; border-top: 1px solid var(--border); }
  .block-subtitle { font-family: var(--font-head); font-size: var(--text-xl); font-weight: 500; color: var(--text-muted); margin: var(--space-4) 0 var(--space-2); }
  .block-pullquote { font-family: var(--font-head); font-size: clamp(var(--text-xl), 2.4vw, var(--text-2xl)); font-style: italic; line-height: 1.35; color: var(--accent); margin: var(--space-8) 0; padding-inline: var(--space-6); border-inline-start: 3px solid var(--accent); }
  .block-spacer { display: block; width: 100%; }
  .block-spacer-small  { height: var(--space-6); }
  .block-spacer-medium { height: var(--space-12); }
  .block-spacer-large  { height: var(--space-20); }

  /* Per-block font sizing + whole-block formatting toggles. */
  .block { --block-size-mult: 1; }
  .block.block-size-small { --block-size-mult: 0.75; }
  .block.block-size-large { --block-size-mult: 1.3; }
  .block.block-size-xl    { --block-size-mult: 1.75; }
  .block.block-size-huge  { --block-size-mult: 2.3; }
  .block.block-bold       { font-weight: 700; }
  .block.block-italic     { font-style: italic; }
  .block.block-underline > *,
  .block.block-underline .block-text,
  .block.block-underline h2,
  .block.block-underline h3,
  .block.block-underline .block-quote,
  .block.block-underline .block-pullquote { text-decoration: underline; text-underline-offset: 4px; }
  .block-paragraph .block-text { font-size: calc(var(--text-lg) * var(--block-size-mult)); line-height: 1.55; }
  .block-heading h2            { font-size: calc(clamp(1.6rem, 3vw, var(--text-3xl)) * var(--block-size-mult)); }
  .block-subtitle h3.block-subtitle { font-size: calc(var(--text-xl) * var(--block-size-mult)); }
  .block-quote                 { font-size: calc(var(--text-xl) * var(--block-size-mult)); }
  .block-pullquote             { font-size: calc(clamp(var(--text-xl), 2.4vw, var(--text-2xl)) * var(--block-size-mult)); }

  /* list_section: heading + intro + numbered/bulleted items */
  .info-section { margin-block: var(--space-4); }
  .info-title { margin: 0 0 var(--space-3); }
  .info-intro { color: var(--text-muted); font-size: var(--text-lg); margin: 0 0 var(--space-5); max-width: 65ch; }
  .info-items { display: grid; gap: var(--space-3); }
  .info-item {
    display: flex; gap: var(--space-4); align-items: flex-start;
    padding: var(--space-4) var(--space-5);
    background: var(--bg-elevated); border: 1px solid var(--border);
    border-radius: var(--radius-lg);
  }
  .info-num {
    flex: none; width: 28px; height: 28px; border-radius: var(--radius-full);
    background: var(--accent-soft); color: var(--accent);
    font-weight: 600; font-size: var(--text-sm); font-family: var(--font-body);
    display: grid; place-items: center;
  }
  .info-item-text { line-height: 1.5; flex: 1; }

  /* Per-field text size overrides applied via data-field-size on the editable
     wrapper. Use !important so they override inherited h1/h2/p font-size from
     the typography scale (CSS-cascade specificity alone isn't enough because
     the parent h1 sets px font-size directly, not via inheritance). */
  [data-field-size="small"]  { font-size: 0.75em !important; }
  [data-field-size="normal"] { font-size: 1em !important; }
  [data-field-size="large"]  { font-size: 1.3em !important; }
  [data-field-size="xl"]     { font-size: 1.75em !important; }
  [data-field-size="huge"]   { font-size: 2.3em !important; }

  /* Introduction page — book-chapter feel with side rails and indented paragraphs */
  .intro-body {
    padding-block: var(--space-12) var(--space-16);
    position: relative;
  }
  .intro-body .prose {
    max-width: 62ch;
    margin-inline: auto;
    padding: var(--space-10) clamp(var(--space-6), 5vw, var(--space-12));
    background: var(--bg-elevated);
    border-inline: 1px solid var(--border);
    border-radius: 2px;
    box-shadow:
      0 1px 0 var(--border),
      0 24px 48px -32px color-mix(in srgb, var(--text) 18%, transparent);
    position: relative;
  }
  /* Subtle inner "page" rules on either side of the column */
  .intro-body .prose::before,
  .intro-body .prose::after {
    content: '';
    position: absolute;
    top: var(--space-8);
    bottom: var(--space-8);
    width: 1px;
    background: color-mix(in srgb, var(--accent) 22%, transparent);
  }
  .intro-body .prose::before { left: var(--space-4); }
  .intro-body .prose::after  { right: var(--space-4); }
  .intro-body h1 {
    font-family: var(--font-head);
    font-size: clamp(1.75rem, 3.4vw, var(--text-3xl));
    line-height: 1.2;
    margin-bottom: var(--space-8);
    text-align: center;
  }
  .intro-body .block,
  .intro-body p {
    font-size: var(--text-base);
    line-height: 1.75;
    margin-bottom: var(--space-5);
    text-align: left;     /* Word-doc default — no forced justification */
    hyphens: none;        /* never break words across lines */
    -webkit-hyphens: none;
    word-break: normal;
    overflow-wrap: break-word;  /* long URLs still wrap, but ordinary words don't get hyphenated */
    text-indent: 2em;     /* book-style paragraph indent */
  }
  /* Every paragraph gets the same tab indent (matches what admin preview shows). */
  .intro-body .block-text { text-indent: 2em; }
  /* When inside the intro layout, the generic .content section's prose padding
     would double up — strip it so blocks sit inside the page panel cleanly. */
  .intro-body .content { padding-block: 0; }
  .intro-body .content .layout.prose { padding: 0; background: transparent; border: 0; box-shadow: none; }
  .intro-body .content .layout.prose::before,
  .intro-body .content .layout.prose::after { display: none; }
  @media (max-width: 640px) {
    .intro-body .prose {
      padding: var(--space-6) var(--space-5);
    }
    .intro-body .prose::before,
    .intro-body .prose::after { display: none; }
  }

  /* gallery */
  .gallery-head { padding-block: var(--space-12) var(--space-8); }
  /* Public layout: CSS columns so cards fill upward Pinterest-style — no
     vertical gaps under short cards. Reading order is column-by-column in DOM,
     but the lightbox JS re-sorts to row-major for arrow nav. */
  .gallery-grid {
    display: block;
    column-gap: var(--space-5);
    column-count: 3;
  }
  .gallery-grid > .figure {
    break-inside: avoid; -webkit-column-break-inside: avoid;
    display: block; width: 100%;
    margin: 0 0 var(--space-5);
  }
  .gallery-grid > .gallery-add { break-inside: avoid; margin-bottom: var(--space-5); }
  .gallery-grid[data-cols="1"] { column-count: 1; }
  .gallery-grid[data-cols="2"] { column-count: 2; }
  .gallery-grid[data-cols="3"] { column-count: 3; }
  .gallery-grid[data-cols="4"] { column-count: 4; }
  .gallery-grid[data-cols="auto"] { column-count: auto; column-width: 300px; }
  @media (max-width: 720px) {
    .gallery-grid[data-cols="3"], .gallery-grid[data-cols="4"] { column-count: 2; }
  }
  @media (max-width: 480px) {
    .gallery-grid[data-cols="2"], .gallery-grid[data-cols="3"], .gallery-grid[data-cols="4"] { column-count: 1; }
  }
  /* JS masonry (public.js) packs BOTH the public gallery and the admin editor:
     items get position:absolute and DOM order == grid reading order (item 0
     top-left, 1 top-middle, 2 top-right, then shortest-column packing). So the
     admin looks exactly like the live site.

     While the editor is actively dragging a card to reorder, the grid gets the
     `.is-reordering` class: it temporarily flips to a flow CSS grid so
     Sortable.js can show live reflow feedback and detect the drop slot. JS
     re-packs masonry on drop. These !important rules override the inline
     absolute pins set by the masonry packer. */
  .gallery-grid.is-reordering {
    display: grid !important;
    position: static !important;
    height: auto !important;
    gap: var(--space-4);
    column-count: revert !important;
    column-gap: revert !important;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start;
    padding-bottom: 0 !important;
  }
  .gallery-grid.is-reordering[data-cols="1"] { grid-template-columns: 1fr; }
  .gallery-grid.is-reordering[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery-grid.is-reordering[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .gallery-grid.is-reordering[data-cols="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .gallery-grid.is-reordering[data-cols="auto"] { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
  .gallery-grid.is-reordering > .figure,
  .gallery-grid.is-reordering > .gallery-add {
    position: static !important;
    top: auto !important; left: auto !important;
    width: auto !important;
    margin: 0 !important;
    max-width: none !important;
  }

  /* Masonry style: CSS columns. Shorter images allow tall images in adjacent
     columns to fill the space. Reading order is top-to-bottom, column-by-column. */
  /* Masonry style: tight CSS-columns packing on the public site, plus stripped
     card chrome so images sit nearly seamless. */
  .gallery-grid[data-style="masonry"] {
    display: block;
    column-gap: 2px;
    column-count: 3;
    padding-bottom: var(--space-2);
  }
  .gallery-grid[data-style="masonry"][data-cols="1"] { column-count: 1; }
  .gallery-grid[data-style="masonry"][data-cols="2"] { column-count: 2; }
  .gallery-grid[data-style="masonry"][data-cols="3"] { column-count: 3; }
  .gallery-grid[data-style="masonry"][data-cols="4"] { column-count: 4; }
  .gallery-grid[data-style="masonry"][data-cols="auto"] { column-count: auto; column-width: 300px; }
  .gallery-grid[data-style="masonry"] > .figure {
    break-inside: avoid; -webkit-column-break-inside: avoid;
    display: block; width: 100%;
    margin: 0 0 2px;
    border-radius: 0;
    border: 0;
    box-shadow: none;
    background: transparent;
  }
  .gallery-grid[data-style="masonry"] > .figure .frame { background: transparent; }
  .gallery-grid[data-style="masonry"] > .figure img { display: block; margin: 0; }
  .gallery-grid[data-style="masonry"] > .figure figcaption {
    padding: var(--space-2) var(--space-3) var(--space-3);
    background: transparent;
  }
  .gallery-grid[data-style="masonry"] > .figure .figure-title { margin: 0 0 var(--space-1); }
  .gallery-grid[data-style="masonry"] > .gallery-add {
    break-inside: avoid; margin-bottom: 2px;
  }
  @media (max-width: 720px) {
    .gallery-grid[data-style="masonry"][data-cols="3"],
    .gallery-grid[data-style="masonry"][data-cols="4"] { column-count: 2; }
  }
  @media (max-width: 480px) {
    .gallery-grid[data-style="masonry"][data-cols="2"],
    .gallery-grid[data-style="masonry"][data-cols="3"],
    .gallery-grid[data-style="masonry"][data-cols="4"] { column-count: 1; }
  }
  .figure {
    margin: 0; background: var(--bg-elevated); border: 1px solid var(--border);
    border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow);
    position: relative;
  }
  .gallery-grid[data-style="minimal"] .figure { background: transparent; border: 0; border-radius: var(--radius); box-shadow: none; }
  .gallery-grid[data-style="framed"]  .figure { box-shadow: none; border-color: var(--border-strong); }
  /* Frame is the crop window — must clip everything that overflows it.
     The width/height of the img inside is set inline by the renderer
     (it's > 100% to position the cropped sub-region inside the frame),
     so we do NOT force width:100% here or it would defeat the crop math. */
  .figure .frame {
    display: block;
    overflow: hidden;
    background: var(--surface-sunk);
    position: relative;  /* ensure overflow:hidden actually clips children */
  }
  .figure .frame .stage { overflow: hidden; }
  /* The reset has `img { max-width: 100% }` which would clamp the inline
     `width: 133.33%` (or whatever) that the crop+rotation math emits,
     producing white-space gaps after 90° rotation. Unset that here so the
     inline width wins. */
  .figure img { object-fit: cover; max-width: none; max-height: none; }
  /* The old `transform: scale(1.04)` hover used to look nice on the legacy
     direct-img layout, but the new render uses inline transform for crop +
     rotation + flip — applying a scale on top would break the crop math. */
  .figure figcaption { padding: var(--space-4) var(--space-5); font-size: var(--text-sm); }
  .figure .figure-title { font-family: var(--font-head); font-size: var(--text-lg); margin: 0 0 var(--space-1); line-height: 1.3; }
  .figure .caption-text { color: var(--text); margin: 0 0 var(--space-2); line-height: 1.5; }
  .figure .attribution { color: var(--text-muted); font-size: var(--text-xs); margin: 0; font-style: italic; }
  .gallery-empty { color: var(--text-muted); font-style: italic; padding-block: var(--space-12); text-align: center; }

  /* Gallery pagination */
  .pager {
    display: flex; align-items: center; justify-content: center; gap: var(--space-2);
    margin-block: var(--space-6);
    font-family: var(--font-body);
  }
  .pager-num, .pager-arrow {
    display: inline-grid; place-items: center;
    min-width: 40px; height: 40px; padding-inline: var(--space-3);
    border-radius: var(--radius-full);
    border: 1px solid var(--border-strong);
    background: var(--bg-elevated); color: var(--text);
    font-weight: 600; font-size: var(--text-sm);
    text-decoration: none;
    transition: background var(--dur-hover) var(--ease), border-color var(--dur-hover) var(--ease), color var(--dur-hover) var(--ease);
  }
  .pager-num:hover, .pager-arrow:not(.is-disabled):hover {
    border-color: var(--accent); color: var(--accent); background: var(--accent-soft);
  }
  .pager-num.is-active {
    background: var(--accent); color: var(--accent-contrast); border-color: var(--accent);
  }
  .pager-arrow.is-disabled {
    opacity: .35; cursor: not-allowed; pointer-events: none;
  }

  /* buy */
  .buy-head { padding-block: var(--space-12) var(--space-6); }
  .disclosure { color: var(--text-muted); font-size: var(--text-sm); margin-block: var(--space-6); }
  .retailer-group { margin-top: var(--space-8); }
  .retailer-group h3 { color: var(--text-muted); font-size: var(--text-sm); text-transform: uppercase; letter-spacing: .06em; font-family: var(--font-body); margin-bottom: var(--space-3); }
  .retailer-list { display: grid; gap: var(--space-3); grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); }
  .retailer-btn {
    display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
    height: 56px; padding-inline: var(--space-5);
    background: var(--bg-elevated); border: 1px solid var(--border-strong);
    border-radius: var(--radius); font-weight: 600;
    transition: border-color var(--dur-hover) var(--ease), transform var(--dur-hover) var(--ease), background var(--dur-hover) var(--ease);
  }
  .retailer-btn:hover { border-color: var(--accent); color: var(--text); transform: scale(1.035); background: var(--surface-sunk); }
  .retailer-btn .arrow { color: var(--text-muted); }
  .isbn { color: var(--text-muted); font-size: var(--text-sm); margin-top: var(--space-8); }

  /* footer */
  /* (page-cta removed per design — bottom-of-page Continue CTAs were noise.) */

  /* Sub-nav: just a centered row of buttons. No rule, no label. */
  .gallery-subnav,
  .page-subnav {
    display: flex; flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--space-3);
    margin-top: var(--space-8);
  }

  .gallery-subnav .btn,
  .page-subnav .btn {
    height: 44px;
    padding-inline: var(--space-5);
    font-size: var(--text-sm);
    min-width: 200px;
    justify-content: center;
  }
  /* End-of-chapter feel on the intro page — extra breathing room. */
  .intro-body .page-subnav { margin-top: var(--space-12); }
  @media (max-width: 640px) {
    .gallery-subnav, .page-subnav { gap: var(--space-2); }
    .gallery-subnav .btn, .page-subnav .btn { min-width: 0; flex: 1 1 auto; height: 42px; }
  }

  .footer { background: var(--surface-sunk); border-block-start: 1px solid var(--border); margin-top: var(--space-24); }
  .footer .layout { padding-block: var(--space-12); display: grid; gap: var(--space-8); }
  .footer h4 { font-family: var(--font-body); font-size: var(--text-sm); text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); margin-bottom: var(--space-3); }
  .footer a { color: var(--text-muted); font-size: var(--text-sm); }
  .footer a:hover { color: var(--accent); }
  .footer .foot-links { display: grid; gap: var(--space-2); }
  .footer .muted { color: var(--text-muted); font-size: var(--text-sm); }
  @media (min-width: 720px) { .footer .layout { grid-template-columns: 1.4fr 1fr 1fr; } }
}

/* =====================================================================
   Motion — one easing, two durations, simple opacity+translateY reveals.
   The vibe: a literary memoir site (think Atlantic, New Yorker, Penguin
   author pages). Motion supports reading, never interrupts it.
   ===================================================================== */
@layer utilities {
  [hidden] { display: none !important; }

  /* Smooth scroll for in-page anchors */
  html { scroll-behavior: smooth; }

  /* Focus + selection — refined, calm */
  :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
  ::selection { background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--text); }

  /* Thin reading-progress bar across the Introduction page */
  .read-progress {
    position: fixed; top: 0; left: 0;
    height: 2px; width: 0;
    background: var(--accent);
    z-index: 100;
    transition: width 60ms linear;
    pointer-events: none;
  }

  /* ============================================================
     ONE motion idea: a soft gradient veil sweeps top-to-bottom across
     the whole page on load. Content under the sweep gradually appears;
     there's no per-element pop-in. The same idea drives scroll-reveal —
     each section's mask animates as it enters the viewport so the
     gradient feels continuous, never jumpy.
     ============================================================ */
  @property --sweep {
    syntax: '<percentage>';
    inherits: false;
    initial-value: 0%;
  }
  /* The ONE page entrance: a soft gradient veil sweeps top-to-bottom across
     the whole <main> on load. Everything inside (hero, sections, gallery)
     uncovers together as the veil passes — there is NO per-section pop-in.
     The animation carries !important so it still plays when the OS has
     "reduce motion" on (this is a gentle, owner-requested page fade). */
  main#main {
    -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 var(--sweep, 0%), transparent calc(var(--sweep, 0%) + 16%));
            mask-image: linear-gradient(180deg, #000 0%, #000 var(--sweep, 0%), transparent calc(var(--sweep, 0%) + 16%));
    animation: pageSweep 1150ms var(--ease-soft) 40ms forwards !important;
  }
  @keyframes pageSweep {
    from { --sweep: 0%; }
    to   { --sweep: 120%; }
  }
  /* Browsers that don't yet support @property fall back to no mask
     (instant visible). Detection via @supports. */
  @supports not (background: paint(something)) {
    main#main { -webkit-mask-image: none; mask-image: none; animation: none; }
  }

  /* Per-element scroll-reveal is intentionally DISABLED — the owner wants one
     cohesive top-to-bottom page fade (above), not individual sections/text
     popping in one by one. `.reveal` is kept as an inert no-op so the JS that
     still tags elements with it (and the markup that references it) keeps
     working without hiding anything. */
  .reveal, .reveal.in {
    -webkit-mask-image: none !important;
            mask-image: none !important;
    opacity: 1 !important;
  }

  /* The hero is revealed by the page-level sweep like everything else — it has
     no separate entrance animation, so the page fades in as a single unit. */

  /* Images fade in once they decode — but DEFAULT to visible so they show
     even if the JS hook misses or loads late. JS removes the .img-pending
     class once the load event fires. */
  .figure img.img-pending,
  .hero-cover img.img-pending { opacity: 0; }
  .figure img,
  .hero-cover img {
    transition: opacity 600ms var(--ease-soft);
  }

  /* ============================================================
     Buttons — one unified, refined hover with multiple layered effects.
     All buttons (primary, secondary, sub-nav) use the same vocabulary.
     ============================================================ */
  .btn,
  .btn-primary,
  .btn-secondary {
    position: relative;
    overflow: hidden;
    background: var(--accent);
    color: var(--accent-contrast);
    border: 1px solid var(--accent);
    box-shadow:
      0 1px 0 0 color-mix(in srgb, var(--accent) 60%, #000),
      0 1px 2px -1px color-mix(in srgb, var(--accent) 70%, transparent);
    transition:
      background-color 360ms var(--ease-soft),
      border-color 360ms var(--ease-soft),
      color 360ms var(--ease-soft),
      box-shadow 420ms var(--ease-soft),
      transform 360ms var(--ease-soft);
    will-change: transform, box-shadow;
  }

  /* A soft radial highlight that appears from the cursor on hover, and
     a darker overlay that slides in from the bottom — together they make
     the hover feel multi-layered, not flat. */
  .btn::before {
    content: '';
    position: absolute; inset: 0;
    background:
      radial-gradient(circle at 50% 120%, color-mix(in srgb, #fff 22%, transparent) 0%, transparent 60%);
    opacity: 0;
    transition: opacity 420ms var(--ease-soft);
    pointer-events: none;
  }
  .btn:hover::before { opacity: 1; }

  /* Hover grows the button from its center (no translate) so the cursor can
     never sit just under an edge and trigger an up/down/up oscillation. */
  .btn:hover,
  .btn-primary:hover,
  .btn-secondary:hover {
    transform: scale(1.05);
    background: color-mix(in srgb, var(--accent) 88%, #000);
    border-color: color-mix(in srgb, var(--accent) 88%, #000);
    color: var(--accent-contrast);
    box-shadow:
      0 1px 0 0 color-mix(in srgb, var(--accent) 65%, #000),
      0 14px 28px -14px color-mix(in srgb, var(--accent) 70%, transparent),
      0 6px 14px -8px color-mix(in srgb, var(--accent) 50%, transparent);
  }
  .btn:active,
  .btn-primary:active,
  .btn-secondary:active {
    transform: scale(.97);
    transition-duration: 120ms;
    box-shadow:
      0 1px 0 0 color-mix(in srgb, var(--accent) 60%, #000),
      0 4px 10px -8px color-mix(in srgb, var(--accent) 50%, transparent);
  }

  /* Underline bar under EVERY button — fades in AND grows from the center
     outwards. Wider, more visible than before so it reads as a real detail
     rather than a hairline. */
  .btn::after {
    content: '';
    position: absolute;
    left: 50%; bottom: 8px;
    width: 56%; height: 2px;
    background: currentColor;
    border-radius: 1px;
    opacity: 0;
    transform: translateX(-50%) scaleX(0);
    transform-origin: center;
    transition:
      transform 520ms var(--ease-soft),
      opacity 360ms var(--ease-soft) 60ms;
    pointer-events: none;
  }
  .btn:hover::after {
    opacity: .9;
    transform: translateX(-50%) scaleX(1);
  }

  /* ============================================================
     Cards (gallery figures + retailer buttons) — subtle hover only.
     No layout shift, just a hint of accent + shadow softening.
     ============================================================ */
  .figure { cursor: pointer; }
  .hero-cover { cursor: pointer; }
  /* The actual hover transforms live unlayered below — see the
     "Unlayered hover overrides" block at the bottom of this file. The
     `.reveal.in { transform: none }` rule in @layer utilities would
     otherwise outrank a `.figure:hover { transform: ... }` rule placed
     inside @layer components, no matter the specificity. */
  .retailer-btn:hover { transform: scale(1.035); box-shadow: 0 12px 24px -18px color-mix(in srgb, var(--text) 25%, transparent); }
  .pager-num, .pager-arrow { transition: background 240ms var(--ease-soft), color 240ms var(--ease-soft), border-color 240ms var(--ease-soft); }

  /* ============================================================
     Nav links — single growing underline (same vocabulary as the
     primary button bar) instead of background fill on hover.
     ============================================================ */
  .nav-links a, .nav-links .nav-link {
    position: relative;
    background: transparent !important;  /* override the older fill */
  }
  .nav-links a::after, .nav-links .nav-link::after {
    content: '';
    position: absolute;
    left: var(--space-3); right: var(--space-3); bottom: 6px;
    height: 1px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 320ms var(--ease-soft);
  }
  .nav-links a:hover::after, .nav-links .nav-link:hover::after,
  .nav-links a[aria-current="page"]::after,
  .nav-links .nav-link[aria-current="page"]::after { transform: scaleX(1); }

  /* ===== Lightbox (gallery image viewer) ===================================
     Click any gallery image -> full-screen modal with soft gray backdrop,
     fade + scale entrance, close button, ESC key, arrow keys to navigate,
     and click-the-backdrop-to-close. No external dependencies. */
  .lightbox {
    position: fixed; inset: 0; z-index: 1000;
    display: none;
    flex-direction: column;
    align-items: center; justify-content: center;
    gap: var(--space-3);
    padding: var(--space-6);
  }
  .lightbox.is-mounted { display: flex; }
  .lightbox-backdrop {
    position: absolute; inset: 0;
    background: rgba(20, 18, 16, 0);
    backdrop-filter: blur(0px);
    -webkit-backdrop-filter: blur(0px);
    transition: background 380ms var(--ease-soft), backdrop-filter 380ms var(--ease-soft);
  }
  .lightbox.is-open .lightbox-backdrop {
    background: rgba(20, 18, 16, .85);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .lightbox-stage {
    position: relative; z-index: 2;
    display: grid; place-items: center;
    max-width: 100%;
    min-height: 0;            /* allow the image to shrink so caption fits */
    flex: 0 1 auto;
    opacity: 0;
    transform: scale(.92);
    transition: opacity 380ms var(--ease-soft), transform 380ms var(--ease-soft);
  }
  .lightbox.is-open .lightbox-stage { opacity: 1; transform: none; }
  /* Whatever is dropped inside the lightbox-stage (a cloned .frame OR a
     plain cover-image) gets sized to fit the viewport, preserving aspect. */
  .lightbox-stage .lightbox-frame,
  .lightbox-stage .lightbox-cover-img {
    display: block;
    max-width: min(96vw, 1600px);
    max-height: 80vh;
    width: auto; height: auto;
    border-radius: var(--radius);
    box-shadow: 0 24px 60px -20px rgba(0,0,0,.6);
    background: #1a1612;
    user-select: none;
  }
  /* Cloned gallery .frame — JS sizes it in pixels to fit the viewport while
     preserving its aspect-ratio. The nested .stage + img keep all the crop /
     rotation / filter math intact (via inline styles). The toolbar / edit
     gear from the source card are hidden inside the lightbox view. */
  .lightbox-stage .lightbox-frame {
    position: relative;
    overflow: hidden;
    display: block;
  }
  .lightbox-stage .lightbox-frame .figure-toolbar,
  .lightbox-stage .lightbox-frame .figure-edit { display: none !important; }
  /* The source frame's :hover lift/scale shouldn't fire inside the lightbox. */
  .lightbox-stage .lightbox-frame:hover { transform: none !important; box-shadow: 0 24px 60px -20px rgba(0,0,0,.6) !important; border-color: var(--border) !important; }
  /* Caption flows BELOW the image in the flex column — never overlaps it. */
  .lightbox-caption {
    position: relative;
    z-index: 2;
    flex: 0 0 auto;
    max-width: min(70ch, 92vw);
    text-align: center;
    color: rgba(255,255,255,.9);
    font-size: var(--text-sm);
    line-height: 1.5;
    background: rgba(0,0,0,.42);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 480ms var(--ease-soft) 120ms, transform 480ms var(--ease-soft) 120ms;
    pointer-events: none;
  }
  .lightbox-caption:empty { display: none; }
  .lightbox.is-open .lightbox-caption { opacity: 1; transform: none; }
  .lightbox-close, .lightbox-nav {
    position: absolute; z-index: 3;
    width: 44px; height: 44px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: rgba(255,255,255,.12);
    color: #fff;
    border: 1px solid rgba(255,255,255,.16);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    cursor: pointer;
    opacity: 0;
    transition: opacity 360ms var(--ease-soft) 80ms, background 200ms var(--ease-soft), transform 200ms var(--ease-soft);
  }
  .lightbox.is-open .lightbox-close,
  .lightbox.is-open .lightbox-nav { opacity: 1; }
  .lightbox-close { top: var(--space-5); right: var(--space-5); }
  .lightbox-prev  { left: var(--space-5); top: 50%; transform: translateY(-50%); }
  .lightbox-next  { right: var(--space-5); top: 50%; transform: translateY(-50%); }
  .lightbox-close:hover { background: rgba(255,255,255,.22); transform: scale(1.06); }
  .lightbox.is-open .lightbox-prev:hover { transform: translateY(-50%) scale(1.06); background: rgba(255,255,255,.22); }
  .lightbox.is-open .lightbox-next:hover { transform: translateY(-50%) scale(1.06); background: rgba(255,255,255,.22); }
  @media (max-width: 640px) {
    .lightbox-close, .lightbox-nav { width: 40px; height: 40px; }
    .lightbox-close { top: var(--space-3); right: var(--space-3); }
    .lightbox-prev  { left: var(--space-2); }
    .lightbox-next  { right: var(--space-2); }
  }
  @media (prefers-reduced-motion: reduce) {
    .lightbox-backdrop, .lightbox-stage, .lightbox-caption,
    .lightbox-close, .lightbox-nav { transition: none !important; }
    .lightbox-stage { transform: none; }
  }

  /* ============================================================
     Theme/palette swaps — crossfade colors so palette changes
     don't snap.
     ============================================================ */
  html, body, .nav, .footer, .figure, .btn, .takeaway, .info-item, .intro-body .prose {
    transition: background-color 280ms var(--ease-soft), color 280ms var(--ease-soft), border-color 280ms var(--ease-soft);
  }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
  body { animation: none; }
  html { scroll-behavior: auto; }
}

@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 360ms; animation-timing-function: cubic-bezier(.2, 0, 0, 1); }

/* =====================================================================
   Unlayered hover overrides — outside @layer so they beat any layered
   rule regardless of specificity. Pure scale, no translate — translating
   the element shifts the cursor relative to it and can cause hover/unhover
   oscillation when the cursor sits near the element's edge. Scale grows
   from the center without moving the bounding region's center, so the
   cursor stays "inside" cleanly. transform-origin defaults to center.

   The `transition` carries !important on purpose: the global
   `@media (prefers-reduced-motion) * { transition-duration: .001ms !important }`
   rule would otherwise snap this hover instantly. This hover scale is a small,
   hover-only affordance the site owner explicitly wants, so we keep it smooth
   and active even when the OS has "reduce motion" / "animation effects off".
   (The larger page-load sweep/reveal animations remain gated by reduced-motion
   elsewhere — only this micro-interaction is exempt.)
   ===================================================================== */
/* The transition is scoped to `body:not(.is-dnd-active)` so that DURING an
   admin drag-reorder it does NOT apply to the cards. That matters because the
   dragged element is a cloned `.figure`, and Sortable repositions that clone
   every mouse-move by setting `transform`. If this 600ms transition were live,
   the clone would smoothly LAG ~600ms behind the cursor instead of being locked
   to it — and Sortable's own reflow timing would be overridden too. With the
   class on <body> during a drag, the clone tracks the mouse 1:1 and siblings
   pre-slide using Sortable's animation. Outside of dragging (the whole public
   site), the hover transition is fully active, even under reduced-motion. */
body:not(.is-dnd-active) .figure,
body:not(.is-dnd-active) .hero-cover {
  transition:
    transform 600ms cubic-bezier(.22, 1, .36, 1),
    box-shadow 600ms cubic-bezier(.22, 1, .36, 1),
    border-color 320ms cubic-bezier(.22, 1, .36, 1) !important;
  will-change: transform;
}
.figure:hover {
  transform: scale(1.045) !important;
  box-shadow:
    0 28px 56px -22px rgba(0,0,0,.28),
    0 12px 24px -12px rgba(0,0,0,.18);
  border-color: color-mix(in srgb, var(--accent) 38%, var(--border));
  z-index: 2;
}
.hero-cover:hover {
  transform: scale(1.035) !important;
}
