/*
   DuckDB case study: page chrome around the shared system diagram.
   The diagram itself (canvas, projected labels, and the per-theme --dg-* tokens)
   is drawn and styled by shared/system-diagram.{js,css}; this file styles only
   what is specific to the scroll-driven case study: the intro, the pinned stage,
   the chapter caption card, and the no-JS fallback.
    */

/* Intro */
.dg-intro {
  min-height: 76svh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 90px 24px 36px;
}
.dg-intro h1 {
  font-family: "Space Grotesk", sans-serif;
  font-size: clamp(2.4rem, 5.6vw, 4.2rem);
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -0.05em;
  margin: 0 auto 18px;
  max-width: 17ch;
  text-wrap: balance;
}
.dg-lede {
  font-size: 1.08rem;
  color: var(--muted);
  max-width: 600px;
  margin: 0 auto;
}
.dg-note {
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--muted);
  max-width: 560px;
  margin: 20px auto 0;
  padding: 12px 18px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--card-bg);
}
.dg-cue {
  width: 27px;
  height: 44px;
  margin: 42px auto 0;
  border: 2px solid var(--dg-line);
  border-radius: 999px;
  position: relative;
}
.dg-cue span {
  position: absolute;
  left: 50%;
  top: 8px;
  width: 4px;
  height: 8px;
  margin-left: -2px;
  border-radius: 4px;
  background: var(--accent);
  animation: dgCue 1.9s ease-in-out infinite;
}
@keyframes dgCue {
  0%   { transform: translateY(0); opacity: 0; }
  22%  { opacity: 1; }
  62%  { transform: translateY(15px); opacity: 1; }
  100% { transform: translateY(19px); opacity: 0; }
}
.dg-cue-text {
  margin-top: 10px;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Pinned stage */
.dg-scrolly {
  position: relative;
  height: 660vh;
  height: 660svh;
}
.dg-scrolly .dg-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
}

/* Chapter caption card */
.dg-caption-dock {
  position: absolute;
  left: 44px;
  top: 50%;
  transform: translateY(-50%);
  width: 340px;
  z-index: 3;
}
.dg-caption {
  background: var(--nav-bg);
  backdrop-filter: blur(16px);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 20px 22px 16px;
  box-shadow: var(--shadow);
}
/* Chapter transition: the old content slides out as a ghost while the new
   content wipes in from the direction of travel; the card height morphs. */
