/* Post page CSS — reading progress + article + TOC + prev/next. */

.reading-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: transparent;
  z-index: 35;
  pointer-events: none;
}
.reading-progress > div {
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, #0ea5e9, #6366f1);
  transform-origin: 0 50%;
  transform: scaleX(0);
  will-change: transform;
}
/* Pure CSS scroll-driven fill — Chrome/Edge 115+, Safari 26+. */
@supports (animation-timeline: scroll()) {
  .reading-progress > div {
    animation: reading-progress-fill linear both;
    animation-timeline: scroll(root);
  }
  @keyframes reading-progress-fill {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
  }
}
@media (prefers-reduced-motion: reduce) {
  .reading-progress > div { animation-duration: 0s !important; }
}

.article-grid {
  display: grid;
  gap: 2rem;
  grid-template-columns: 1fr;
}
@media (min-width: 1024px) { .article-grid { grid-template-columns: minmax(0, 1fr) 240px; } }

/* TOC layout — inline (mobile) vs sidebar (desktop) */
.toc-inline-wrap { margin: 1.5rem 0 2rem; }
.toc-sidebar-wrap { display: none; }
@media (min-width: 1024px) {
  .toc-inline-wrap { display: none; }
  .toc-sidebar-wrap { display: block; }
}

article.post { max-width: 65ch; }
@media (min-width: 1024px) { article.post { max-width: none; } }

/*
 * Cover image — fixed 1536x1024 (3:2) ratio per ADR-020 (gpt-image-2 spec).
 * Intrinsic ratio comes from the `width=1536 height=1024` HTML attributes
 * Next.js Image emits — modern browsers compute aspect-ratio from those
 * automatically, so we MUST NOT override with a CSS `aspect-ratio` here
 * (doing so conflicted with width=100%/height=auto and rendered portrait).
 */
.post-cover {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 0.75rem;
  margin-bottom: 1.5rem;
  background: #f3f4f6;
}

/*
 * Post title bar — full editorial header, in document flow (NOT sticky).
 * Scrolls naturally with the article. The compact stuck UI lives in a
 * separate `<StickyOverlay>` fixed-position element so transitioning to
 * compact never reflows the page (no scroll jump).
 */
