/* components.css — appearance of reusable pieces. Geometry lives in the
   position-*.css files, so a component can be re-placed without restyling. */

.site-header { background: var(--c-header-bg); }
.site-nav    { background: var(--c-navbar-bg); }

.brand        { text-decoration: none; display: block; }
/* contain, so the lockup keeps its aspect if its box has to narrow on a
   very small screen rather than stretching */
.brand-lockup { display: block; width: 100%; height: 100%;
                object-fit: contain; object-position: left center; }

/* One horizontal row of tabs, always. They are laid out by flexbox, not by
   script writing left/top on each link. If eight labels cannot fit at readable
   size the row scrolls sideways; it never wraps to a second row and never
   stacks. */
.nav-track {
  position: relative;
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-between;
  gap: 4px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* a tab bar in its own band: no dividers, active marked underneath */
.nav-link {
  flex: 0 0 auto;
  display: grid; place-items: center;
  background: transparent;
  text-decoration: none;
  border: 0;
  border-bottom: 3px solid transparent;
}
.nav-link:hover { background: var(--c-tab-hover); }
.nav-link.is-active { border-bottom-color: var(--c-tab-active); }

.cta {
  background: linear-gradient(115deg, var(--c-cta-from), var(--c-cta-to));
  border-radius: 8px;
  display: grid; place-items: center;
  text-decoration: none;
}
.cta:hover { filter: brightness(1.15); }

/* Text size is a transient choice, so it collapses to one trigger and reveals
   its options on hover/focus instead of permanently occupying header width. */
.ts-trigger {
  width: 100%; height: 100%;
  background: transparent;
  color: var(--c-header-ink);
  border: 1px solid var(--c-tab-line);
  border-radius: 8px;
  cursor: pointer;
}
.ts-trigger:hover { background: var(--c-tab-hover); }

.ts-panel {
  position: absolute; top: calc(100% + 8px); right: 0;
  display: none; gap: 4px; padding: 6px;
  background: var(--c-header-bg);
  border: 1px solid var(--c-tab-line);
  border-radius: 8px;
  z-index: 5;
}
.text-size:hover .ts-panel,
.text-size:focus-within .ts-panel { display: flex; }

.ts-panel button {
  min-width: 32px; height: 28px; padding: 0 8px;
  background: transparent;
  color: var(--c-header-ink);
  border: 1px solid var(--c-tab-line);
  border-radius: 6px;
  cursor: pointer;
}
.ts-panel button[aria-pressed="true"] {
  background: var(--c-tab-active);
  border-color: var(--c-tab-active);
}

/* --- home hero ------------------------------------------------------------
   The image is cropped to the band with object-fit, and the overlay fades it
   into the page colour so the headline sitting over its foot stays legible. */
.hero-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.hero-fade {
  position: absolute; inset: 0;
  background: linear-gradient(
    180deg,
    rgba(0,0,0,.30) 0%,
    transparent 35%,
    var(--c-surface) 100%
  );
  pointer-events: none;
}

/* --- footer --------------------------------------------------------------- */
/* Solid black band, same as the header, so the footer reads as chrome rather
   than as page. The card keeps its own translucent fill on top. */
.site-footer { background: var(--c-header-bg); }
.footer-rule { background: var(--c-border-subtle); }

.footer-brand  { display: block; width: 100%; height: 100%; object-fit: contain;
                 object-position: left center; }
/* Card foot: copyright on the left buffer, compliance holding the right. */
.entity-foot {
  margin-top: 14px; padding-top: 11px;
  border-top: 1px solid var(--c-border-subtle);
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 24px;
}
.entity-badges {
  margin: 0; padding: 0; list-style: none;
  display: contents;
}
.entity-compliance a {
  color: var(--c-accent-emerald);
  text-decoration: underline; text-underline-offset: 2px;
}
.entity-compliance a:hover { color: var(--c-accent-blue); }
.entity-badges li {
  display: inline-flex; align-items: center; justify-content: center;
  padding: 4px 9px;
  border: 1px solid rgba(6,214,160,.25);
  border-radius: 4px;
  background: rgba(6,214,160,.12);
  color: var(--c-accent-emerald);
}
.entity-badges li:nth-child(2) {
  border-color: rgba(255,255,255,.20);
  background: rgba(255,255,255,.08);
  color: #ffffff;
}

.footer-contact,
.footer-compliance a {
  color: var(--c-accent-emerald);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.footer-contact:hover,
.footer-compliance a:hover { color: var(--c-accent-blue); }

/* --- SAM.gov entity card ---------------------------------------------------
   Public registration record. Internals flow normally inside the absolutely
   positioned card, the way the CTA and text-size panel do. */
.entity-card {
  background: var(--c-glass-bg);
  border: 1px solid var(--c-border-subtle);
  border-radius: 8px;
  padding: 14px 16px;
}
/* Top row: the lockup and each badge are siblings in one flex row, so the
   spacing between every pair is identical rather than the badges clustering
   with a different gap to the lockup. The list keeps its semantics via
   display:contents. */
.entity-head {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 14px;
}
.entity-lockup { display: block; height: 30px; width: auto; flex: none; }
.entity-badges li.entity-status { gap: 6px; }
.entity-badges li.entity-status::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--c-accent-emerald);
}
/* The four label/value pairs join the lockup as siblings in the head row, so
   one space-between distribution spaces all five evenly. display:contents
   keeps the dl semantics while letting its pairs be flex items. */
