/* Component Lab — a plug-and-play catalog of every visual element this site
   has ever shipped (current, deprecated, and the original "stock" reference
   components some were adapted from), for other developers to borrow.
   Live demos on this page load the site's own real home.css/professional.css
   directly (see _layouts/lab.html) rather than reimplementing each effect a
   second time — so `.theme-lab` needs the same --bg/--text/--muted/--accent
   custom properties `.theme-home` defines, or every `var(--bg)` etc.
   reference throughout those files would resolve to nothing. Matches the
   Grind (light) palette, since that's what most of these effects were
   actually designed against. */
.theme-lab {
  --bg: #ffffff;
  --text: #14171c;
  --muted: #5b6572;
  --accent: #1d4ed8;
  --surface: #f5f6f8;
  --border: #e3e6ea;
  /* Matches .theme-professional's own override — a wide catalog page reads
     better at this width than the shared 780px default, and the fixed pill
     nav (tokens.css) reads var(--max-width) too, so it stays the same
     width as main#main below instead of needing its own hardcoded number. */
  --max-width: 1100px;

  background: var(--bg);
  color: var(--text);
}

.theme-lab a {
  color: var(--accent);
}

/* Shape/position/glass/padding for .lab-header and .lab-header-inner now
   live in tokens.css, shared with .site-header — only the link colors
   below are lab-specific. */

.lab-header nav a {
  text-decoration: none;
  color: var(--muted);
  font-size: 0.95rem;
}

.lab-header nav a:hover {
  color: var(--text);
}

.lab-header-current {
  font-size: 0.95rem;
  color: var(--text);
  font-weight: 600;
}

/* max-width/padding-left/right already come from tokens.css's shared
   main#main rule (now reading var(--max-width), which this theme sets to
   the same 1100px above). padding-top clears the fixed pill nav, which no
   longer pushes content down the way the old in-flow header did. Taller
   under 640px, where the 4-item nav wraps onto more rows (see below). */
.theme-lab main#main {
  padding-top: 6.5rem;
}

/* This nav has 4 items (brand's siblings), not /life/'s 2 — nowrap would
   just overflow instead of fitting, so it keeps tokens.css's wrap but a
   full border-radius: 999px pill (right for a single row) turns into a
   deformed blob once that wrap happens, confirmed live at 375px. Below
   the row-wrapping threshold, trade the pill for a plain rounded panel —
   still glass, still floating, just a shape that works wrapped onto
   multiple lines — and size main#main's clearance for the taller result. */
@media (max-width: 640px) {
  .lab-header {
    border-radius: var(--radius-lg);
  }

  .lab-header-inner {
    gap: var(--space-1) var(--space-2);
  }

  .theme-lab main#main {
    padding-top: 13.5rem;
  }
}

.lab-intro {
  padding-top: var(--space-3);
  max-width: 68ch;
}

.lab-intro h1 {
  font-size: clamp(1.9rem, 4vw, 2.5rem);
  margin-bottom: 0.4rem;
}

.lab-intro p {
  color: var(--muted);
}

.lab-intro code {
  background: var(--surface);
  padding: 0.1em 0.4em;
  border-radius: 4px;
  font-size: 0.92em;
}

.lab-section {
  margin-top: var(--space-5);
}

.lab-section-head {
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.5rem;
  margin-bottom: var(--space-3);
}

.lab-section-head h2 {
  font-size: 1.3rem;
  margin: 0 0 0.25rem;
}

.lab-section-head p {
  color: var(--muted);
  font-size: 0.92rem;
  margin: 0;
}

.lab-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

@media (min-width: 760px) {
  .lab-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.lab-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.lab-card:hover {
  transform: translateY(-3px);
  border-color: var(--accent);
  box-shadow: 0 16px 32px -18px rgba(0, 0, 0, 0.28);
}

.lab-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: var(--space-2) var(--space-2) 0;
}

.lab-card-head h3 {
  margin: 0;
  font-size: 1.05rem;
  font-family: var(--font-display);
}

