/* ============================================================================
   Grosso University — site layer
   Components built on theme/tokens/*. Nothing here hardcodes a color: every
   value resolves from the [data-surface] the component sits in, so a section
   can be moved between plates without touching its CSS.
   ============================================================================ */

/* ── Page frame ─────────────────────────────────────────────────────────── */
body { min-height: 100dvh; display: flex; flex-direction: column; }
#main { flex: 1; }

/* 🔴 THE min-width:0 RULE — the single most load-bearing line in this file.
   A grid or flex CHILD defaults to `min-width: auto`, which refuses to shrink
   below its own min-content width. So a one-column grid does not produce a
   one-column-wide track: it produces a track as wide as the longest unbreakable
   thing inside it, and the page then scrolls sideways.
   Measured on the home hero at 360px: container 326px, computed
   `grid-template-columns: 390.203px` — the min-content of the word
   "PROFESSIONALS" set at --gu-text-5xl. 47px of spill from one word.
   `overflow-wrap: break-word` does NOT fix this; it permits a break but does
   not reduce min-content size (that is `anywhere`, which collapses tracks).
   Every layout component's children are listed here. Add new ones to the list. */
:where(.gu-split, .gu-grid, .gu-btn-row, .gu-checklist, .gu-header__inner,
       .gu-footer__cols, .gu-nav__list, .gu-crumbs ol, .gu-social,
       .gu-drawer__inner, .gu-band__inner, .gu-card, .gu-sitemap) > * { min-width: 0; }

/* Every section is a plate. `container-type: inline-size` makes its children
   size to the section, not the viewport — the reason this site needs no
   component-level media queries. */
.gu-band {
  position: relative;
  padding-block: var(--gu-section-y);
  container-type: inline-size;
  container-name: band;
}
.gu-band__inner {
  position: relative;
  z-index: 1;                       /* above the canvas backdrop */
  max-width: var(--gu-max-width);
  margin-inline: auto;
  padding-inline: var(--gu-gutter);
}
.gu-band--tight { padding-block: calc(var(--gu-section-y) * 0.55); }

/* ── Canvas backdrop ────────────────────────────────────────────────────────
   A decorative layer only. It is `aria-hidden` and carries no information: if
   the canvas fails to create a context, or JS never runs, the band still has
   its surface background and every word is still in the DOM. */
.gu-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 0;
  pointer-events: none;
}

/* ── Header ─────────────────────────────────────────────────────────────── */
.gu-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--gu-bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--gu-rule);
}
.gu-header__inner {
  max-width: var(--gu-max-width);
  margin-inline: auto;
  padding: var(--gu-space-2xs) var(--gu-gutter);
  display: flex;
  align-items: center;
  gap: var(--gu-space-md);
  min-height: 64px;
}
.gu-header__logo { flex: none; width: clamp(120px, 18vw, 190px); }
.gu-header__logo a { display: block; }
.gu-header__spacer { flex: 1; }

/* At 320px the bar is logo + CTA + hamburger inside a 288px content box, and
   the hamburger ended up 1px past the edge. The CTA is dropped below 480px
   rather than shrunk — it is the first item in the drawer, so nothing is lost,
   and a squeezed 8px-padding button would be a worse touch target than none.
   ⚠️ Selector is `.gu-btn.gu-header__cta`, not `.gu-header__cta`. The element
   carries BOTH classes, and `.gu-btn { display: inline-flex }` is declared later
   in this file — at equal specificity the later rule wins and the CTA stayed
   visible, wrapping onto two lines at 390px. This is the second time source
   order silently beat a media query here (see the header toggle above); the
   answer is specificity, which does not depend on where the rule sits. */
@media (max-width: 479px) {
  .gu-btn.gu-header__cta { display: none; }
  .gu-header__inner { gap: var(--gu-space-2xs); }
}

.gu-nav { display: none; }
.gu-nav__list { display: flex; gap: var(--gu-space-md); list-style: none; margin: 0; padding: 0; flex-wrap: wrap; }
.gu-nav__link {
  font-family: var(--gu-font-display);
  font-size: var(--gu-text-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  text-decoration: none;
  color: var(--gu-fg);
  white-space: nowrap;
}
.gu-nav__link:hover, .gu-nav__link[aria-current="page"] { color: var(--gu-accent); }

.gu-header__toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;                 /* 44px = the minimum touch target */
  background: none; border: 1px solid var(--gu-rule); border-radius: var(--gu-radius-sm);
  color: var(--gu-fg); cursor: pointer; flex: none;
}

/* ⚠️ This media query MUST come after `.gu-header__toggle`'s base rule. Same
   specificity means source order decides, and with the query written first the
   base `display: inline-flex` won — the hamburger sat next to the full desktop
   nav at 1440px. A media query does not add specificity. */
