/*
  css/layout.css — page-level structural layout (nav shell, home rail+grid frame).
  No color/font values here — see tokens.css (§12).

  Breakpoints below are literal px values mirroring the --bp-* tokens in
  tokens.css (480 / 768 / 1024 / 1280) — keep in sync, don't invent new ones (§9).
*/

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

body {
  font-family: var(--font-body);
  color: var(--color-text);
  background: var(--color-bg);
  /* Reserves room for the fixed-position .site-nav below, which is
     removed from normal document flow. */
  padding-top: var(--site-nav-height);
}

h1 {
  font-family: var(--font-headline);
  font-weight: 700;
  font-size: clamp(2.25rem, 1.5rem + 4vw, 3.25rem);
  line-height: 1.05;
}

/* --- Shared nav shell (markup injected by js/shared-ui.js, so this
   applies on every page that mounts #shared-nav — home + every case
   study — with one rule). Pinned to the top of the viewport so it stays
   reachable while scrolling, on every page; an opaque background keeps
   content from showing through underneath it; z-index sits above
   ordinary content and the sidenav (both default stacking) but below
   .tianne-panel (z-index: 30, components.css) so the Ask Tianne panel
   still opens on top of the nav, not under it.

   position: fixed rather than sticky — the nav's containing block is
   the full-height page, so the two are visually identical here (fixed
   just always pins; sticky would pin from the same spot with nothing
   to ever release it), and fixed measured as reliable in testing where
   sticky did not consistently composite correctly. Since fixed removes
   the nav from normal flow, `body`'s padding-top below reserves its
   height so page content doesn't render underneath it. */
.site-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-border);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 25;
  background: var(--color-bg);
}

/* Keep in sync with the nav's real rendered height — used both to
   reserve room for the now-fixed nav (body's padding-top, below) and
   so the case-study sidenav's sticky offset clears it. */
:root {
  --site-nav-height: 69px;
}

.site-nav-list {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}

/* From --bp-lg the nav is three equal-flex columns (brand | links | pill),
   so the links sit on the page's true center instead of drifting toward
   whichever side is narrower. Below that the brand block needs its natural
   width, so the flex layout above stays. */
@media (min-width: 1024px) {
  .site-nav {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
  }

  .site-nav-list {
    justify-self: center;
  }

  .site-nav .chat-toggle {
    justify-self: end;
  }
}

/* --- Home layout: mobile-first, single column (no category rail — the
   main content fills the full width at every size). --- */
.home-layout {
  display: block;
  padding: var(--space-4);
}

/* Generous outer margins on wider screens: the grid sits inset from the
   window edges rather than running edge to edge. */
@media (min-width: 768px) {
  .home-layout {
    padding: var(--space-4) var(--space-7);
  }
}

@media (min-width: 1024px) {
  .home-layout {
    padding: var(--space-4) var(--space-8);
  }
}

.home-main {
  display: block;
  /* Caps the search bar and the card grid together, so the cards are about a
     fifth smaller than when they ran the full width (2026-09-21) and the
     hero has room for the suggested questions. */
  max-width: 1100px;
  margin-inline: auto;
}

/* --- Generic content-page shell (resume/feedback/fun) --- */
.page-content {
  padding: var(--space-6) var(--space-4);
  max-width: 720px;
  margin-inline: auto;
}

.page-header {
  margin-bottom: var(--space-5);
}

.page-intro {
  color: var(--color-text-muted);
}

.page-section {
  margin-bottom: var(--space-6);
}

.page-section h2 {
  margin-bottom: var(--space-3);
  font-size: clamp(2.25rem, 1.5rem + 4vw, 3.25rem);
  line-height: 1.05;
  font-family: var(--font-headline);
  font-weight: 700;
}

/* --- Feedback page --- */
.testimonial-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.testimonial {
  border-left: 3px solid var(--color-border);
  padding-left: var(--space-4);
  margin: 0;
}

.testimonial p {
  margin-bottom: var(--space-2);
}

.testimonial cite {
  font-style: normal;
  color: var(--color-text-muted);
  font-size: 0.875rem;
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* --- Fun page --- */
.fun-gallery {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
}

/* Real photos, varying source dimensions — cropped to a consistent
   card shape rather than leaving a ragged grid of mismatched sizes. */
.fun-gallery img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: var(--radius-lg);
}

