/* graphs.css — the graphs landing page.
   Built from _figures.css (the inline-SVG visual language) plus the
   page layout. Loaded only by pages/graphs.html. */

/* =======================================================================
   Graph figures — shared visual language for the hand-built inline SVG
   diagrams used by the graphs landing concepts.

   Every colour here resolves from the sitewide tokens, so light and dark
   both work with one copy of the markup. The SVG files carry no fill or
   stroke attributes of their own; they only carry classes.

   --g-warn is the one addition to the two-accent palette. A cyclic
   dependency, a removed edge and an untested branch all need to read as
   "this is the problem" and neither blue nor green says that. It is
   themed separately because amber on the light surface needs to go darker
   to stay legible.
   ======================================================================= */
:root { --g-warn: #F59E0B; --g-warn-rgb: 245, 158, 11; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) { --g-warn: #B45309; --g-warn-rgb: 180, 83, 9; }
}
:root[data-theme="light"] { --g-warn: #B45309; --g-warn-rgb: 180, 83, 9; }

.g-figure {
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--card);
  padding: clamp(0.75rem, 2vw, 1.25rem);
}
.g-figure figcaption {
  margin-top: 0.9rem;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--text-muted);
}
.g-svg { display: block; width: 100%; height: auto; }

/* nodes ---------------------------------------------------------------- */
.g-node        { fill: var(--surface); stroke: currentColor; stroke-opacity: 0.22; stroke-width: 1; }
.g-node-focus  { fill: rgba(var(--accent-1-rgb), 0.14); stroke: var(--accent-1); stroke-opacity: 1; stroke-width: 1.5; }
.g-node-warn   { fill: rgba(var(--g-warn-rgb), 0.10); stroke: var(--g-warn); stroke-opacity: 0.85; stroke-width: 1.3; }
.g-node-add    { fill: rgba(var(--accent-2-rgb), 0.12); stroke: var(--accent-2); stroke-opacity: 0.9; stroke-width: 1.3; }

/* edges ---------------------------------------------------------------- */
.g-edge      { fill: none; stroke: currentColor; stroke-opacity: 0.26; stroke-width: 1.4; }
.g-edge-hot  { fill: none; stroke: var(--accent-1); stroke-opacity: 0.95; stroke-width: 2; }
.g-edge-add  { fill: none; stroke: var(--accent-2); stroke-opacity: 0.95; stroke-width: 2; }
.g-edge-warn { fill: none; stroke: var(--g-warn); stroke-opacity: 0.95; stroke-width: 1.8; }
.g-arrow      { fill: currentColor; fill-opacity: 0.32; }
.g-arrow-hot  { fill: var(--accent-1); }
.g-arrow-warn { fill: var(--g-warn); }

/* text ----------------------------------------------------------------- */
.g-label {
  fill: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
}
.g-label-focus { fill: var(--accent-1); font-weight: 600; }
.g-label-warn  { fill: var(--g-warn); }
.g-label-add   { fill: var(--accent-2); }
.g-member {
  fill: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10.5px;
}
.g-sub, .g-axis {
  fill: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 11px;
}
.g-edge-label {
  fill: var(--text-muted);
  font-family: var(--font-sans);
  font-size: 10.5px;
}
.g-edge-label-warn { fill: var(--g-warn); font-weight: 600; }
.g-divider  { stroke: currentColor; stroke-opacity: 0.16; stroke-width: 1; }
.g-uml-tri  { fill: var(--surface); stroke: currentColor; stroke-opacity: 0.35; stroke-width: 1.2; }

/* dense real-scale figure ---------------------------------------------- */
.g-hair    { stroke: currentColor; stroke-opacity: 0.13; stroke-width: 0.7; }
.g-dot     { fill: currentColor; fill-opacity: 0.42; }
.g-dot-hot { fill: var(--accent-1); fill-opacity: 0.95; }
.g-swatch-add  { fill: var(--accent-2); }
.g-swatch-warn { fill: var(--g-warn); }

@media (prefers-reduced-motion: no-preference) {
  .g-edge, .g-edge-hot, .g-edge-add, .g-edge-warn { transition: stroke-opacity 0.25s var(--ease); }
}

/* stale-vs-generated contrast pair ------------------------------------- */
.g-stale       { stroke-opacity: 0.14; fill-opacity: 0.45; }
.g-stale-label { fill: var(--text-muted); fill-opacity: 0.7; }
.g-stamp {
  fill: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10.5px;
}
.g-stamp-live { fill: var(--accent-2); }