.entity-facts { display: contents; }
.entity-facts > div { flex: none; }
.entity-facts dd { margin: 2px 0 0; }
.entity-contact {
  color: var(--c-accent-emerald);
  text-decoration: underline; text-underline-offset: 2px;
}
.entity-contact:hover { color: var(--c-accent-blue); }

/* --- home: the Hyena helper ------------------------------------------------
   Trigger centred under the headline; the panel opens beneath it on hover,
   keyboard focus, or tap. The original opened upward, which here would cover
   the headline it sits under. */
.hyena { display: flex; justify-content: center; }
/* anchors the panel to the trigger rather than to the full-width row */
.hyena-anchor { position: relative; display: inline-flex; }

.hyena-trigger {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 0 20px;
  border: 1px solid rgba(77,158,255,.18);
  border-radius: 999px;
  background: rgba(77,158,255,.04);
  color: var(--c-slate-dark);
  cursor: pointer;
  transition: color .2s, border-color .2s, background .2s;
}
.hyena-trigger:hover,
.hyena:focus-within .hyena-trigger,
.hyena.is-open .hyena-trigger {
  color: var(--c-muted);
  border-color: rgba(77,158,255,.35);
  background: rgba(77,158,255,.08);
}
.hyena-info {
  display: inline-grid; place-items: center;
  width: 13px; height: 13px; border-radius: 50%;
  border: 1px solid currentColor; opacity: .55;
}

.hyena-panel {
  display: none;
  position: absolute; left: calc(100% + 16px); top: 50%;
  transform: translateY(-50%);
  width: 480px; padding: 20px 22px;
  border: 1px solid rgba(77,158,255,.20);
  border-radius: 12px;
  background: rgba(2,6,23,.96);
  box-shadow: 0 12px 40px rgba(0,0,0,.7);
  text-align: left;
  z-index: 20;
}
.hyena:hover .hyena-panel,
.hyena:focus-within .hyena-panel,
.hyena.is-open .hyena-panel { display: block; }

/* --- content container ---------------------------------------------------- */
/* The panel itself is invisible - no fill, no border - but it stays in the
   markup as the named home for this copy, so the text is easy to find and
   edit. Only the sentence reads. */
.content-panel {
  background: transparent;
  border: 0;
  display: grid; place-items: center; align-content: center;
  padding: 28px 48px;
}

/* Word-by-word reveal, matching the predecessor's TextReveal: each word fades
   up out of a blur on a 0.04s stagger, fired once when the block scrolls into
   view. Words are wrapped by js/canvas.js so the markup stays plain text. */
.reveal-word {
  display: inline-block;
  opacity: 0;
  transform: translateY(14px);
  filter: blur(6px);
  transition: opacity .95s cubic-bezier(.16,1,.3,1),
              transform .95s cubic-bezier(.16,1,.3,1),
              filter .95s cubic-bezier(.16,1,.3,1);
}
.is-revealed .reveal-word { opacity: 1; transform: none; filter: blur(0); }

@media (prefers-reduced-motion: reduce) {
  .reveal-word { transition: none; opacity: 1; transform: none; filter: none; }
}

/* --- section scaffold -----------------------------------------------------
   Labelled empty containers, one per planned section. Header only: no copy,
   no badges. js/canvas.js stacks them below whatever the page already holds
   and sizes the canvas to fit, so a page grows with its section count. */
.section-block {
  background: var(--c-glass-bg);
  border: 1px solid var(--c-border-subtle);
  border-radius: 8px;
  padding: 18px 24px;
}

/* Radix Leadership carries its own cards, so the scaffold panel around them is
   dropped: no fill, no border, and no padding either, so the heading and the
   cards sit on the page's 48px buffer rather than indented inside an invisible
   box. */
.section-block[aria-labelledby="s-radix-leadership"] {
  background: transparent;
  border: 0;
  padding: 0;
}

/* --- founder cards --------------------------------------------------------
   Two equal halves of the section: Steve left, Ben right. 3:4 portraits are
   cropped to a fixed box with object-fit so both heads sit at the same scale
   regardless of the source framing. */
.founder-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 24px; margin-top: 18px;
}
.founder-card {
  background: rgba(255,255,255,.03);
  border: 1px solid var(--c-border-subtle);
  border-radius: 8px;
  padding: 18px;
}
/* Top block: photo on the left, an inset panel on the right carrying the
   identity, then a rule, then education. The panel now runs taller than the
   photo, so the photo holds its own size at the top of the row. */
.founder-top {
  display: flex; gap: 16px; align-items: flex-start;
}
/* Height is pinned to the photo's 266px and the type inside is sized to fill
   it, so the two columns of the top block square off. */