@media (min-width: 480px) {
  .fun-gallery {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .fun-gallery {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* --- Case-study page shell (projects/*) --- */
.case-study {
  padding: var(--space-6) var(--space-4);
  max-width: 720px;
  margin-inline: auto;
}

/* --- Case-study sidebar nav — sticky, scroll-spy list of section
   links, built at runtime by js/case-study-nav.js from that page's own
   headings (docs/superpowers/specs/2026-09-11-case-study-sidenav-spacing-design.md).
   Below --bp-md (768px, same breakpoint the Intelkin column layout
   already uses) the script builds a <details> accordion instead of a
   bare list — this styles both shapes. --- */
.case-study-page {
  display: block;
  margin-bottom: var(--space-6);
}

.case-study-sidenav {
  margin-bottom: var(--space-5);
}

.case-study-sidenav details {
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
}

.case-study-sidenav summary {
  cursor: pointer;
  font-family: var(--font-body);
  font-weight: 600;
  color: var(--color-text);
}

.case-study-sidenav details .case-study-sidenav-list {
  margin-top: var(--space-3);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Link styling applies identically whether the ancestor is <details>
   (mobile) or the bare hook div (desktop, below) — only the container
   layout differs by breakpoint, not the active/muted color treatment.
   padding: var(--space-2) (was --space-3) — a page with a long section
   list (Intelkin's 11 vs. e.g. Recollab's 5) was tall enough to trip
   the sticky sidenav's max-height/overflow-y on a shorter browser
   window, clipping a section link mid-line under a bare scrollbar.
   Tighter padding keeps an 11-item list fitting without scrolling on
   realistic window heights, so every case study's sidenav reads the
   same regardless of how many sections it has. */
.case-study-sidenav a {
  display: block;
  font-family: var(--font-body);
  font-size: 0.9375rem;
  color: var(--color-text-muted);
  padding: var(--space-2) 0;
}

.case-study-sidenav a.is-active {
  color: var(--color-text);
  font-weight: 600;
}

/* Sits above the section list (js/case-study-nav.js prepends it), set
   off with its own bottom border + margin rather than reading as just
   another entry in that list. */
.case-study-sidenav-back {
  display: block;
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.case-study-sidenav:empty {
  display: none;
}

@media (min-width: 768px) {
  /* Widened from 960px, and switched from a large auto-centered gutter
     to a modest fixed side padding: at typical desktop widths (up to
     1440px) the container now fills the viewport minus that fixed
     padding, so the sidenav sits close to the real left edge instead
     of a big empty margin pushing it toward the middle. Beyond 1440px
     (very wide monitors), margin-inline: auto still centers the capped
     box, but the two gutters stay a normal, comparable size on both
     sides rather than ballooning around a narrow 960px column. */
  .case-study-page {
    display: flex;
    align-items: flex-start;
    /* More room between the sidenav and the body text than the
       container's own side inset (below) — the two were previously
       tied to the same value. */
    gap: var(--space-7);
    /* No max-width/margin-inline:auto here on purpose (removed) — that
       combination re-centers the whole row on any screen wider than
       the cap (very common at 1920px+), which silently undid the
       smaller left inset below the moment a viewer's monitor exceeded
       1440px. .case-study (the content column) already caps its own
       width at 880px independently, so nothing needs this container
       to do it too — dropping it means the sidenav sits at a fixed
       distance from the real left edge on any screen size, not just
       up to 1440px. */
    padding-left: var(--space-4);
    padding-right: var(--space-6);
  }

  .case-study-sidenav {
    margin-bottom: 0;
    position: sticky;
    /* Clears the fixed site-nav's real height (--site-nav-height,
       above) plus a gap, so the sidenav starts right below the nav
       instead of sitting underneath it. */
    top: calc(var(--site-nav-height) + var(--space-5));
    flex: 0 0 180px;
    max-height: calc(100vh - var(--site-nav-height) - var(--space-5) - var(--space-6));
    overflow-y: auto;
    /* Fallback for a section list still too tall for a very short
       window even after the tighter link padding above — a themed
       thin scrollbar instead of the bare default one. */
    scrollbar-width: thin;
    scrollbar-color: var(--color-border) transparent;
  }

  .case-study-sidenav::-webkit-scrollbar {
    width: 6px;
  }

  .case-study-sidenav::-webkit-scrollbar-thumb {
    background: var(--color-border);
    border-radius: var(--radius);
  }

  .case-study-sidenav > .case-study-sidenav-list {
    display: flex;
    flex-direction: column;
    /* Tighter than the mobile accordion's list (var(--space-2)) —
       more headroom before a long section list needs the max-height
       scroll fallback above. Mobile's <details> version isn't
       height-constrained the same way, so it keeps the roomier gap. */
    gap: var(--space-1);
  }

  .case-study {
    /* Centers the 880px-capped text column within its own leftover
       flex space (margin-inline: auto works for a flex item's free
       space, same technique as a block element) — without this, the
       column hugs flush against the sidenav with all the unused
       width left as empty space on the far right, reading as
       lopsided/pinned-left rather than balanced, especially on a
       wide screen where the sidenav itself sits near the true left
       edge (previous pass) rather than the whole row being centered.
       Widened from the mobile-first 720px (still set as the base rule
       above) so the body text actually uses the extra room this
       breakpoint frees up, instead of leaving it as unused gutter. */
    max-width: 880px;
    flex: 1;
    margin-inline: auto;
    padding-inline: 0;
  }
}

.case-study-header {
  margin-bottom: var(--space-5);
}

.case-study-category {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  margin-bottom: var(--space-2);
  font-family: var(--font-label);
}

.case-study-section {
  margin-bottom: var(--space-7);
}

.case-study-section h2 {
  margin-bottom: var(--space-4);
  font-size: clamp(2.25rem, 1.5rem + 4vw, 3.25rem);
  line-height: 1.05;
  font-family: var(--font-headline);
  font-weight: 700;
}

.case-study-section p,
.case-study-section li {
  color: var(--color-text-muted);
}

/* Was inheriting body's line-height: 1.5 and reset.css's `* { margin: 0 }`
   with no override — paragraphs had no breathing room and consecutive
   <p> siblings within one section sat flush against each other.
   Direct-child combinator (>) is deliberate: .case-study-section also
   contains <p> tags several levels deep inside other components
   (case-study-stat, insight-map-quote, …) —
   those already have their own sizing and must not inherit prose
   spacing/line-height too. Only the hand-written body paragraphs are
   direct children of the section. */
.case-study-section > p {
  line-height: 1.7;
  margin-bottom: var(--space-4);
}

.case-study-section > p:last-child {
  margin-bottom: 0;
}

.case-study-back {
  margin-top: var(--space-6);
}

.case-study-back a {
  text-decoration: underline;
}

/* --- Richer case-study content patterns (used where a real writeup exists,
   e.g. projects/intelkin.html — the generic lorem template above still
   covers pages without one). --- */
.case-study-eyebrow {
  color: var(--color-text-muted);
  font-size: 0.8125rem;
  margin-top: var(--space-2);
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Hero image/gif/video — shows the animated version by default, swaps to a
   static poster frame under prefers-reduced-motion (Quality Floor, §11).
   The motion element is an <img> (gif) or a <video> (autoplay/loop/muted)
   depending on the asset; the poster is always a plain <img>. */
.case-study-hero {
  margin-bottom: var(--space-6);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  overflow: hidden;
}

.case-study-hero img,
.case-study-hero video {
  display: block;
  width: 100%;
  height: auto;
}

/* Ties .case-study-hero img/video's specificity (class+element) so this
   actually wins instead of losing the cascade to the rule above. */
img.case-study-hero-static {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  img.case-study-hero-motion,
  video.case-study-hero-motion {
    display: none;
  }

  img.case-study-hero-static {
    display: block;
  }
}

.case-study-section h3 {
  margin-top: var(--space-5);
  margin-bottom: var(--space-2);
  font-size: clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem);
  line-height: 1.2;
  color: var(--color-text);
  font-family: var(--font-headline);
  font-weight: 700;
}

.case-study-section h4 {
  margin-bottom: var(--space-1);
  font-size: 1.125rem;
  line-height: 1.3;
  color: var(--color-text);
  font-family: var(--font-headline);
  font-weight: 700;
}

.case-study-section a {
  color: var(--color-text);
  text-decoration: underline;
}

p.case-study-lede {
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--color-text);
  margin-bottom: var(--space-3);
}

.case-study-meta {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  margin-bottom: var(--space-7);
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.case-study-meta div {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.case-study-meta dt {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  font-family: var(--font-label);
}

.case-study-meta dd {
  color: var(--color-text);
}

/* Hero role/timeline/team/skills/[tech-stack] row, directly under the
   hero thumbnail — no card, no border, no background: the fields sit
   straight on the page. A plain 4-column grid on desktop (a 5th field
   wraps to a second row of the same grid automatically — 5 items in a
   4-column grid just do that, no extra rule needed), one column
   stacked on mobile. Explicitly un-sets every card property the base
   .case-study-meta above sets, since --hero is layered on top of it
   in markup (class="case-study-meta case-study-meta--hero"). Every
   current usage pairs the two together, but the base class's own
   dt/dd typography rules stay separate/unoverridden on purpose, in
   case a future non-hero use (a bordered dt/dd mini-table somewhere)
   needs the base card treatment without this modifier. */
.case-study-meta.case-study-meta--hero {
  gap: var(--space-5) var(--space-4);
  padding: 0;
  border: none;
  border-radius: 0;
  margin-bottom: var(--space-6);
}

@media (min-width: 768px) {
  .case-study-meta.case-study-meta--hero {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Multi-value fields (Skills, a multi-part Team) stack as separate
   lines in their own column rather than running together with commas —
   values are unchanged, only the separator (comma -> line break). */
.case-study-meta--hero dd.case-study-meta-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.friction-point {
  margin-bottom: var(--space-4);
}

.friction-point h3 {
  margin-top: 0;
  margin-bottom: var(--space-1);
  font-size: 1.125rem;
  line-height: 1.3;
  font-family: var(--font-headline);
  font-weight: 700;
}

.friction-meta {
  display: block;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--color-text-muted);
  margin-top: var(--space-1);
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.case-study-quote {
  margin: var(--space-5) 0;
  padding: var(--space-4);
  border-left: 3px solid var(--color-border);
}

.case-study-quote p {
  color: var(--color-text);
}

.case-study-quote cite {
  display: block;
  margin-top: var(--space-2);
  font-style: normal;
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

p.case-study-callout {
  padding: var(--space-4);
  border: 1px dashed var(--color-border);
  border-radius: var(--radius);
  color: var(--color-text);
}

.case-study-artifacts {
  font-style: italic;
}

.reflection-item {
  margin-bottom: var(--space-4);
}

/* --- Parallel-content columns — a shared case-study component for
   genuinely parallel items (a stat row, a set of findings, a set of
   takeaways) that would otherwise render as stacked full-width blocks,
   obscuring that they're parallel. Originated as a page-scoped Intelkin
   exception; promoted here once a second case study (Recollab) needed
   the same pattern, per "reuse, don't build parallel new components."
   Stacks to one column below 768px, matching the site's named-breakpoint
   convention (§9/§11). --- */
.case-study-columns {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5) var(--space-4);
}

@media (min-width: 768px) {
  .case-study-columns--2 {
    grid-template-columns: repeat(2, 1fr);
  }

  .case-study-columns--3 {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* .friction-point / .reflection-item carry their own margin-bottom for
   the single-column case elsewhere on the site; inside this grid it's
   redundant since `gap` already spaces the columns. */
.case-study-columns > .friction-point,
.case-study-columns > .reflection-item {
  margin-bottom: 0;
}

.case-study-column {
  /* Market Research's three parallel-approach columns — no dedicated
     component of their own, just this top-margin reset so they align
     with .friction-point/.reflection-item's own zeroing above. */
}

.case-study-columns > .case-study-column h3 {
  margin-top: 0;
}

/* A single stat: a big Headline-tier number/claim (h3) over a short
   Body-tier label (p) — e.g. "8x faster" / "Quote turnaround". Meant to
   sit inside .case-study-columns, same as .friction-point. Font-family
   already comes from .case-study-section h3 (Headline tier); this only
   adds the extra size/spacing a stat callout needs over an ordinary
   sub-headline. */
.case-study-stat h3 {
  font-size: 1.75rem;
  margin-top: 0;
}

.case-study-stat p {
  margin-top: var(--space-1);
}

/* Real image + caption — once a real asset replaces a media-placeholder
   (e.g. the Intelkin research moodboard). */
.case-study-figure {
  margin: 0 0 var(--space-5);
}

.case-study-figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid var(--color-border);
}

.case-study-figure figcaption {
  margin-top: var(--space-2);
  font-size: 0.8125rem;
  color: var(--color-text-muted);
}

/* Theme Clustering visual (research-aggregator.html) — two real screenshots
   (raw sticky notes going in, AI-grouped themes coming out) inside a small
   bordered/surface container with a top micro-label, connected by a plain
   gray arrow. No accent color here deliberately: CLAUDE.md §12 reserves
   the accent for tiny moments, and this container is a new pattern, not a
   reuse of an existing "labeled gray container" component (no such
   component existed site-wide when this was built — closest neighbors are
   .laptop-frame and .insight-map-card, whose surface/border/label styling
   this borrows). Mobile-first: stacked with the arrow pointing down; side
   by side with the arrow pointing right from --bp-md up. */
.case-study-visual {
  margin: 0 0 var(--space-5);
  padding: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

/* Extra breathing room above a .case-study-visual that follows dense
   content directly (e.g. the frequency/impact quadrant sitting right
   under the Human Fallback Triggers grid) — not the default spacing,
   since most .case-study-visual instances already get enough gap from
   the preceding paragraph's own margin-bottom. */
.case-study-visual--spaced {
  margin-top: var(--space-6);
}

.case-study-visual-label {
  margin: 0 0 var(--space-4);
  font-family: var(--font-label);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
}

.case-study-visual-pair {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}

.case-study-visual-item {
  margin: 0;
  width: 100%;
}

.case-study-visual-item img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  border: 1px solid var(--color-border);
}

.case-study-visual-item figcaption {
  margin-top: var(--space-2);
  text-align: center;
  font-family: var(--font-label);
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
}

/* Wide screenshots (Intelkin's Recollab before/after) stay stacked at every
   size: side by side each would shrink to unreadable. */
@media (min-width: 768px) {
  .case-study-visual-pair.case-study-visual-pair--stacked {
    flex-direction: column;
  }

  .case-study-visual-pair--stacked .case-study-visual-arrow {
    transform: rotate(90deg);
  }
}

.case-study-visual-arrow {
  display: block;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--color-text-muted);
  transform: rotate(90deg);
}

@media (min-width: 768px) {
  .case-study-visual-pair {
    flex-direction: row;
  }

  .case-study-visual-arrow {
    transform: none;
  }
}

/* "The Redesign" 3-step diagram (research-aggregator.html, Approach) —
   sits inside .case-study-visual, reuses .case-study-visual-arrow as the
   connector between steps. The middle step is the only AI-assisted one,
   so it's the only one that gets --color-accent — everything else here
   stays plain white/border, per the prompt's own "don't add any other
   color" instruction. Note: the source prompt called for "accent
   orange," but this site's confirmed accent (CLAUDE.md §12) is Oxblood
   red, not orange — no orange exists anywhere in tokens.css, so this
   uses the real --color-accent rather than inventing an undisclosed new
   color. Mobile-first column stack; row at --bp-md, same breakpoint as
   the Theme Clustering pair above. */
.case-study-steps {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-3);
}

.case-study-step {
  flex: 1;
  padding: var(--space-3);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  text-align: center;
}

.case-study-step p {
  margin: 0;
  font-family: var(--font-label);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text);
}

.case-study-step--accent {
  background: var(--color-accent);
  border-color: var(--color-accent);
}

.case-study-step--accent p {
  color: var(--color-accent-text);
}

@media (min-width: 768px) {
  .case-study-steps {
    flex-direction: row;
    align-items: center;
  }
}

/* Frequency vs Impact quadrant (research-aggregator.html, Human Fallback
   Triggers) — a qualitative scatter illustrating the "single mention,
   high impact" trigger, not a precise data chart. Two thin gray axes
   with CSS-triangle arrowheads; four small point-cards positioned by eye
   via per-point --x/--y custom properties (percentages within the plot,
   set inline since each point's position is one-off layout data, not a
   reusable style). Sits inside .case-study-visual, same as the two
   components above. Only the single flagged outlier (P7) gets the real
   site accent, matching the "one AI/exception moment" restraint used in
   the step diagram above — same "not actually orange" note applies. */
.quadrant-plot {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  min-height: 340px;
}

.quadrant-axis {
  position: absolute;
  background: var(--color-text-muted);
}

.quadrant-axis--x {
  left: 6%;
  right: 10%;
  bottom: 10%;
  height: 1px;
}

.quadrant-axis--y {
  left: 6%;
  top: 18%;
  bottom: 10%;
  width: 1px;
}

.quadrant-arrow {
  position: absolute;
  width: 0;
  height: 0;
  border: 5px solid transparent;
}

.quadrant-arrow--x {
  right: calc(10% - 9px);
  bottom: calc(10% - 5px);
  border-left-color: var(--color-text-muted);
  border-right-width: 0;
}

.quadrant-arrow--y {
  left: calc(6% - 5px);
  top: calc(18% - 9px);
  border-bottom-color: var(--color-text-muted);
  border-top-width: 0;
}

.quadrant-label {
  position: absolute;
  font-family: var(--font-body);
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.quadrant-label--x {
  right: 0;
  bottom: calc(10% - 6px);
}

.quadrant-label--y {
  left: 9%;
  top: 8%;
}

.quadrant-point {
  position: absolute;
  left: var(--x);
  top: var(--y);
  max-width: 180px;
  margin: 0;
  padding: var(--space-3) var(--space-4);
  transform: translate(-50%, -50%);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  font-family: var(--font-label);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1.35;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--color-text);
}

.quadrant-point--flagged {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-text);
}

/* Sample terminal output (research-aggregator.html, Approach's Theme
   Clustering step) — a static sibling to Intelkin's .terminal-card
   (projects/intelkin.html), not the same component. Shares its real
   colors and the site's one disclosed non-tokens.css font exception
   (--font-mono, see tokens.css) and reuses .terminal-card-titlebar /
   .terminal-dot* / .terminal-prompt / .terminal-cmd / .terminal-output
   as-is, since those are purely visual with no attached behavior. Does
   NOT reuse .terminal-card itself: that class carries a click-to-open
   affordance (cursor:pointer, hover lift, pulsing glow, blinking
   cursor) built for a link to a real repo — wiring that onto a block of
   static sample output that links nowhere would visually promise a
   click that does nothing. */
.terminal-static-card {
  width: 100%;
  margin: 0 0 var(--space-5);
  background: #0d0d0f;
  border-radius: 10px;
  overflow: hidden;
}

.terminal-static-body {
  margin: 0;
  padding: 20px 18px;
  font-family: var(--font-mono);
  font-size: 13.5px;
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-word;
}

/* A wide diagram that doesn't fit the column at a legible size (e.g. a
   long linear flowchart) scrolls horizontally instead of shrinking past
   readability — CLAUDE.md §9's "wide content scrolls in its own
   container" rule, applied to an image instead of a table/code block. */
.case-study-scroll {
  overflow-x: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
}

.case-study-scroll img {
  display: block;
  width: auto;
  height: 130px;
  max-width: none;
  border: none;
  border-radius: 0;
}

/* Sub-beat: a smaller headline + one line + its own visual, nested under a
   section's main lede (e.g. the three "How It Works" steps). */
.case-study-subbeat {
  margin-bottom: var(--space-5);
}

.case-study-subbeat h3 {
  margin-top: 0;
  margin-bottom: var(--space-2);
  font-size: clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem);
  line-height: 1.2;
  font-family: var(--font-headline);
  font-weight: 700;
}

/* Light laptop-frame mockup for step gifs whose UI content is dark —
   a dark bezel would let the gif's own edges disappear into it, so the
   frame is deliberately light regardless of the gif inside it. Front-on
   view: bezel (with a centered camera dot) around the screen, a flat
   base bar with a trackpad notch underneath. Reused as-is everywhere a
   dark-UI step gif needs one, so a set of them reads as one consistent
   device rather than three different mockups. */
.laptop-frame {
  margin-bottom: var(--space-5);
  padding: var(--space-3) var(--space-3) 0;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.laptop-frame-camera {
  display: block;
  width: 6px;
  height: 6px;
  margin: 0 auto var(--space-2);
  border-radius: 50%;
  background: var(--color-text-muted);
}

.laptop-frame-screen {
  overflow: hidden;
  border: 1px solid var(--color-text);
  border-radius: calc(var(--radius) / 2);
}

.laptop-frame-screen img {
  display: block;
  width: 100%;
  height: auto;
}

.laptop-frame-base {
  position: relative;
  height: 14px;
  margin-top: var(--space-2);
  border-top: 1px solid var(--color-border);
  border-radius: 0 0 var(--radius) var(--radius);
}

.laptop-frame-notch {
  position: absolute;
  top: 0;
  left: 50%;
  width: 56px;
  height: 4px;
  transform: translateX(-50%);
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--color-border);
}

@media (min-width: 480px) {
  .case-study-meta {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* --- Terminal-style repo card ("Where It Is Now", projects/intelkin.html)
   Deliberate, scoped exception to CLAUDE.md §10's grayscale-only status:
   this recreates a real terminal window (macOS traffic-light dots, ANSI
   syntax-highlight colors), so it needs real colors to read as an
   authentic terminal rather than site chrome — the same reasoning that
   already let the Intelkin product screenshots/gifs stay full-color.
   Nothing here feeds into or changes the site's still-pending palette;
   every other component still routes through tokens.css exclusively.
   Values match a prototyped reference build exactly. Click/Enter-to-open
   behavior lives in js/intelkin-terminal.js (page-specific, not shared). */
.terminal-card {
  display: block;
  width: 100%;
  margin: 0 0 var(--space-3);
  border-radius: 10px;
  background: #0d0d0f;
  font-family: var(--font-mono);
  overflow: hidden;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  animation: terminal-pulse-glow 3.2s ease-in-out infinite;
}

.terminal-card:hover,
.terminal-card:focus-visible {
  outline: none;
  transform: translateY(-2px);
  /* !important: the resting-state pulse (terminal-pulse-glow) keeps
     animating box-shadow at CSS Animation priority, which otherwise
     outranks this plain rule and fights it every cycle — matches the
     reference build's own fix for the same conflict. */
  box-shadow:
    0 0 0 1px #4a4a4e,
    0 0 32px rgba(95, 217, 122, 0.24),
    0 6px 16px rgba(0, 0, 0, 0.35) !important;
}

@keyframes terminal-pulse-glow {
  0%, 100% {
    box-shadow: 0 0 0 1px #2a2a2e, 0 1px 3px rgba(0, 0, 0, 0.3);
  }
  50% {
    box-shadow:
      0 0 0 1px #3a3a3e,
      0 0 26px rgba(95, 217, 122, 0.16),
      0 1px 3px rgba(0, 0, 0, 0.3);
  }
}

.terminal-card-titlebar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 16px;
  background: #1c1c1e;
  border-bottom: 1px solid #2a2a2c;
}

.terminal-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  flex: 0 0 auto;
}

.terminal-dot--red {
  background: #ff5f56;
}

.terminal-dot--yellow {
  background: #ffbd2e;
}

.terminal-dot--green {
  background: #27c93f;
}

.terminal-card-titletext {
  margin-left: 8px;
  font-size: 12px;
  color: #6f6f74;
}

.terminal-card-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 20px 18px;
  font-size: 13.5px;
  line-height: 1.7;
}

.terminal-line--cursor {
  margin-top: 4px;
}

.terminal-prompt {
  color: #5fd97a;
}

/* The hint is typed on the live prompt line (js/intelkin-terminal.js), as if
   entered at the shell; the cursor follows the last typed character. */
.terminal-typed {
  margin-left: 8px;
  color: #e8e8e8;
}

.terminal-dir {
  color: #8ab4ff;
}

.terminal-git {
  color: #6f6f74;
}

.terminal-branch {
  color: #ffbd2e;
}

.terminal-cmd {
  color: #e8e8e8;
}

.terminal-output {
  color: #7d7d82;
}

.terminal-cursor {
  display: inline-block;
  width: 8px;
  height: 15px;
  margin-left: 2px;
  vertical-align: text-bottom;
  background: #e8e8e8;
  animation: terminal-blink 1s steps(1) infinite;
}

@keyframes terminal-blink {
  0%, 49% {
    opacity: 1;
  }
  50%, 100% {
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .terminal-card,
  .terminal-cursor {
    animation: none;
  }
}

/* --- Media placeholder (used on case-study + fun pages until real
   images exist, CLAUDE.md §8) --- */
.media-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 220px;
  border: 1px dashed var(--color-border);
  border-radius: var(--radius);
  color: var(--color-text-muted);
  font-size: 0.875rem;
  padding: var(--space-4);
  margin-bottom: var(--space-5);
}

/* Louder variant — a project with nothing built yet to preview, rather
   than an image simply not sourced yet. Same slot, bigger statement. */
.media-placeholder--coming-soon {
  font-family: var(--font-headline);
  font-size: clamp(1.5rem, 1.1rem + 2vw, 2.5rem);
  font-weight: 700;
  text-transform: uppercase;
  color: var(--color-text);
  letter-spacing: 0.02em;
}