@media (min-width: 1080px) {
  .gu-nav { display: block; }
  .gu-header__toggle { display: none; }
}
.gu-header__toggle .gu-icon { width: 24px; height: 24px; }

/* The mobile drawer is a <dialog>: focus trap, Esc, and inert background all
   come free from the platform rather than from hand-written JS. */
.gu-drawer {
  border: 0; padding: 0; max-width: min(420px, 92vw); width: 100%;
  max-height: 100dvh; height: 100dvh; margin: 0 0 0 auto;
  background: var(--gu-bg); color: var(--gu-fg);
}
.gu-drawer::backdrop { background: rgb(0 0 0 / 0.6); }
.gu-drawer__inner { padding: var(--gu-space-md); display: grid; gap: var(--gu-space-sm); }
.gu-drawer__head { display: flex; align-items: center; justify-content: space-between; }
.gu-drawer__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gu-space-2xs); }
.gu-drawer__list li.is-sub a { padding-left: var(--gu-space-sm); font-size: var(--gu-text-sm); color: var(--gu-fg-muted); }
.gu-drawer__list a {
  display: block; padding: var(--gu-space-2xs) 0;
  font-family: var(--gu-font-display); text-transform: uppercase;
  letter-spacing: 0.06em; font-size: var(--gu-text-base); text-decoration: none;
  color: var(--gu-fg); border-bottom: 1px solid var(--gu-rule);
}
.gu-drawer__list a:hover { color: var(--gu-accent); }

/* ── Buttons ────────────────────────────────────────────────────────────── */
.gu-btn {
  display: inline-flex; align-items: center; gap: var(--gu-space-2xs);
  font-family: var(--gu-font-display); font-weight: 700; font-size: var(--gu-text-sm);
  text-transform: uppercase; letter-spacing: 0.1em; text-decoration: none;
  padding: 0.85em 1.6em; border: 2px solid transparent;
  border-radius: var(--gu-radius-sm); cursor: pointer; text-align: center;
  transition: background-color var(--gu-dur-fast) var(--gu-ease),
              color var(--gu-dur-fast) var(--gu-ease),
              border-color var(--gu-dur-fast) var(--gu-ease),
              transform var(--gu-dur-fast) var(--gu-ease);
}
.gu-btn:hover { transform: translateY(-1px); text-decoration: none; }
.gu-btn--primary { background: var(--gu-accent); color: var(--gu-bg); border-color: var(--gu-accent); }
.gu-btn--primary:hover { background: var(--gu-fg-strong); border-color: var(--gu-fg-strong); color: var(--gu-bg); }
.gu-btn--ghost { border-color: currentColor; color: var(--gu-fg); }
.gu-btn--ghost:hover { background: var(--gu-fg); color: var(--gu-bg); }
.gu-btn .gu-icon { width: 1.1em; height: 1.1em; flex: none; }

.gu-btn-row { display: flex; flex-wrap: wrap; gap: var(--gu-space-xs); margin-top: var(--gu-space-md); }

/* ── Icons ──────────────────────────────────────────────────────────────── */
.gu-icon {
  width: 1.25em; height: 1.25em;
  fill: none; stroke: currentColor;         /* stroke icons; filled ones override */
  vertical-align: -0.15em; flex: none;
}

/* ── Type helpers ───────────────────────────────────────────────────────── */
.gu-eyebrow {
  font-family: var(--gu-font-display); font-size: var(--gu-text-sm);
  font-weight: 700; text-transform: uppercase; letter-spacing: 0.18em;
  color: var(--gu-accent); margin: 0 0 var(--gu-space-xs);
}
.gu-lede { font-size: var(--gu-text-lg); color: var(--gu-fg-muted); max-width: var(--gu-measure); }
.gu-prose > * + * { margin-top: var(--gu-space-sm); }
.gu-prose :where(h2, h3, h4) { margin-top: var(--gu-space-lg); }

/* ── Hero ───────────────────────────────────────────────────────────────── */
.gu-hero { padding-block: clamp(3.5rem, 2rem + 7vw, 9rem); }

/* 🔴 The hero copy column is its OWN container, and the title is sized in `cqi`
   against it.
   Two bugs led here, in order:
   1. `--gu-text-5xl` is viewport-relative, so in a two-column split it sized to
      a 1440px WINDOW while living in a ~550px COLUMN — 88px type, hard-breaking
      into "IMPROVEME / NT" and "PROFESSION / ALS".
   2. Switching to `cqi` was not enough on its own: the nearest container was
      `.gu-band`, which is the FULL-WIDTH section. `cqi` still measured 1440px
      and still overflowed the column.
   Declaring the copy column a container makes `cqi` mean what it looks like it
   means. 9cqi resolves to ~49px in a 550px column and ~29px in a 326px phone
   column — both fit the longest word in this site's headings. */