.lab-view-btn {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  font: inherit;
  font-size: 0.78rem;
  font-weight: 700;
  padding: 0.3rem 0.85rem;
  border-radius: 999px;
  border: 1px solid var(--accent);
  background: transparent;
  color: var(--accent);
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.lab-view-btn:hover,
.lab-view-btn:focus-visible {
  background: var(--accent);
  color: #fff;
}

.lab-card-desc {
  padding: 0.35rem var(--space-2) 0;
  margin: 0;
  color: var(--muted);
  font-size: 0.88rem;
  max-width: none;
}

.lab-demo {
  margin: var(--space-2);
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background:
    linear-gradient(45deg, #fafafa 25%, transparent 25%) 0 0 / 16px 16px,
    linear-gradient(-45deg, #fafafa 25%, transparent 25%) 0 0 / 16px 16px,
    linear-gradient(45deg, transparent 75%, #fafafa 75%) 0 0 / 16px 16px,
    linear-gradient(-45deg, transparent 75%, #fafafa 75%) 0 0 / 16px 16px,
    #ffffff;
  position: relative;
  min-height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.lab-demo-tall {
  min-height: 340px;
}

.lab-demo-dark {
  background: #0f1419;
}

/* Demos that are full-viewport-fixed on the real site (the intro splash,
   the "keep going" pill, page-corner/portal-orb) need their positioning
   context contained to just this box instead of the real page — .lab-demo
   is the containing block for any `position: fixed` *descendant that also
   sets a transform*, but plain `position: fixed` still escapes to the
   viewport regardless. Cards demoing those effects opt into
   `.lab-demo-contain` (`contain: layout`) which turns this box itself into
   a fixed-position containing block per spec, so "fixed" elements inside
   stay confined to the card instead of covering the real page. */
.lab-demo-contain {
  contain: layout;
}

.lab-demo-controls {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 50;
}

.lab-btn {
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.9);
  color: var(--text);
  cursor: pointer;
}

@media (pointer: coarse) {
  .lab-btn {
    min-height: 44px;
    padding-inline: 1rem;
  }
}

.lab-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.lab-card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0 var(--space-2) var(--space-2);
  margin-top: auto;
}

.lab-copy-btn {
  font: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 0.45rem 0.9rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}

.lab-copy-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.lab-copy-btn-done {
  border-color: #166534 !important;
  color: #166534 !important;
}

/* Stock (original pasted reference) vs Ours (the adapted, shipped version) */
.lab-tabs-nav {
  display: flex;
  gap: 0.35rem;
  padding: 0 var(--space-2);
}

.lab-tab-btn {
  font: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 0.3rem 0.75rem;
  border-radius: 999px 999px 0 0;
  border: 1px solid var(--border);
  border-bottom: none;
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
}

.lab-tab-btn-active {
  background: var(--bg);
  color: var(--text);
}

.lab-tab-panel[hidden] {
  display: none;
}

.lab-code-note {
  margin: 0.5rem var(--space-2) 0;
  font-size: 0.82rem;
  color: var(--muted);
}

.lab-code-details {
  margin: 0 var(--space-2) var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}

.lab-code-details summary {
  cursor: pointer;
  padding: 0.5rem 0.75rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  list-style: none;
}

.lab-code-details summary::-webkit-details-marker {
  display: none;
}

.lab-code-details summary::before {
  content: "▸ ";
}

.lab-code-details[open] summary::before {
  content: "▾ ";
}

.lab-code {
  margin: 0;
  padding: 0.9rem;
  max-height: 360px;
  overflow: auto;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.78rem;
  line-height: 1.55;
  background: #12161c;
  color: #d6dde5;
  white-space: pre;
}

.lab-foundation-swatch {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.5rem 0;
}

.lab-swatch {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 8px;
  border: 1px solid var(--border);
  flex-shrink: 0;
}

.lab-foundation-label {
  font-size: 0.85rem;
}

.lab-foundation-label code {
  display: block;
  color: var(--muted);
  font-size: 0.8rem;
}

/* Portal Orb's real CSS only exists inside home.css's own
   @media (max-width: 640px) block — it's genuinely mobile-only in
   production, hidden on desktop by a separate plain `display: none`.
   A real @media query can't be forced to match regardless of viewport,
   so unlike every other "force it visible" card on this page (which just
   needs an inline style tweak), demoing this one at any width means
   duplicating its mobile declarations here, scoped to the demo only. */
.lab-demo .portal-orb,
.lab-modal-stage .portal-orb {
  position: absolute;
  z-index: 3;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #eaf4ff;
  box-shadow: 0 0 0 4px rgba(234, 244, 255, 0.08), 0 0 22px 6px rgba(110, 193, 255, 0.65);
  cursor: pointer;
  animation: orb-pulse 3.5s ease-in-out infinite;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.lab-demo .portal-orb:hover,
.lab-modal-stage .portal-orb:hover,
.lab-demo .portal-orb:focus-visible,
.lab-modal-stage .portal-orb:focus-visible {
  transform: scale(1.2);
  box-shadow: 0 0 0 6px rgba(234, 244, 255, 0.1), 0 0 32px 10px rgba(110, 193, 255, 0.9);
}

.lab-demo .portal-orb-label,
.lab-modal-stage .portal-orb-label {
  position: absolute;
  right: 50%;
  bottom: 140%;
  transform: translate(50%, 6px);
  white-space: nowrap;
  background: #1c1430;
  border: 1px solid rgba(183, 155, 250, 0.35);
  color: #eaf4ff;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
}

.lab-demo .portal-orb:hover .portal-orb-label,
.lab-modal-stage .portal-orb:hover .portal-orb-label,
.lab-demo .portal-orb:focus-visible .portal-orb-label,
.lab-modal-stage .portal-orb:focus-visible .portal-orb-label {
  opacity: 1;
  transform: translate(50%, 0);
}

@media (prefers-reduced-motion: reduce) {
  .lab-demo .portal-orb,
  .lab-modal-stage .portal-orb {
    animation: none;
  }
}

/* Card → modal: the effect opens bigger here, code stays out of the
   compact grid entirely until "Get code" is clicked inside this panel. */
.lab-card-code {
  margin: var(--space-2);
}

.lab-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-3);
}

/* `.lab-modal[hidden]` (two selectors, specificity 0-2-0) has to outrank the
   plain `.lab-modal { display: flex }` rule above it (0-1-0) or the [hidden]
   attribute does nothing and the modal renders permanently open — the exact
   "invisible from the CSS alone" class of bug this project has hit before. */
.lab-modal[hidden] {
  display: none;
}

.lab-modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 20, 25, 0.6);
  backdrop-filter: blur(2px);
}

.lab-modal-panel {
  position: relative;
  width: 100%;
  max-width: min(920px, 100%);
  max-height: min(860px, 100%);
  overflow-y: auto;
  background: var(--bg);
  color: var(--text);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 64px -12px rgba(0, 0, 0, 0.4);
}

.lab-modal-close {
  position: absolute;
  top: 0.6rem;
  right: 0.6rem;
  z-index: 2;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  font-size: 1.3rem;
  line-height: 1;
  cursor: pointer;
}

.lab-modal-close:hover,
.lab-modal-close:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}