.post-title-bar {
  margin: 0 0 1.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.post-title-bar h1,
.post-title-bar .post-section,
.post-title-bar .post-meta {
  margin: 0;
}
.post-section {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.post-title-bar h1 {
  font-size: 1.875rem;
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.25;
  min-width: 0;
}
@media (min-width: 768px) { .post-title-bar h1 { font-size: 2.25rem; } }
.post-meta { font-size: 0.875rem; color: var(--ink-muted); }

/*
 * Sticky overlay — fixed-position compact strip with TOC dropdown.
 * Mounted by `<StickyOverlay>` (client component) above article-grid;
 * IntersectionObserver toggles `data-visible="true|false"` based on whether
 * the in-flow `.post-title-bar` has scrolled past the viewport top.
 *
 * Hidden by default (opacity 0 + translateY -4px + pointer-events none).
 * No layout flow impact, so morphing in/out never causes scroll jump.
 *
 * Hidden entirely on desktop (≥1024px) — sidebar TOC is the primary
 * affordance there and the article is wide enough to keep the in-flow
 * title bar reachable via scroll.
 */
/*
 * IMPORTANT: this element MUST NOT carry `backdrop-filter`, `transform`,
 * `filter`, `perspective`, or `will-change` for those properties — any of
 * them would create a containing block and trap the child `.sticky-
 * overlay-backdrop` (`position: fixed`) inside this overlay's box,
 * breaking the viewport-wide blur. Glass effects therefore live on the
 * `.sticky-overlay-bar` and `.sticky-overlay-toc-panel` children only.
 */
.sticky-overlay {
  position: fixed;
  top: 48px; /* sits directly under the global site-header */
  left: 0;
  right: 0;
  z-index: 30;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease-out;
}
.sticky-overlay[data-visible="true"] {
  opacity: 1;
  pointer-events: auto;
}
@media (min-width: 1024px) {
  /* Desktop = sidebar TOC handles overview; hide the compact overlay. */
  .sticky-overlay { display: none; }
}

.sticky-overlay-bar {
  position: relative;
  z-index: 2; /* above the backdrop */
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem max(1rem, calc((100vw - 1100px) / 2));
  height: 40px;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: saturate(180%) blur(10px);
  -webkit-backdrop-filter: saturate(180%) blur(10px);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 4px 12px -8px rgba(0, 0, 0, 0.18);
}

/*
 * Glassmorphism backdrop — covers the entire viewport (below the strip)
 * while the TOC panel is open. Parent `.sticky-overlay` has no containing-
 * block-creating property (no transform/filter/backdrop-filter/perspective)
 * so this `position: fixed` truly anchors to the viewport.
 *
 * Why `100vw` / `100dvh`: explicit sizing instead of inset:0 prevents any
 * stale containing-block accident from collapsing the layer.
 */
.sticky-overlay-backdrop {
  position: fixed;
  top: 88px; /* below site-header (48px) + overlay bar (40px) */
  left: 0;
  width: 100vw;
  height: calc(100dvh - 88px);
  z-index: 1;
  /* Light glass — frosted but visually airy; not dark-tinted. */
  background: rgba(255, 255, 255, 0.32);
  backdrop-filter: blur(6px) saturate(115%);
  -webkit-backdrop-filter: blur(6px) saturate(115%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease-out;
  cursor: pointer;
  /* Block touch / wheel pass-through so the page doesn't drag while open. */
  touch-action: none;
  overscroll-behavior: contain;
}
/* Fallback for browsers without dvh support — fall back to vh. */
@supports not (height: 100dvh) {
  .sticky-overlay-backdrop { height: calc(100vh - 88px); }
}
.sticky-overlay[data-toc-open="true"] .sticky-overlay-backdrop {
  opacity: 1;
  pointer-events: auto;
}
.sticky-overlay-section {
  font-size: 0.65rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--accent);
  flex-shrink: 0;
}
.sticky-overlay-title {
  flex: 1 1 0;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.875rem;
  font-weight: 700;
  color: var(--ink);
}
.sticky-overlay-toc-toggle {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.3rem 0.55rem;
  background: var(--surface, #f3f4f6);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.sticky-overlay-toc-toggle:hover {
  background: rgba(14, 165, 233, 0.08);
  border-color: var(--accent);
  color: var(--accent);
}
.sticky-overlay-toc-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}
.sticky-overlay-toc-toggle svg:last-child {
  transition: transform 0.18s ease-out;
}
.sticky-overlay[data-toc-open="true"] .sticky-overlay-toc-toggle svg:last-child {
  transform: rotate(180deg);
}
.sticky-overlay-toc-label { font-weight: 600; }
.sticky-overlay-toc-count {
  color: var(--ink-muted);
  font-weight: 500;
  font-size: 0.7rem;
}

/* TOC dropdown panel — slides down from below the bar, sits above backdrop */
.sticky-overlay-toc-panel {
  position: relative;
  z-index: 2; /* above the glass backdrop */
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.22s ease-out;
  background: rgba(255, 255, 255, 0.92);
  border-top: 1px solid var(--line);
  box-shadow: 0 12px 28px -16px rgba(0, 0, 0, 0.32);
}
.sticky-overlay[data-toc-open="true"] .sticky-overlay-toc-panel {
  max-height: 60vh;
  overflow-y: auto;
}
.sticky-overlay-toc-list {
  list-style: none;
  padding: 0.5rem 0.75rem;
  margin: 0;
  max-width: 1100px;
  margin: 0 auto;
}
.sticky-overlay-toc-list li { line-height: 1.4; }
.sticky-overlay-toc-list a {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  text-decoration: none;
  border-radius: 0.3rem;
  transition: background 0.12s, color 0.12s;
}
.sticky-overlay-toc-list .toc-l2 a {
  padding: 0.45rem 0.5rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink);
}
.sticky-overlay-toc-list .toc-l3 a {
  padding: 0.35rem 0.5rem 0.35rem 1.5rem;
  font-size: 0.8125rem;
  color: var(--ink-muted);
}
.sticky-overlay-toc-list a:hover {
  background: rgba(14, 165, 233, 0.06);
  color: var(--accent);
}
.sticky-overlay-toc-list .toc-bullet {
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.4;
  flex-shrink: 0;
  transform: translateY(-2px);
}
.sticky-overlay-toc-list .toc-l3 .toc-bullet { width: 3px; height: 3px; }
.sticky-overlay-toc-list .toc-text {
  flex: 1;
  min-width: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
@media (prefers-reduced-motion: reduce) {
  .sticky-overlay,
  .sticky-overlay-toc-panel,
  .sticky-overlay-toc-toggle svg:last-child,
  .sticky-overlay-backdrop {
    transition: none !important;
  }
}

article.post h2 {
  font-size: 1.5rem;
  font-weight: 700;
  margin: 2.5rem 0 0.75rem;
  line-height: 1.35;
  scroll-margin-top: 80px;
}
article.post h3 {
  font-size: 1.125rem;
  font-weight: 600;
  margin: 1.75rem 0 0.5rem;
  line-height: 1.4;
  scroll-margin-top: 80px;
}
article.post p { margin: 0 0 1rem; line-height: 1.75; font-size: 1rem; }
article.post ul { padding-left: 1.25rem; margin: 0 0 1rem; color: var(--ink-muted); }
article.post ul li { margin-bottom: 0.25rem; line-height: 1.6; }
article.post strong { font-weight: 600; color: var(--ink); }
article.post .ext-link { color: var(--accent); text-decoration: underline; }

/*
 * TOC — full editorial card. Single variant.
 *   - inline (mobile, after intro): full list in document flow.
 *   - sidebar (desktop right column): same card, sticky on long articles.
 *
 * The compact "always-on" TOC at the top of the viewport is in a separate
 * `<StickyOverlay>` fixed-position element (no flow impact, no scroll jump).
 */
.toc {
  position: relative;
  border: 1px solid var(--line);
  border-radius: 0.75rem;
  background: linear-gradient(180deg, #fafafa, #fff);
  padding: 0.85rem 1rem 1rem;
}
@media (min-width: 1024px) {
  .toc-sidebar-wrap .toc {
    position: sticky;
    top: 96px;
    max-height: calc(100vh - 120px);
    overflow-y: auto;
    padding: 0.75rem 0.85rem 0.85rem;
  }
}
.toc-header {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding-bottom: 0.6rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--line);
  color: var(--ink);
}
.toc-icon { color: var(--accent); flex-shrink: 0; }
.toc-label {
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.toc-count {
  margin-left: auto;
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--ink-muted);
  padding: 0.1rem 0.45rem;
  background: var(--surface, #f3f4f6);
  border-radius: 999px;
}
.toc-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
}
.toc-list li { line-height: 1.4; }
.toc-list a {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  text-decoration: none;
  border-left: 2px solid transparent;
  border-radius: 0 0.3rem 0.3rem 0;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.toc-bullet {
  display: inline-block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.4;
  flex-shrink: 0;
  transform: translateY(-2px);
}
.toc-text {
  flex: 1;
  min-width: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.toc-l2 a {
  padding: 0.4rem 0.5rem 0.4rem 0.6rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink);
}
.toc-l3 a {
  padding: 0.3rem 0.5rem 0.3rem 1.5rem;
  font-size: 0.8125rem;
  color: var(--ink-muted);
}
.toc-l3 .toc-bullet { width: 3px; height: 3px; }
.toc-list a:hover {
  color: var(--accent);
  background: rgba(14, 165, 233, 0.06);
}
.toc-list a:hover .toc-bullet { opacity: 1; }
.toc-list a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  background: rgba(14, 165, 233, 0.06);
}
/* :target highlight — when user clicks a TOC link, the matching heading
 * becomes :target; rebound the matching TOC link visually via :has(). */
.toc-list li:has(a:target) a {
  color: var(--accent);
  border-left-color: var(--accent);
  background: rgba(14, 165, 233, 0.08);
}

.prev-next {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
  margin-top: 3rem;
  padding-top: 2rem;
  border-top: 1px solid var(--line);
}
@media (min-width: 640px) { .prev-next { grid-template-columns: 1fr 1fr; } }
.pn-card {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 1rem;
  border: 1px solid var(--line-strong);
  border-radius: 0.6rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s, transform 0.15s;
}
.pn-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.pn-empty { background: transparent; border: 1px dashed var(--line); pointer-events: none; }
@media (max-width: 639px) { .pn-empty { display: none; } }
.pn-label { font-size: 0.75rem; color: var(--ink-faint); }
.pn-section { font-size: 0.7rem; color: var(--accent); font-weight: 600; }
.pn-title { font-size: 0.95rem; font-weight: 600; line-height: 1.4; color: var(--ink); }