.gu-hero__copy {
  container-type: inline-size;
  container-name: herocopy;
}
.gu-hero__title {
  font-size: clamp(1.75rem, 9cqi, 3.5rem);
  margin-bottom: var(--gu-space-sm);
}
.gu-hero__sub { font-size: var(--gu-text-lg); color: var(--gu-fg-muted); max-width: 58ch; }
.gu-hero .gu-figure img { max-height: 70vh; object-fit: cover; }

/* ── Sections ───────────────────────────────────────────────────────────── */
.gu-section__head { max-width: var(--gu-measure); margin-bottom: var(--gu-space-lg); }
.gu-section__title { font-size: var(--gu-text-3xl); }

/* ── Cards ──────────────────────────────────────────────────────────────── */
.gu-grid { display: grid; gap: var(--gu-space-md); }
.gu-grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }
.gu-grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); }
.gu-grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); }
.gu-grid > * { min-width: 0; }               /* the no-spill rule, per track */

.gu-card {
  display: flex; flex-direction: column;
  padding: var(--gu-space-md);
  background: var(--gu-bg-raised);
  border: 1px solid var(--gu-rule);
  border-radius: var(--gu-radius-md);
  transition: border-color var(--gu-dur-fast) var(--gu-ease),
              transform var(--gu-dur-fast) var(--gu-ease);
}
.gu-card:hover { border-color: var(--gu-accent); transform: translateY(-2px); }
.gu-card__title { font-size: var(--gu-text-xl); margin-bottom: var(--gu-space-2xs); }
.gu-card__body { color: var(--gu-fg-muted); flex: 1; }
.gu-card__media { margin: calc(var(--gu-space-md) * -1) calc(var(--gu-space-md) * -1) var(--gu-space-sm); }
.gu-card__media img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover;
                      border-radius: var(--gu-radius-md) var(--gu-radius-md) 0 0; }
.gu-card--link { text-decoration: none; color: inherit; }
.gu-card--link:hover .gu-card__title { color: var(--gu-accent); }
.gu-card--link:focus-visible { outline: 2px solid var(--gu-accent); outline-offset: 3px; }

/* ── Child listing ──────────────────────────────────────────────────────────
   The grid an index page uses to LINK its children. It is the same .gu-card as
   everywhere else; what it adds is an even card height, so a listing of 65
   webinars does not read as a ragged wall.
   ⚠️ The excerpt is CLAMPED, never truncated. The full text stays in the DOM —
   clamping is a display decision and a build-time cut would be a content one,
   and these excerpts are already the legacy site's own truncations. */
.gu-cardlist { align-items: stretch; margin-bottom: var(--gu-space-xl); }
.gu-cardlist:last-child { margin-bottom: 0; }
.gu-cardlist .gu-card__title { font-size: var(--gu-text-lg); }
.gu-cardlist .gu-card__body { font-size: var(--gu-text-sm); margin-top: var(--gu-space-2xs); }
.gu-cardlist .gu-card__body p {
  display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden;
}

/* ── HTML sitemap ───────────────────────────────────────────────────────────
   A flat link list per namespace, in as many columns as the band can hold.
   ⚠️ COLUMNS, not a grid. Grid rows are as tall as their tallest cell, so a
   2-link "Site" group beside a 24-link "Insights" group left a screen and a
   half of empty space under it. Multi-column flows the groups instead and
   balances them; `break-inside: avoid` keeps a group's links with its heading. */
.gu-sitemap { columns: 3 260px; column-gap: var(--gu-space-lg); }
.gu-sitemap__group { break-inside: avoid; margin-bottom: var(--gu-space-lg); }
.gu-sitemap .gu-section__title { font-size: var(--gu-text-xl); margin-bottom: var(--gu-space-xs); }
.gu-linklist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gu-space-3xs); }
.gu-linklist > * { min-width: 0; }
.gu-linklist a { color: var(--gu-fg-muted); text-decoration: none; font-size: var(--gu-text-sm); }
.gu-linklist a:hover { color: var(--gu-accent); text-decoration: underline; }

/* ── Media ──────────────────────────────────────────────────────────────── */
.gu-figure { margin: 0; }
.gu-figure img { width: 100%; border-radius: var(--gu-radius-md); }
.gu-figure figcaption { margin-top: var(--gu-space-2xs); font-size: var(--gu-text-sm); color: var(--gu-fg-muted); }
.gu-embed { position: relative; aspect-ratio: 16 / 9; border-radius: var(--gu-radius-md); overflow: hidden; }
.gu-embed > * { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ── Split ──────────────────────────────────────────────────────────────── */
.gu-split { display: grid; gap: var(--gu-space-xl); align-items: center; }
@container band (min-width: 780px) { .gu-split { grid-template-columns: 1fr 1fr; } }

/* ── Lists ──────────────────────────────────────────────────────────────── */
.gu-checklist { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gu-space-xs); }
.gu-checklist li { display: grid; grid-template-columns: 1.4em 1fr; gap: var(--gu-space-2xs); align-items: start; }
/* A 29-item list in one narrow column is a scroll, not a list. Above 8 items it
   flows into as many columns as the BAND can hold — container-driven, so it is
   one column in a sidebar and three in a full-width section with no breakpoint. */