.dg-cap-swap {
  position: relative;
  overflow: hidden;
  transition: height 0.34s cubic-bezier(0.33, 1, 0.5, 1);
}
.dg-cap-ghost {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  pointer-events: none;
}
.dg-swap-down .dg-cap-ghost { animation: dgCapOutUp 0.28s cubic-bezier(0.55, 0, 0.55, 0.2) both; }
.dg-swap-up   .dg-cap-ghost { animation: dgCapOutDown 0.28s cubic-bezier(0.55, 0, 0.55, 0.2) both; }
.dg-swap-down .dg-cap-enter { animation: dgCapInUp 0.44s cubic-bezier(0.16, 1, 0.3, 1) 0.08s both; }
.dg-swap-up   .dg-cap-enter { animation: dgCapInDown 0.44s cubic-bezier(0.16, 1, 0.3, 1) 0.08s both; }
@keyframes dgCapOutUp   { to { opacity: 0; transform: translateY(-18px); } }
@keyframes dgCapOutDown { to { opacity: 0; transform: translateY(18px); } }
@keyframes dgCapInUp {
  from { opacity: 0; transform: translateY(26px); clip-path: inset(45% 0 0 0); }
  to   { opacity: 1; transform: translateY(0);    clip-path: inset(0 0 0 0); }
}
@keyframes dgCapInDown {
  from { opacity: 0; transform: translateY(-26px); clip-path: inset(0 0 45% 0); }
  to   { opacity: 1; transform: translateY(0);     clip-path: inset(0 0 0 0); }
}
.dg-cap-kicker {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-bottom: 6px;
}
.dg-cap-num {
  font-family: "Space Grotesk", sans-serif;
  font-size: 1.7rem;
  font-weight: 800;
  letter-spacing: -0.04em;
  background: var(--brand-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.dg-cap-total {
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--muted);
}
.dg-cap-body h2 {
  font-family: "Space Grotesk", sans-serif;
  font-size: 1.32rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  margin: 0 0 8px;
}
.dg-cap-body p {
  font-size: 0.92rem;
  line-height: 1.62;
  color: var(--text);
  opacity: 0.92;
  margin: 0;
}
.dg-cap-stats {
  display: flex;
  gap: 10px;
  margin-top: 14px;
  flex-wrap: wrap;
}
.dg-cap-stats span {
  font-size: 0.74rem;
  color: var(--muted);
  border: 1px solid var(--border);
  background: var(--card-bg);
  border-radius: 999px;
  padding: 5px 12px;
}
.dg-cap-stats b {
  font-family: "Space Grotesk", sans-serif;
  font-weight: 800;
  color: var(--highlight);
  margin-right: 4px;
}
/* The card carries no CTA of its own: the copy cloned into it hides its link,
   and the real call to action is the button docked below the card. It reveals
   only on the final chapter, the conclusion of the walkthrough. */
.dg-cap-body .dg-copy-cta { display: none; }
.dg-try-btn {
  display: none;
  width: 100%;
  justify-content: center;
  margin-top: 12px;
}
.dg-caption-dock.show-try .dg-try-btn {
  display: inline-flex;
  animation: dgTryIn 0.4s ease 0.1s both;
}
@keyframes dgTryIn {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}
.dg-cap-steps {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 16px;
  padding-top: 13px;
  border-top: 1px solid var(--border);
}
.dg-cap-steps .dg-tick {
  width: 24px;
  height: 18px;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.dg-cap-steps .dg-tick::before {
  content: "";
  width: 100%;
  height: 4px;
  border-radius: 4px;
  background: var(--dg-line);
  transition: background 0.2s ease, transform 0.2s ease;
}
.dg-cap-steps .dg-tick:hover::before { transform: scaleY(1.6); }
.dg-cap-steps .dg-tick[aria-current="true"]::before { background: var(--brand-grad); }
/* up / down chapter buttons */
.dg-cap-nav {
  width: 27px;
  height: 27px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--card-bg);
  color: var(--muted);
  cursor: pointer;
  display: grid;
  place-items: center;
  transition: color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.dg-cap-steps .dg-tick + .dg-cap-nav { margin-left: auto; }
.dg-cap-nav svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.dg-cap-nav:hover:not(:disabled) {
  color: var(--text);
  border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  transform: translateY(-1px);
}
.dg-cap-nav:disabled { opacity: 0.35; cursor: default; }

/* Fallback article: the same chapter copy as a plain page when JS is off.
   (It is also the source the caption card clones from.) */
.dg-fallback {
  display: none;
  max-width: 660px;
  padding-top: 30px;
  padding-bottom: 90px;
}
.dg-fallback h2 {
  font-size: 1.5rem;
  margin: 34px 0 8px;
}
.dg-fallback p {
  color: var(--text);
  opacity: 0.92;
  line-height: 1.7;
}

/* Closing CTA: run the same case study locally in a Jupyter notebook */
.dg-notebook {
  padding-top: 20px;
  padding-bottom: 100px;
}
.dg-notebook-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  max-width: 820px;
  margin: 0 auto;
  padding: 32px 36px;
  border: 1px solid color-mix(in srgb, var(--accent) 22%, transparent);
  border-radius: 16px;
  background: color-mix(in srgb, var(--accent) 6%, var(--surface, transparent));
}
.dg-notebook-copy .eyebrow { margin-bottom: 10px; }
.dg-notebook-copy h2 {
  font-size: 1.5rem;
  margin: 0 0 8px;
}
.dg-notebook-copy p {
  margin: 0;
  color: var(--text);
  opacity: 0.9;
  line-height: 1.65;
}
.dg-notebook-btn { flex: none; white-space: nowrap; }

@media (max-width: 720px) {
  .dg-notebook-card {
    flex-direction: column;
    align-items: flex-start;
    padding: 26px 24px;
  }
}

/* Small screens: the caption compacts (label rules live in system-diagram.css) */
@media (max-width: 899px) {
  /* the floating buttons would sit on top of the diagram; the caption CTA
     and the footer keep both destinations reachable */
  .contact-fab, .discord-fab { display: none; }
  .dg-caption { padding: 14px 16px 12px; }
  .dg-cap-kicker { margin-bottom: 3px; }
  .dg-cap-num { font-size: 1.25rem; }
  .dg-cap-body h2 { font-size: 1.04rem; margin-bottom: 5px; }
  .dg-cap-body p { font-size: 0.8rem; line-height: 1.5; }
  .dg-cap-stats { margin-top: 9px; }
  .dg-cap-stats span { font-size: 0.68rem; padding: 4px 10px; }
  .dg-try-btn { margin-top: 10px; font-size: 0.78rem; padding: 9px 14px; }
  .dg-cap-steps { margin-top: 11px; padding-top: 9px; }
  .dg-cap-nav { width: 24px; height: 24px; }
  .dg-cap-nav svg { width: 11px; height: 11px; }
}

/* Phones held upright: the caption docks under the nav, the diagram gets the
   rest (accelerator.js keys off the same query for label placement) */
@media (max-width: 899px) and (orientation: portrait) {
  .dg-caption-dock {
    left: 14px;
    right: 14px;
    top: 82px;
    bottom: auto;
    transform: none;
    width: auto;
  }
  .dg-intro { min-height: 66svh; }
}

/* Phones held sideways: keep the desktop side-card layout, but pin the card
   below the nav — centering it vertically would push it behind the nav */
@media (max-width: 899px) and (orientation: landscape) {
  .dg-caption-dock {
    left: 16px;
    top: 76px;
    bottom: auto;
    transform: none;
    width: min(320px, 44vw);
    max-height: calc(100svh - 86px);
    overflow-y: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .dg-cue span { animation: none; top: 14px; opacity: 1; }
  /* theme.css disables all animation under reduced motion; the chapter swap is
     a small, contained transition the walkthrough needs, so re-enable it here */
  .dg-swap-down .dg-cap-ghost { animation: dgCapOutUp 0.28s cubic-bezier(0.55, 0, 0.55, 0.2) both !important; }
  .dg-swap-up   .dg-cap-ghost { animation: dgCapOutDown 0.28s cubic-bezier(0.55, 0, 0.55, 0.2) both !important; }
  .dg-swap-down .dg-cap-enter { animation: dgCapInUp 0.44s cubic-bezier(0.16, 1, 0.3, 1) 0.08s both !important; }
  .dg-swap-up   .dg-cap-enter { animation: dgCapInDown 0.44s cubic-bezier(0.16, 1, 0.3, 1) 0.08s both !important; }
  .dg-cap-swap { transition: height 0.34s cubic-bezier(0.33, 1, 0.5, 1) !important; }
}