/* =======================================================================
   Concept A — "The Graph Itself"
   Product-first. The visitor arrives from a graphs ad and sees a graph
   inside the first screen, with the six types one click apart.
   Only one primary action on the page: start the trial.
   ======================================================================= */

/* --- hero -------------------------------------------------------------
   The whole premise of this concept is that somebody arriving from a graphs
   ad sees a graph without scrolling, so the copy above the panel is kept
   deliberately short: two lines of headline, one line of lede, one button
   row. The trust note moves below the panel rather than pushing it down. */
.gr-hero { padding-top: clamp(2rem, 4vw, 3rem); padding-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.gr-hero-copy { max-width: 820px; margin: 0 auto 2rem; }
.gr-hero-copy h1 {
  text-wrap: balance;
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  margin-bottom: 0.85rem;
}
.gr-hero-copy .lead { max-width: 56ch; }
.gr-hero-copy .p-hero-actions { margin-top: 1.75rem; }
.gr-hero-note { margin-top: 1.25rem; text-align: center; }

/* --- hero video + chapters (replaced the view switcher) --------------- */
.gr-views {
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  background: var(--card);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

/* --- chapter row ------------------------------------------------------
   Same place and same furniture as the old tab bar, so the hero reads the
   way it did. Each button is a segment of a progress bar that happens to
   be labelled. */
.gr-ch {
  display: flex;
  gap: 0.25rem;
  padding: 0.5rem;
  border-bottom: 1px solid var(--border);
  background: var(--navbar-highlight);
  overflow-x: auto;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.gr-ch[hidden] { display: none; }        /* shown only once the script runs */

.gr-ch-btn {
  position: relative;
  isolation: isolate;                     /* keeps the fill behind the text */
  flex: 1 1 0;
  min-width: fit-content;
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: var(--text-muted);
  font-family: inherit;
  font-size: 0.875rem;
  font-weight: 600;
  padding: 0.5rem 0.95rem;
  border-radius: var(--radius-full);
  cursor: pointer;
  white-space: nowrap;
  text-align: center;
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease);
}
.gr-ch-text { position: relative; }
.gr-ch-fill {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: rgba(var(--accent-1-rgb), 0.14);
  transform: scaleX(0);
  transform-origin: left center;
  will-change: transform;                 /* transform only -- no layout */
}
.gr-ch-btn:hover { color: var(--text-primary); }
.gr-ch-btn:hover .gr-ch-fill { background: rgba(var(--accent-1-rgb), 0.20); }
.gr-ch-btn[aria-current="true"] {
  color: var(--accent-1);
  border-color: rgba(var(--accent-1-rgb), 0.35);
}
.gr-ch-btn:focus-visible { outline: 2px solid var(--accent-1); outline-offset: 2px; }

/* --- the clip --------------------------------------------------------- */
.gr-views-stage { padding: clamp(1rem, 2.5vw, 1.75rem); }
.gr-video-frame { position: relative; }
.gr-video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
  background: var(--card);                /* matches the clip's own surround */
}

/* Pause control -- WCAG 2.2.2, since the clip plays on its own. */
.gr-video-toggle {
  position: absolute;
  right: 10px;
  bottom: 10px;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: rgba(var(--surface-rgb), 0.72);
  backdrop-filter: blur(6px);
  color: var(--text-primary);
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 0.18s var(--ease);
}
.gr-video-frame:hover .gr-video-toggle,
.gr-video-toggle:focus-visible { opacity: 1; }
.gr-video-toggle:focus-visible { outline: 2px solid var(--accent-1); outline-offset: 2px; }
.gr-video-toggle svg { width: 15px; height: 15px; fill: currentColor; }
.gr-video-toggle .gr-ico-play { display: none; }
.gr-video-toggle[data-state="paused"] .gr-ico-pause { display: none; }
.gr-video-toggle[data-state="paused"] .gr-ico-play { display: block; }

/* --- breakpoints ------------------------------------------------------
   Five equal segments stop fitting before the labels do, so below 640px the
   row keeps each label's natural width and scrolls sideways instead of
   squeezing "UML sequence" to three characters. */
@media (max-width: 760px) {
  .gr-ch-btn { font-size: 0.8125rem; padding: 0.45rem 0.8rem; }
}
@media (max-width: 639px) {
  /* Five labels need roughly 600px. At phone width the row clipped "UML
     sequence" and scrolled sideways, so it is dropped rather than squeezed --
     every chapter is headlined inside the footage anyway. The script stops
     its requestAnimationFrame loop to match. */
  .gr-ch { display: none; }
  .gr-video-toggle { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .gr-ch-fill { transition: none; }
}

/* --- proof ribbon ----------------------------------------------------- */
.gr-ribbon { padding-top: 0; }
.gr-ribbon-label {
  text-align: center;
  font-size: 0.8125rem;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin-bottom: 1.5rem;
}

/* --- real scale ------------------------------------------------------- */
/* Two stats, not the three .stats-row assumes -- without its own template
   the pair would sit in the first two of three columns and read as though a
   third went missing. minmax(0, 1fr) rather than 1fr so a long label can wrap
   instead of setting a floor wider than the cell. */
.gr-stats {
  margin-top: 2rem;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* The copy, the stats and the button all share the left edge here, unlike
     the centred .stats-row on index.html, so the pair is capped and pulled
     left instead of spreading across the column. */
  max-width: 27rem;
  text-align: left;
}
.gr-stats .stat-item { padding: 0; }
/* .stat-value and .stat-label are inline spans sitewide with no display rule,
   so they only sit on separate lines where the cell is narrow enough to force
   a wrap -- and the label's margin-top never applies. Wider cells here put
   them side by side. Fixed in this section only; the same latent bug is on
   every page using .stats-row and wants its own pass. */
.gr-stats .stat-value,
.gr-stats .stat-label { display: block; }
.gr-scale-cta { margin-top: 1.75rem; }
/* .stats-row supplies only the column template; .grid supplies display:grid.
   Both classes are required, same as index.html and autosar.html. */
.gr-scale-media { padding: clamp(0.75rem, 2vw, 1.25rem); }
.gr-figure-flush { border: 0; background: transparent; padding: 0; }
/* The real-scale shot is a dark screenshot in both themes, so it carries the
   same framing as the other product shots rather than floating on a white
   card in light mode. The background matches the shot's own ground so there
   is no pale flash before it decodes. */
.gr-scale-shot {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: #1E1E1E;
}

/* --- working with graphs --------------------------------------------- */
.gr-work-card { display: flex; flex-direction: column; }
.gr-work-shot {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--surface);
  overflow: hidden;
  margin-bottom: 1.25rem;
  aspect-ratio: 16 / 10;
  display: flex;
  align-items: center;
  justify-content: center;
}
.gr-work-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.gr-work-card h3 { margin-bottom: 0.6rem; font-size: 1.0625rem; }

/* --- proof ------------------------------------------------------------ */
.gr-proof-grid { margin-bottom: 2rem; }
/* .p-quote-name and .p-quote-org are inline spans sitewide with no display
   rule, so the person's name and their company ran together as one unbroken
   string ("Randall LandaicheIntuity"). Stacked here, in the page's own sheet,
   rather than in pages.css -- the same latent bug is on every page using
   .p-quote and wants its own pass. */
.p-quote-who .p-quote-name,
.p-quote-who .p-quote-org { display: block; }
.p-quote-who .p-quote-org { margin-top: 0.1rem; }
.gr-case-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
.gr-case-link {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--card);
  color: var(--text-primary);
  font-weight: 600;
  font-size: 0.9375rem;
  text-decoration: none;
  transition: border-color 0.18s var(--ease), transform 0.18s var(--ease);
}
.gr-case-link span { font-weight: 500; font-size: 0.8125rem; color: var(--accent-1); }
.gr-case-link:hover { border-color: var(--border-strong); transform: translateY(-2px); }

/* --- breakpoints ------------------------------------------------------ */
@media (max-width: 1100px) {
  .gr-case-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .p-row { grid-template-columns: minmax(0, 1fr); }
  .gr-stats { flex-wrap: wrap; gap: 1.25rem 2rem; }
}
@media (max-width: 760px) {
  .gr-case-row { grid-template-columns: minmax(0, 1fr); }
  .gr-hero-copy { margin-bottom: 2rem; }
}
@media (max-width: 480px) {
  .gr-work-shot { aspect-ratio: 16 / 11; }
}