.founder-info {
  flex: 1; min-width: 0; height: 266px;
  display: flex; flex-direction: column;
  padding: 18px 16px;
  border: 1px solid var(--c-border-subtle);
  border-radius: 6px;
  background: rgba(255,255,255,.02);
}
/* LinkedIn sits immediately under the location, not pushed to the foot. */
.founder-info .founder-link { margin-top: 16px; margin-bottom: 0; }

/* Section break, inside the panel, directly beneath LinkedIn. */
.founder-divider {
  height: 1px; margin: 12px 0;
  background: var(--c-border-subtle);
}
.founder-info .founder-divider { margin: 18px 0; }
.founder-photo {
  flex: none; align-self: flex-start; width: 200px; height: 266px;
  object-fit: cover; object-position: top center;
  border-radius: 6px; display: block;
  border: 1px solid var(--c-border-subtle);
}

.founder-expertise {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px;
  margin-top: 16px;
}
.founder-expertise ul { margin: 6px 0 0; padding: 0; list-style: none; }
.founder-edu { margin: 0; padding: 0; list-style: none; }
.founder-edu li + li { margin-top: 12px; }
.founder-link {
  display: inline-block;
  color: var(--c-accent-emerald);
  text-decoration: underline; text-underline-offset: 2px;
}
.founder-link:hover { color: var(--c-accent-blue); }

/* --- founding principle: three named sub-sections -------------------------
   Stacked, separated by a rule, with no panel of their own. The nesting this
   replaces put bordered boxes inside a bordered box. */
.principle-stack { margin-top: 16px; }
/* 72ch keeps the line inside a readable measure. It ran 163 characters at the
   container width, roughly double the upper limit for continuous reading. */
.principle-body { max-width: 72ch; }
.principle-body p + p { margin-top: 10px; }
.principle-item + .principle-item {
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--c-border-subtle);
}

/* ==========================================================================
   BELOW 900px - the same components, stacked where a row cannot hold them.
   ========================================================================== */
@media (max-width: 899px) {
  /* the tab row starts at the left buffer instead of spreading, so the first
     tab is where the eye expects it when the row scrolls */
  .nav-track { justify-content: flex-start; gap: 2px; }

  /* --- founder cards: one per row, photo on top, text below at full width.
     Side by side each card was 174px wide, which put the bios at 22.7
     characters per line over 19 lines; prose needs 45 to 75. */
  .founder-grid { grid-template-columns: 1fr; gap: 16px; margin-top: 14px; }
  .founder-card { padding: 14px; }
  .founder-top  { flex-direction: column; gap: 12px; }
  /* Hold the portrait aspect. A full-width 313x240 box is landscape (1.31)
     while the source is 3:4 (0.75), so object-fit:cover was discarding 43% of
     each photo. Desktop's 200x266 box is 3:4, which is why it never cropped. */
  .founder-photo { width: min(200px, 60%); height: auto; aspect-ratio: 3 / 4;
                   align-self: flex-start; }
  .founder-info  { width: 100%; height: auto; padding: 14px; }
  .founder-info .founder-link    { margin-top: 10px; }
  .founder-info .founder-divider { margin: 12px 0; }
  .founder-edu li + li { margin-top: 8px; }
  .founder-expertise { grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px; }

  .principle-body { max-width: none; }
  .principle-item + .principle-item { margin-top: 14px; padding-top: 14px; }

  .content-panel { background: transparent; border: 0; padding: 20px 0; }

  /* The panel opened to the right of its trigger, which is off-screen here. */
  .hyena-panel {
    left: 50%; right: auto; top: calc(100% + 12px);
    transform: translateX(-50%);
    width: min(90vw, 480px);
  }

  /* --- footer card ---------------------------------------------------------
     The head is one row of five on desktop. Here the lockup takes its own line
     and the four facts go two by two, each label and value staying together.
     The foot's three parts each take their own line so nothing is clipped and
     no chip is split. */
  .entity-card   { padding: 16px; }
  .entity-head   { flex-direction: column; align-items: stretch; gap: 12px;
                   margin-bottom: 12px; }
  .entity-lockup { height: 26px; align-self: flex-start; }
  .entity-facts  { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
  .entity-facts > div { min-width: 0; }
  /* the address is longer than a half-width column, and breaking it mid-word
     ("admin@radixgov.co / m") is worse than giving it the whole row */
  .entity-facts > div:nth-child(4) { grid-column: 1 / -1; }
  .entity-facts dd { overflow-wrap: anywhere; }

  /* stretch, not flex-start: a shrink-to-fit badge list wraps to one chip per
     line instead of using the row it has */
  .entity-foot   { flex-direction: column; align-items: stretch; gap: 10px; }
  /* display:contents on desktop puts the chips in the foot's own row; here they
     are their own wrapping line */
  .entity-badges { display: flex; flex-wrap: wrap; gap: 6px; width: 100%; }
  .entity-copy,
  .entity-compliance { white-space: normal; text-align: left; }
}