.gu-checklist--cols { grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr)); column-gap: var(--gu-space-lg); }
.gu-checklist .gu-icon { color: var(--gu-accent); margin-top: 0.2em; }

/* ── FAQ ────────────────────────────────────────────────────────────────── */
.gu-faq { border-top: 1px solid var(--gu-rule); }
.gu-faq details { border-bottom: 1px solid var(--gu-rule); }
.gu-faq summary {
  cursor: pointer; list-style: none; padding: var(--gu-space-sm) 0;
  display: flex; align-items: center; justify-content: space-between; gap: var(--gu-space-sm);
  font-family: var(--gu-font-display); font-weight: 600; font-size: var(--gu-text-lg);
}
.gu-faq summary::-webkit-details-marker { display: none; }
.gu-faq summary .gu-icon { transition: transform var(--gu-dur-fast) var(--gu-ease); }
.gu-faq details[open] summary .gu-icon { transform: rotate(180deg); }
.gu-faq__body { padding-bottom: var(--gu-space-sm); color: var(--gu-fg-muted); }

/* ── Quote ──────────────────────────────────────────────────────────────── */
.gu-quote { border-left: 3px solid var(--gu-accent); padding-left: var(--gu-space-md); margin: 0; }
.gu-quote p { font-size: var(--gu-text-lg); }

/* ── Breadcrumbs ────────────────────────────────────────────────────────── */
.gu-crumbs { font-size: var(--gu-text-sm); color: var(--gu-fg-muted); margin-bottom: var(--gu-space-sm); }
.gu-crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--gu-space-2xs); }
.gu-crumbs li { display: flex; align-items: center; gap: var(--gu-space-2xs); }
.gu-crumbs li + li::before { content: "/"; color: var(--gu-rule); }
.gu-crumbs a { color: inherit; text-decoration: none; }
.gu-crumbs a:hover { color: var(--gu-accent); text-decoration: underline; }

/* ── Footer ─────────────────────────────────────────────────────────────── */
.gu-footer { border-top: 1px solid var(--gu-rule); padding-block: var(--gu-space-xl) var(--gu-space-lg); }
.gu-footer__inner { max-width: var(--gu-max-width); margin-inline: auto; padding-inline: var(--gu-gutter); }
.gu-footer__cols { display: grid; gap: var(--gu-space-lg);
                   grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); }
.gu-footer__logo { width: 180px; margin-bottom: var(--gu-space-sm); }
.gu-footer h2 { font-size: var(--gu-text-sm); letter-spacing: 0.16em; color: var(--gu-fg-muted); margin-bottom: var(--gu-space-xs); }
.gu-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gu-space-3xs); }
.gu-footer a { color: var(--gu-fg); text-decoration: none; font-size: var(--gu-text-sm); }
.gu-footer a:hover { color: var(--gu-accent); text-decoration: underline; }
.gu-footer__bottom {
  margin-top: var(--gu-space-xl); padding-top: var(--gu-space-sm);
  border-top: 1px solid var(--gu-rule);
  display: flex; flex-wrap: wrap; gap: var(--gu-space-sm);
  justify-content: space-between; font-size: var(--gu-text-sm); color: var(--gu-fg-muted);
}
.gu-social { display: flex; gap: var(--gu-space-xs); }
.gu-social a { display: inline-flex; width: 40px; height: 40px; align-items: center; justify-content: center;
               border: 1px solid var(--gu-rule); border-radius: var(--gu-radius-sm); }
.gu-social a:hover { border-color: var(--gu-accent); color: var(--gu-accent); }
.gu-social .gu-icon { width: 20px; height: 20px; fill: currentColor; stroke: none; }

/* ── Reveal on scroll ───────────────────────────────────────────────────────
   Opt-in via JS adding .is-in. Without JS the element is simply visible — the
   initial state is only applied when the class hook exists, so content is never
   hidden behind a script that failed to run. */
.js .gu-reveal { opacity: 0; transform: translateY(12px);
                 transition: opacity var(--gu-dur-slow) var(--gu-ease-out),
                             transform var(--gu-dur-slow) var(--gu-ease-out); }
.js .gu-reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .gu-reveal { opacity: 1; transform: none; }
}