.lab-modal-stage {
  min-height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--border);
  background:
    linear-gradient(45deg, #fafafa 25%, transparent 25%) 0 0 / 16px 16px,
    linear-gradient(-45deg, #fafafa 25%, transparent 25%) 0 0 / 16px 16px,
    linear-gradient(45deg, transparent 75%, #fafafa 75%) 0 0 / 16px 16px,
    linear-gradient(-45deg, transparent 75%, #fafafa 75%) 0 0 / 16px 16px,
    #ffffff;
}

/* A flex item's main-axis size defaults to its content's intrinsic width,
   not "fill the container" — fine for a demo whose content is normal-flow,
   but most ambient/background effects (canvases, absolutely-positioned
   hint elements) put nothing in normal flow, so the moved-in .lab-demo
   collapsed to ~2px wide here even though it filled its card correctly
   in the grid (a plain block child there, not a row-flex item). Force it
   to fill the stage explicitly instead of relying on content size. */
.lab-modal-stage > * {
  width: 100%;
}

@media (min-width: 640px) {
  .lab-modal-stage {
    min-height: 440px;
  }
}

.lab-modal-stage:empty {
  display: none;
}

.lab-modal-stage-dark {
  background: #0f1419;
}

.lab-modal-stage-tall {
  min-height: 460px;
}

.lab-modal-body {
  padding: var(--space-3);
}

.lab-modal-body h3 {
  margin: 0 0 0.5rem;
  font-family: var(--font-display);
  font-size: 1.35rem;
  padding-right: 2.5rem;
}

.lab-modal-desc {
  color: var(--muted);
  margin: 0 0 var(--space-3);
  max-width: none;
}

.lab-modal-note {
  font-size: 0.85rem;
  color: var(--muted);
  font-style: italic;
  margin: -0.5rem 0 var(--space-3);
}

.lab-modal-get-code {
  font: inherit;
  font-size: 0.92rem;
  font-weight: 700;
  min-height: 44px;
  padding: 0.55rem 1.3rem;
  border-radius: 999px;
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  transition: filter 0.15s ease;
}

.lab-modal-get-code:hover,
.lab-modal-get-code:focus-visible {
  filter: brightness(1.1);
}

.lab-modal-code {
  margin-top: var(--space-3);
}

.lab-modal-code .lab-card-code {
  margin: 0;
}

.lab-modal-code .lab-card-actions,
.lab-modal-code .lab-code-note {
  padding-left: 0;
  padding-right: 0;
}

.lab-modal-code .lab-code-details {
  margin-left: 0;
  margin-right: 0;
}

body.lab-modal-open {
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .lab-copy-btn,
  .lab-btn,
  .lab-view-btn,
  .lab-modal-get-code,
  .lab-card {
    transition: none;
  }

  .lab-card:hover {
    transform: none;
  }
}

/* ---------------------------------------------------------------------
   /skills/ — Claude Skills catalog. Reuses /questions/'s own classes
   wholesale (.questions-header/.questions-intro/.questions-count/
   .questions-list/.question-card/.question-example/.skill-pill/
   .filter-chip/.questions-empty, all defined in professional.css,
   already loaded by this layout) rather than cloning them under new
   names — only what's genuinely new to this page gets a rule here.
   --------------------------------------------------------------------- */

/* <details> instead of a static section — someone who already knows how
   skills work shouldn't have to scroll past three install-method cards to
   reach the actual catalog. Closed by default; the summary line alone
   carries the "(skip this if you already know)" hint. */
.install-guide {
  margin-bottom: var(--space-3);
  padding: var(--space-2) var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.install-guide summary {
  cursor: pointer;
  min-height: 44px;
  display: flex;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: 0.3rem 0.5rem;
  padding: 0.3rem 0;
  font-weight: 700;
  font-size: 1.05rem;
  list-style: none;
}

.install-guide summary::-webkit-details-marker {
  display: none;
}

.install-guide summary::before {
  content: "";
  flex-shrink: 0;
  margin-top: 0.45em;
  width: 10px;
  height: 10px;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
  transition: transform var(--speed) var(--ease);
}

.install-guide[open] summary::before {
  transform: rotate(45deg);
}

.install-guide summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.install-guide-hint {
  flex-basis: 100%;
  margin-left: 1.3rem;
  font-weight: 400;
  font-size: 0.85rem;
  color: var(--muted);
}

.install-guide-body {
  padding-top: var(--space-2);
}

.install-guide-body > p:first-child {
  margin-top: 0;
}

.install-guide code {
  padding: 0.1em 0.35em;
  background: var(--bg);
  border-radius: 4px;
  font-size: 0.88em;
}

.install-methods {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-2);
  margin-top: var(--space-2);
}

.install-method {
  padding: var(--space-2) var(--space-3);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.install-method h3 {
  margin-top: 0;
  font-size: 1rem;
}

.install-method ol {
  margin: 0 0 0.6rem;
  padding-left: 1.2rem;
  font-size: 0.92rem;
}

.install-method li + li {
  margin-top: 0.3rem;
}

.install-method .question-example pre {
  font-size: 0.74rem;
}

.skills-search {
  margin-bottom: var(--space-2);
}

.skills-search-input {
  width: 100%;
  min-height: 44px;
  padding: 0.6em 0.9em;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 0.95rem;
}

.skills-search-input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

/* The whole point of a card grid here is showing "there are several of
   these, browse what fits" — a single column makes that illegible (and
   makes the cards themselves pointless) the moment there's more than one
   skill. auto-fit so it's 1 column on a narrow screen and however many
   340px+ columns actually fit above that, no breakpoint to maintain by
   hand as more skills get added. */
.skills-grid-cards {
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  align-items: start;
}

/* .question-card already gives this its panel/border/radius; .skill-card
   layers the catalog-specific presentation on top — a hover lift (same
   numbers as .lab-card:hover, for one consistent "this is a card you can
   act on" feel sitewide). The accent color already carries through the
   monogram icon, highlight bullets, and hover border below, so this
   doesn't also need a top accent bar — that's a tell on its own. */
.skill-card {
  position: relative;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.skill-card:hover {
  transform: translateY(-3px);
  border-color: var(--accent);
  box-shadow: 0 16px 32px -18px rgba(0, 0, 0, 0.28);
}

.skill-card-top {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-bottom: 0.6rem;
}

.skill-card-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--accent), color-mix(in srgb, var(--accent) 60%, black));
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.2rem;
}

.skill-card-name {
  margin: 0 0 0.15rem;
}

.skill-card-tagline {
  margin: 0;
  font-weight: 600;
}

.skill-card-desc {
  color: var(--muted);
}

/* Short "what this actually does" bullets, scannable without reading the
   full description — a check icon in the accent color rather than a plain
   bullet, so the row reads as a feature list, not another paragraph. */
.skill-card-highlights {
  display: grid;
  gap: 0.4rem;
  margin: 0.6rem 0 0;
  padding: 0;
  list-style: none;
  font-size: 0.88rem;
}

.skill-card-highlights li {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
}

.skill-card-highlights li::before {
  content: "";
  flex-shrink: 0;
  margin-top: 0.3em;
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: var(--accent);
}

.skill-card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin: 0.8rem 0 0.4rem;
}

.skill-card-actions .offset-btn {
  min-height: 44px;
  padding: 0.5rem 1.1rem;
  font-size: 0.9rem;
  gap: 0.4rem;
}

.skill-card-share-btn {
  gap: 0.35rem;
}

.skill-card-share-btn[aria-expanded="true"] {
  border-color: var(--accent);
  color: var(--accent);
}

.skill-card-share-panel {
  margin: 0 0 0.6rem;
  padding: 0.7rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}

.skill-card-preview summary {
  cursor: pointer;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--accent);
}

.skill-card-preview summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.skill-card-preview .question-example {
  margin-top: 0.5rem;
}

/* Unlike /questions/'s short ``` ASCII-diagram snippets (the thing
   .question-example pre was built for, with overflow-x: auto), this is a
   whole raw SKILL.md dumped verbatim — ordinary markdown paragraphs that
   were never hard-wrapped, so left as overflow-x:auto they'd blow the
   page out horizontally instead of just scrolling the code block. Wrap
   instead. */
.skill-card-preview .question-example pre {
  max-height: 420px;
  overflow-x: hidden;
  overflow-y: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
