/* ====================================================================
   Use Cases & Skills view
   --------------------------------------------------------------------
   Third home-page view (alongside Graph and Catalogue). Ported from the
   standalone Use Case Library prototype and baked into the platform.

   Everything is scoped under #useCasesView so it cannot affect the rest
   of the home page. Class names that collide with the platform's own
   stylesheet (hero / grid / video / badge / section-label / prompt-code /
   module-card) are uc- prefixed; the ID-scoped specificity guarantees the
   rest win the cascade. Tokens are reused from css/style.css.
   ==================================================================== */

#useCasesView {
  /* Library type accents (accessible on light surfaces) */
  --type-skill: #007A5E;
  --type-skill-soft: rgba(23, 206, 149, 0.12);
  --type-agent: #6161FF;
  --type-agent-soft: rgba(97, 97, 255, 0.10);
  --type-technique: #0084B2;
  --type-technique-soft: rgba(0, 177, 255, 0.10);
  /* Orchid, not amber: amber is the "Coming soon" state colour on a card now,
     and a type identity must not read as a state. Darkened for this light
     surface, the same way --type-skill (#007A5E) is the dark twin of the green
     the catalogue tag uses. Pairs with .course-category-tag--loop in index.html. */
  --type-loop: #A21CAF;
  --type-loop-soft: rgba(162, 28, 175, 0.12);
  /* Use case = the parent/problem page (UC-3.2); brand slate, set apart from
     the four takeaway-type accents above. */
  --type-use_case: #1B2F3C;
  --type-use_case-soft: rgba(27, 47, 60, 0.09);
  --font-mono: 'Courier New', monospace;
}

/* On the standalone detail page (use-case.html) the view is always shown,
   regardless of the home page's body.view-* class that hides it elsewhere. */
#useCasesView[data-detail-page] { display: block; }

/* Scoped reset — the standalone file relied on `* { margin:0; padding:0 }`. */
#useCasesView, #useCasesView * { box-sizing: border-box; }
#useCasesView h1, #useCasesView h2, #useCasesView h3, #useCasesView h4,
#useCasesView p, #useCasesView ul, #useCasesView ol, #useCasesView figure {
  margin: 0; padding: 0;
}
#useCasesView ul { list-style: none; }

/* ====================================================================
   Toolbar — search + dropdown filters
   --------------------------------------------------------------------
   Mirrors the Catalogue explorer (#exploreToolbar). The .xp-* classes are
   styled globally in css/style.css; the Catalogue's own carded container look
   is #exploreToolbar-scoped, so it's replicated here for #uc-toolbar.
   ==================================================================== */
/* Match the standalone prototype's content column. */
#useCasesView #uc-browse { max-width: 1200px; margin: 0 auto; }
/* In the home-page catalogue, the Use Cases view breaks out to the catalogue
   width (see css/style.css), so let its browse column fill that width and line
   up with the course grid instead of staying at the prototype's 1200px. */
body.view-usecases #useCasesView #uc-browse { max-width: none; }

/* No card. This panel earned one while it held a search field and six facet
   controls; both moved into the view band, and what is left is the readout —
   the active chips and the match count. A bordered, shadowed box around two
   lines of status text is heavier than the information in it, and it read as a
   component floating between the band and the results rather than as a caption
   on them. #exploreToolbar lost the same box for the same reason.
   The margins go with it: --spacing-sm above and --spacing-lg below were holding
   a card apart from its neighbours, and left the count marooned in the gap under
   the band. It now sits close under the band, where a caption belongs. */
#useCasesView #uc-toolbar {
  margin: 0 0 var(--spacing-sm);
}
#useCasesView #uc-toolbar .xp-count { margin: 0.35rem 0 0; }

/* ====================================================================
   Card grid
   --------------------------------------------------------------------
   Home-page library cards carry .module-card and reuse the Catalogue grid
   (.modules-grid) + card surface, hover and locked styling wholesale. The
   only touch-ups needed here:
     1. #useCasesView's scoped reset zeroes h3/p margins (higher specificity
        than .module-title / .module-subtitle), so restore the card's spacing.
     2. Pin the platform row to the card foot, mirroring the progress bar.
   The .uc-badge / .blocks / .platrow rules below are still used by the detail
   view (buildDetail), so they stay.
   ==================================================================== */
#useCasesView .modules-grid { padding-top: var(--spacing-md); }

#useCasesView .module-card .module-title { margin: 0 0 4px; }
#useCasesView .module-card .module-subtitle {
  margin: 0 0 12px;
  display: -webkit-box;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: calc(1.45em * 4);
}
#useCasesView .module-card .uc-platrow { margin-top: auto; margin-bottom: 0; }
#useCasesView .uc-plat {
  font-size: 0.7rem;
  font-weight: 600;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-sm);
  padding: 0.12rem 0.5rem;
  color: rgba(255, 255, 255, 0.72);
  background: rgba(255, 255, 255, 0.06);
}

#useCasesView .uc-badge {
  align-self: flex-start;
  display: inline-block;
  padding: 0.25rem 0.75rem;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
#useCasesView .uc-badge--skill { background: var(--type-skill-soft); color: var(--type-skill); }
#useCasesView .uc-badge--agent { background: var(--type-agent-soft); color: var(--type-agent); }
#useCasesView .uc-badge--technique { background: var(--type-technique-soft); color: var(--type-technique); }
#useCasesView .uc-badge--loop { background: var(--type-loop-soft); color: var(--type-loop); }

/* Spec-plate block meter — used by the detail view's .plate / .bigplate. */
#useCasesView .blocks { letter-spacing: 2px; color: var(--color-accent-2-accessible); font-size: 0.7rem; }
#useCasesView .blocks .off { color: var(--color-border); }
#useCasesView .platrow { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-top: 0.1rem; }
#useCasesView .plat {
  font-size: 0.7rem;
  font-weight: 600;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.1rem 0.45rem;
  color: var(--color-text-muted);
  background: var(--color-off-white);
}

#useCasesView .uc-empty { grid-column: 1 / -1; text-align: center; padding: 4rem 1.5rem; color: var(--color-text-muted); }
#useCasesView .uc-empty b { display: block; font-size: 1.15rem; font-weight: 700; color: var(--color-text-primary); margin-bottom: 0.4rem; }

/* ====================================================================
   Detail view
   ==================================================================== */
#useCasesView #uc-detail { display: none; max-width: 980px; margin: 0 auto; padding-bottom: var(--spacing-2xl); }
#useCasesView .back {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--color-text-primary);
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: 99px;
  padding: 0.55rem 1.1rem;
  cursor: pointer;
  margin-bottom: var(--spacing-lg);
  transition: all var(--duration-fast) var(--ease-out);
}
#useCasesView .back:hover { border-color: var(--color-accent-2-accessible); color: var(--color-accent-2-accessible); }

#useCasesView .dhero {
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-xl);
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: var(--spacing-xl);
  box-shadow: var(--shadow-sm);
}
#useCasesView .dhero h1 {
  font-size: clamp(1.6rem, 3.2vw, 2.25rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 0.7rem 0 0.5rem;
}
#useCasesView .dhero .outcome { color: var(--color-text-secondary); font-size: 0.95rem; }
#useCasesView .dhero .platrow { margin-top: var(--spacing-md); }

/* Spec plate — dark stat panel */
#useCasesView .bigplate {
  background: var(--gradient-stat);
  color: var(--color-white);
  border-radius: var(--radius-lg);
  padding: var(--spacing-lg);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  align-self: start;
  display: grid;
  grid-template-columns: auto 1fr auto;
  row-gap: 0.6rem;
  column-gap: 0.9rem;
  box-shadow: var(--shadow-md);
}
#useCasesView .bigplate .head {
  grid-column: 1 / -1;
  text-transform: uppercase;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.6);
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  padding-bottom: 0.5rem;
}
#useCasesView .bigplate .lbl { text-transform: uppercase; font-size: 0.7rem; color: rgba(255, 255, 255, 0.65); }
#useCasesView .bigplate .blocks { color: var(--color-accent-1); }
#useCasesView .bigplate .blocks .off { color: rgba(255, 255, 255, 0.18); }
#useCasesView .bigplate .val { text-align: right; color: var(--color-white); }

/* Content sections */
#useCasesView .dsection {
  margin-top: var(--spacing-md);
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--spacing-xl);
  box-shadow: var(--shadow-sm);
}
#useCasesView .uc-section-label {
  display: inline-block;
  padding: 4px 12px;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-radius: 6px;
  margin-bottom: var(--spacing-md);
  background: rgba(0, 177, 255, 0.1);
  color: var(--color-accent-2-accessible);
}
#useCasesView .dsection p { color: var(--color-text-secondary); font-size: 0.95rem; }
#useCasesView .dsection p + p { margin-top: 0.6rem; }

/* Video placeholder */
#useCasesView .uc-video {
  aspect-ratio: 16 / 9;
  /* Height floor so the box can never collapse to ~0 for the frame before
     `aspect-ratio` resolves its height — without it the centred play button
     briefly renders at the top of the container (and pokes above the edge)
     on first paint. See PRESENTER-NOTES / use-case intro placeholder. */
  min-height: 200px;
  border-radius: var(--radius-md);
  background: var(--gradient-hero);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: var(--spacing-md);
  color: var(--color-white);
  position: relative;
  overflow: hidden;
}
#useCasesView .uc-video::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 30% 20%, rgba(0, 255, 188, 0.08), transparent 60%);
}
#useCasesView .uc-video .play {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--gradient-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow-lg);
  position: relative;
  transition: transform var(--duration-fast) var(--ease-out);
}
#useCasesView .uc-video .play:hover { transform: scale(1.06); }
#useCasesView .uc-video .play::after {
  content: '';
  width: 0; height: 0;
  border-style: solid;
  border-width: 11px 0 11px 19px;
  border-color: transparent transparent transparent var(--color-primary);
  margin-left: 4px;
}
#useCasesView .uc-video .vmeta {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
  position: relative;
}

/* Real Mux intro video: the signed <mux-player> fills the 16:9 slot. */
#useCasesView .uc-video--mux {
  background: #000;
  /* Resolve the 16:9 height in the FIRST layout pass via the padding-ratio
     technique rather than `aspect-ratio`, which can resolve a frame late on
     reveal — collapsing the box so the centred loading play-button flashes
     near the top before snapping to centre. `.video-embed` below is
     position:absolute; inset:0, so it fills this padded box exactly. */
  aspect-ratio: auto;
  min-height: 0;
  height: 0;
  padding-bottom: 56.25%; /* 16 / 9 */
}
#useCasesView .uc-video--mux .video-embed {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
#useCasesView .uc-video--mux mux-player {
  width: 100%;
  height: 100%;
  display: block;
  border-radius: inherit;
  --controls-backdrop-color: rgba(0, 0, 0, 0.4);
}
#useCasesView .uc-video--mux .mux-video-error {
  color: rgba(255, 255, 255, 0.9);
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0 var(--spacing-lg);
  text-align: center;
}

/* Steps */
#useCasesView .steps { counter-reset: s; display: flex; flex-direction: column; }
#useCasesView .step {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: var(--spacing-md);
  padding: 0.9rem 0;
  border-bottom: 1px dashed var(--color-border);
}
#useCasesView .step:last-child { border-bottom: none; }
#useCasesView .step::before {
  counter-increment: s;
  content: counter(s, decimal-leading-zero);
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--color-accent-2-accessible);
  padding-top: 2px;
}
#useCasesView .step b { display: block; font-weight: 600; margin-bottom: 2px; font-size: 0.95rem; }
#useCasesView .step span { color: var(--color-text-secondary); font-size: 0.875rem; }

/* What's involved */
#useCasesView .need { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--spacing-sm); }
#useCasesView .need div {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.85rem 1rem;
  font-size: 0.875rem;
  background: var(--color-off-white);
  color: var(--color-text-secondary);
}
#useCasesView .need b {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  margin-bottom: 0.3rem;
}

/* Platforms */
#useCasesView .plats { display: flex; flex-direction: column; }
#useCasesView .plats .prow {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: var(--spacing-md);
  padding: 0.7rem 0;
  border-bottom: 1px dashed var(--color-border);
  font-size: 0.875rem;
}
#useCasesView .plats .prow:last-child { border-bottom: none; }
#useCasesView .plats .pname { font-weight: 600; font-size: 0.85rem; }
#useCasesView .plats .pnote { color: var(--color-text-secondary); }
#useCasesView .tick { color: var(--color-accent-1-accessible); font-weight: 700; margin-right: 6px; }
#useCasesView .part { color: var(--color-deep-cerulean); font-weight: 700; margin-right: 6px; }

/* Worked example (used by skills that supply an `example` block) */
#useCasesView .example {
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-accent-2);
  border-radius: var(--radius-md);
  background: var(--color-off-white);
  padding: var(--spacing-lg);
  margin-top: var(--spacing-sm);
}
#useCasesView .example .q { font-weight: 600; color: var(--color-text-primary); font-size: 0.95rem; margin-bottom: 0.5rem; }
#useCasesView .example .a { color: var(--color-text-secondary); font-size: 0.9rem; }
#useCasesView .example .a b { color: var(--color-text-primary); }

/* ====================================================================
   Get-it block
   ==================================================================== */
#useCasesView .getit {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-top: var(--spacing-md);
  box-shadow: var(--shadow-md);
}
#useCasesView .getit .ghead {
  background: var(--gradient-stat);
  color: var(--color-white);
  padding: var(--spacing-md) var(--spacing-xl);
  display: flex;
  align-items: center;
  gap: var(--spacing-md);
  flex-wrap: wrap;
}
#useCasesView .getit .ghead h2 { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }
#useCasesView .getit .ghead .uc-badge { margin-left: auto; background: rgba(255, 255, 255, 0.92); }
#useCasesView .getit .gbody { background: var(--color-white); padding: var(--spacing-xl); }
#useCasesView .getit .gbody > p { font-size: 0.95rem; color: var(--color-text-secondary); margin-bottom: var(--spacing-md); }

#useCasesView .uc-prompt-code {
  padding: var(--spacing-lg);
  background: var(--color-off-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-family: var(--font-mono);
  font-size: 0.85rem;
  line-height: 1.6;
  color: var(--color-text-primary);
  white-space: pre-wrap;
  word-break: break-word;
  overflow-x: auto;
  margin: 0 0 var(--spacing-md) 0;
}
#useCasesView .uc-prompt-code .cm { color: var(--color-text-muted); }
#useCasesView .uc-prompt-code .dir { font-weight: 700; }
#useCasesView .gnote { font-size: 0.8rem; color: var(--color-text-muted); margin: var(--spacing-sm) 0; }
#useCasesView .gnote b { color: var(--color-text-primary); }

#useCasesView .btnrow { display: flex; gap: var(--spacing-sm); flex-wrap: wrap; margin-top: var(--spacing-md); }
#useCasesView .btn {
  font-weight: 600;
  font-size: 0.875rem;
  padding: 0.7rem 1.4rem;
  border-radius: var(--radius-md);
  border: none;
  cursor: pointer;
  background: var(--gradient-accent);
  color: var(--color-primary);
  transition: all var(--duration-normal) var(--ease-out);
}
#useCasesView .btn:hover { transform: translateY(-2px); box-shadow: var(--shadow-md), var(--shadow-glow-subtle); }
#useCasesView .btn.sec {
  background: var(--color-white);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border);
}
#useCasesView .btn.sec:hover { border-color: var(--color-accent-2-accessible); color: var(--color-accent-2-accessible); box-shadow: var(--shadow-sm); }

#useCasesView .customise { margin-top: 0.5rem; font-size: 0.875rem; list-style: none; }
#useCasesView .customise li {
  padding-left: 1.4rem;
  position: relative;
  margin-bottom: 0.4rem;
  color: var(--color-text-secondary);
}
#useCasesView .customise li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--gradient-accent);
}

/* ====================================================================
   Loop parts — eight-field structured definition list (D5)
   Orchid loop accent (--type-loop / --type-loop-soft) already declared above.
   ==================================================================== */
#useCasesView .loop-parts {
  display: flex;
  flex-direction: column;
  gap: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin: 0 0 var(--spacing-md) 0;
  background: var(--color-white);
}
#useCasesView .loop-part {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: var(--spacing-md);
  padding: 0.75rem 1rem;
  border-bottom: 1px dashed var(--color-border);
  font-size: 0.875rem;
  align-items: baseline;
}
#useCasesView .loop-part:last-child { border-bottom: none; }
#useCasesView .loop-part-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--type-loop);
  flex-shrink: 0;
}
#useCasesView .loop-part-body {
  color: var(--color-text-secondary);
  line-height: 1.55;
}

/* ====================================================================
   Skill parts — labelled anatomy (Triggers on / Needs / Does / You get),
   the adapt/portability callout, and the collapsible SKILL.md file view.
   Green skill accent (--type-skill / --type-skill-soft) declared above.
   ==================================================================== */
#useCasesView .skill-parts {
  display: flex;
  flex-direction: column;
  gap: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin: 0 0 var(--spacing-md) 0;
  background: var(--color-white);
}
#useCasesView .skill-part {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: var(--spacing-md);
  padding: 0.75rem 1rem;
  border-bottom: 1px dashed var(--color-border);
  font-size: 0.875rem;
  align-items: baseline;
}
#useCasesView .skill-part:last-child { border-bottom: none; }
#useCasesView .skill-part-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--type-skill);
  flex-shrink: 0;
}
#useCasesView .skill-part-body {
  color: var(--color-text-secondary);
  line-height: 1.55;
}

/* Portability caveat — surfaced, not buried in the SKILL.md */
#useCasesView .skill-adapt {
  border: 1px solid var(--type-skill);
  border-left-width: 4px;
  border-radius: var(--radius-md);
  background: var(--type-skill-soft);
  padding: 0.75rem 1rem;
  margin: 0 0 var(--spacing-md) 0;
  font-size: 0.85rem;
}
#useCasesView .skill-adapt-label {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--type-skill);
  margin-bottom: 0.3rem;
}
#useCasesView .skill-adapt-body {
  color: var(--color-text-secondary);
  line-height: 1.55;
}

/* Safe-use guidance — a caution callout, surfaced not buried */
#useCasesView .skill-safe {
  border: 1px solid var(--warn);
  border-left-width: 4px;
  border-radius: var(--radius-md);
  background: var(--warn-bg);
  padding: 0.75rem 1rem;
  margin: 0 0 var(--spacing-md) 0;
  font-size: 0.85rem;
}
#useCasesView .skill-safe-label {
  display: block;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--warn);
  margin-bottom: 0.3rem;
}
#useCasesView .skill-safe-body {
  color: var(--color-text-secondary);
  line-height: 1.55;
}

/* Collapsible SKILL.md + folder tree */
#useCasesView .skill-file {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin: 0 0 var(--spacing-md) 0;
  overflow: hidden;
}
#useCasesView .skill-file > summary {
  cursor: pointer;
  padding: 0.7rem 1rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--type-skill);
  list-style: revert;
  user-select: none;
}
#useCasesView .skill-file[open] > summary { border-bottom: 1px solid var(--color-border); }
#useCasesView .skill-file-body { padding: var(--spacing-md) 1rem 0.5rem; }
#useCasesView .skill-file-body .gnote { margin-top: 0.5rem; }

/* Agent takeaway anatomy (agent-engineering standard) — mirrors the skill parts,
   accented with the agent type colour. safe_use reuses .skill-safe (type-neutral). */
#useCasesView .agent-parts {
  display: flex;
  flex-direction: column;
  gap: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  margin: 0 0 var(--spacing-md) 0;
  background: var(--color-white);
}
#useCasesView .agent-part {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: var(--spacing-md);
  padding: 0.75rem 1rem;
  border-bottom: 1px dashed var(--color-border);
  font-size: 0.875rem;
  align-items: baseline;
}
#useCasesView .agent-part:last-child { border-bottom: none; }
#useCasesView .agent-part-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--type-agent);
  flex-shrink: 0;
}
#useCasesView .agent-part-body {
  color: var(--color-text-secondary);
  line-height: 1.55;
}
/* Collapsible system-instructions prompt — the agent equivalent of .skill-file */
#useCasesView .agent-file {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  margin: 0 0 var(--spacing-md) 0;
  overflow: hidden;
}
#useCasesView .agent-file > summary {
  cursor: pointer;
  padding: 0.7rem 1rem;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--type-agent);
  list-style: revert;
  user-select: none;
}
#useCasesView .agent-file[open] > summary { border-bottom: 1px solid var(--color-border); }

/* ====================================================================
   D6 UX additions — hero CTA, type caption, smooth scroll
   ==================================================================== */
#useCasesView html { scroll-behavior: smooth; }

/* Type caption: small orienting line under the badge */
#useCasesView .uc-type-caption {
  font-size: 0.78rem;
  color: var(--color-text-muted);
  margin: 0.35rem 0 0 0;
  line-height: 1.4;
}

/* Hero CTA button — anchors to #get-it; sits below the platform pills */
#useCasesView .uc-hero-cta {
  display: inline-block;
  margin-top: var(--spacing-md);
  font-weight: 600;
  font-size: 0.875rem;
  padding: 0.65rem 1.3rem;
  border-radius: var(--radius-md);
  border: none;
  cursor: pointer;
  background: var(--gradient-accent);
  color: var(--color-primary);
  text-decoration: none;
  transition: all var(--duration-normal) var(--ease-out);
}
#useCasesView .uc-hero-cta:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md), var(--shadow-glow-subtle);
}

/* ====================================================================
   Responsive
   ==================================================================== */
@media (max-width: 760px) {
  #useCasesView .dhero { grid-template-columns: 1fr; padding: var(--spacing-lg); }
  #useCasesView .dsection, #useCasesView .getit .gbody { padding: var(--spacing-lg); }
  #useCasesView .getit .ghead { padding: var(--spacing-md) var(--spacing-lg); }
  #useCasesView .plats .prow { grid-template-columns: 1fr; gap: 0.2rem; }
  #useCasesView .loop-part { grid-template-columns: 1fr; gap: 0.15rem; }
  #useCasesView .loop-part-label { margin-bottom: 0; }
  #useCasesView .skill-part { grid-template-columns: 1fr; gap: 0.15rem; }
  #useCasesView .skill-part-label { margin-bottom: 0; }
  #useCasesView .agent-part { grid-template-columns: 1fr; gap: 0.15rem; }
  #useCasesView .agent-part-label { margin-bottom: 0; }
}

/* ---------- Use-case entity (UC-3.2): badge, try-now note, commitment ladder ---------- */
#useCasesView .uc-badge--use_case { background: var(--type-use_case-soft); color: var(--type-use_case); }

/* Note under the try-now prompt (try_now.notes). */
#useCasesView .getit .gbody .gnote { font-size: 0.85rem; color: var(--color-text-secondary); margin-top: var(--spacing-sm); }

/* The commitment ladder: TTV-ordered rungs, each with one or more takeaway cards. */
#useCasesView .uc-ladder-intro { font-size: 0.95rem; color: var(--color-text-secondary); margin-bottom: var(--spacing-md); }
#useCasesView .uc-rung { margin-bottom: var(--spacing-md); }
#useCasesView .uc-rung-head { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: var(--spacing-sm); }
#useCasesView .uc-rung-step { font-size: 0.95rem; font-weight: 700; color: var(--color-primary); letter-spacing: -0.01em; }
#useCasesView .uc-rung-meta { font-size: 0.78rem; color: var(--color-text-muted); }
#useCasesView .uc-rung-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--spacing-sm); }
#useCasesView .uc-rung-card {
  display: flex; flex-direction: column; gap: 0.35rem;
  padding: var(--spacing-md); background: var(--color-white);
  border: 1px solid var(--color-border); border-radius: 10px;
  text-decoration: none; transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}
#useCasesView .uc-rung-card:hover { border-color: var(--color-accent-1); box-shadow: 0 4px 14px rgba(0,0,0,0.07); transform: translateY(-1px); }
#useCasesView .uc-rung-card .uc-badge { align-self: flex-start; }
#useCasesView .uc-rung-title { font-size: 0.95rem; font-weight: 600; color: var(--color-primary); }
#useCasesView .uc-rung-outcome { font-size: 0.82rem; color: var(--color-text-secondary); line-height: 1.4; }

/* A rung this viewer cannot open. It is a <span>, not a link, so it cannot
   navigate — but it is still clickable and keyboard-reachable, and a click
   opens the lock dialog (PLA-80: a locked surface explains itself rather than
   ignoring you). Keeps its title and outcome so it still says what is behind
   the lock. Unreachable for the free tier now that the trial inherits the
   artefacts its use cases implement; this covers a `client:` audience. */
#useCasesView .uc-rung-card--locked { cursor: pointer; }
#useCasesView .uc-rung-card--locked .uc-rung-title { color: var(--color-text-secondary); }

/* The badge itself is styled HERE, in full, rather than relying on
   .module-status-tag from index.html's inline <style>. Rung cards render on
   use-case.html, which loads only style.css + this file — so inheriting that
   rule was never an option, and without these the badge came out as bare text
   next to an unsized SVG at its intrinsic size. Red matches the corner badge
   on a locked card in the catalogue: same fact, same colour. */
#useCasesView .uc-rung-card--locked .module-status-tag--locked {
  position: static;
  align-self: flex-start;
  margin-top: 0.15rem;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 9px;
  border-radius: 999px;
  border: 1px solid rgba(220, 38, 38, 0.32);
  background: rgba(220, 38, 38, 0.10);
  color: #B91C1C;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
}
#useCasesView .uc-rung-card--locked .module-status-tag--locked svg {
  width: 12px; height: 12px; flex-shrink: 0;
}

@media (max-width: 640px) {
  #useCasesView .uc-rung-cards { grid-template-columns: 1fr; }
}

/* A use-case card carries no tag row, so its title is the first thing in the
   card — and the lock badge is absolutely positioned in that same top-right
   corner. Nothing was reserving the space, so a locked card printed the badge
   straight over the title. A floated spacer the size of the badge (86x30) makes
   the first line or two of the title flow around it, which costs nothing on the
   cards that are not locked because it only exists when they are. */
#useCasesView [data-uc-card].module-card--unavailable .module-title::before {
  content: '';
  float: right;
  width: 94px;
  height: 30px;
}

/* ---------- Use-case-first landing + sub-view toggle (UC-3.3) ---------- */
#useCasesView .uc-subswitch {
  display: inline-flex; gap: 4px; padding: 4px;
  background: var(--color-off-white); border: 1px solid var(--color-border);
  border-radius: 99px; margin: var(--spacing-sm) 0 var(--spacing-lg);
}
#useCasesView .uc-subbtn {
  border: 0; background: transparent; padding: 0.5rem 1.15rem; border-radius: 99px;
  font-size: 0.85rem; font-weight: 600; color: var(--color-text-secondary);
  cursor: pointer; transition: all var(--duration-fast) var(--ease-out);
}
#useCasesView .uc-subbtn:hover { color: var(--color-text-primary); }
#useCasesView .uc-subbtn.is-active { background: var(--color-primary); color: var(--color-white); }

#useCasesView .uc-land-intro { margin-bottom: var(--spacing-md); }
#useCasesView .uc-land-title { font-size: clamp(1.4rem, 2.6vw, 1.9rem); font-weight: 700; letter-spacing: -0.02em; }
#useCasesView .uc-land-sub { font-size: 0.95rem; color: var(--color-text-secondary); max-width: 62ch; margin-top: 0.4rem; }
/* The landing's own search box and its eight `.uc-role` pills went with
   data/roles.json (PLA-91): one toolbar above the sub-switch now drives both
   toggles, and departments are a register axis rather than a curated pill row. */

/* DARK MODE — the active pill was invisible without these.
   The rule above pairs `background: var(--color-primary)` with
   `color: var(--color-white)`. In dark, --color-white is redefined as a
   SURFACE token and resolves to #1B2F3C, which is exactly what
   --color-primary already is — so the fill and the text became the same
   colour and the label disappeared. style.css flags this class of bug in its
   own dark block ("--color-white now resolves to #1B2F3C in dark, so these
   explicit overrides keep the text legible"); this selector was never added to
   that list, and this file had no dark overrides at all.

   Inverted rather than patched: on a dark ground the high-contrast pill is a
   light fill with dark text, which is the same treatment #exploreToolbar
   .xp-clear:hover already uses. */
:root[data-theme="dark"] #useCasesView .uc-subbtn.is-active {
  background: var(--color-accent-2);
  color: #08131B;
  border-color: var(--color-accent-2);
}
/* No prefers-color-scheme companion on purpose: the platform's theme is
   entirely data-theme driven (style.css uses prefers-color-scheme zero times),
   so an OS-preference rule here would fire on a light-theme page whose tokens
   had not flipped. */
#useCasesView #uc-land-count { margin-top: 0.8rem; }

#useCasesView .uc-fam { margin-bottom: var(--spacing-xl); }
#useCasesView .uc-fam-head {
  font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; color: var(--color-text-primary);
  margin-bottom: var(--spacing-md); padding-bottom: 0.4rem; border-bottom: 1px solid var(--color-border);
}

/* Rungs-available row on a use-case card (dark card surface). */
#useCasesView .uc-card-rungs { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; margin: 0.1rem 0 0.6rem; }
#useCasesView .uc-card-rungs-lbl { font-size: 0.68rem; color: rgba(255, 255, 255, 0.6); margin-right: 0.15rem; }
#useCasesView .uc-card-rungs .uc-badge { font-size: 0.6rem; padding: 0.12rem 0.4rem; letter-spacing: 0.04em; }

/* ---------- Takeaway → use-case up-link (UC-3.4) ---------- */
#useCasesView .uc-uplink { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin: 0.2rem 0 0.7rem; }
#useCasesView .uc-uplink-lbl { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-text-muted); }
#useCasesView .uc-uplink-item { font-size: 0.85rem; font-weight: 600; color: var(--color-accent-2-accessible); text-decoration: none; border-bottom: 1px solid transparent; }
#useCasesView .uc-uplink-item:hover { border-bottom-color: currentColor; }

/* ---------- Platform preference bar (UC-3.5) ---------- */
#useCasesView .uc-platform-pref { display: flex; align-items: center; justify-content: flex-end; gap: 0.5rem; margin-bottom: var(--spacing-sm); }
#useCasesView .uc-platform-pref label { font-size: 0.78rem; font-weight: 600; color: var(--color-text-muted); }

/* Back link and platform picker on ONE row, at every width.
   They were block-level siblings and stacked, which on a phone spent two
   rows of chrome before any content — and read as two unrelated controls
   rather than the page's one toolbar.

   nowrap on purpose: the whole point is that these two never separate, so
   the row is built to survive a narrow screen instead of wrapping out of
   it. The back link keeps its intrinsic size (it is a pill with a label
   that should not be cut) and the picker takes the remaining space and
   shrinks, because a <select> truncates gracefully and a button does not.

   The children's own bottom margins go: the row owns the spacing now, or
   the taller of the two would decide it. */
#useCasesView .uc-detail-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: nowrap;
  gap: var(--spacing-sm);
  margin-bottom: var(--spacing-lg);
}
#useCasesView .uc-detail-top .back { margin-bottom: 0; flex: 0 0 auto; }
#useCasesView .uc-detail-top .uc-platform-pref {
  margin-bottom: 0;
  flex: 1 1 auto;
  min-width: 0;
}
/* min-width: 0 on the wrapper too, or the select's intrinsic width keeps
   the flex item from ever shrinking and the row overflows instead. */
#useCasesView .uc-detail-top .xp-select-wrap { min-width: 0; }
#useCasesView .uc-detail-top select { max-width: 100%; }
/* nowrap first, and it does the real work. Measured at 320px the label broke
   to "Showing" / "for" and took the row to two lines high — the row was
   still ONE row by every geometric test, and still looked wrong. The select
   shrinking is the intended release valve, not the label rewrapping. */
#useCasesView .uc-detail-top .uc-platform-pref label { white-space: nowrap; }
/* Below about 380px the label goes entirely: "Showing for" is a nicety and
   the select keeps its own accessible name via aria-label. This is a
   viewport query while the rule above is container-independent, which is
   why both are here — the query cannot see a narrow column inside a wide
   window, and that is exactly the case the platform's own layout creates. */
@media (max-width: 380px) {
  #useCasesView .uc-detail-top .uc-platform-pref label { display: none; }
}

/* ====================================================================
   Per-subject use-case cards (designer handoff, Aug 2026)
   --------------------------------------------------------------------
   A use-case card takes its surface from its U-family, so a subject is
   recognisable before the title is read. Ported from the Claude Design
   project "Module Cards - Tiles.dc.html"; the generative art layer that
   pairs with each surface is built by js/uc-tiles.js.

   Scoped to [data-uc-card] rather than .module-card: course and module
   cards elsewhere on the home page keep the uniform navy gradient set
   in index.html, and only the use-case landing recolours. The base card
   there is ALREADY dark navy with white-alpha text, so for the seven
   dark families this is a background and border swap, nothing more.

   Two families are LIGHT surfaces (u4 blush, u5 grey) and flip the text
   to dark. That was the designer's decision and it is the right one:
   white on #EFACA8 is about 1.7:1. The overrides below are what make
   the light cards legible, so they are load-bearing, not polish.
   ==================================================================== */

/* The handoff's only keyframe was an opacity breath (0.7 to 1 over 6s).
   On its own that does not read as movement — it is a brightness change,
   and at that amplitude an observer sees a still image. So the art layer
   also DRIFTS: a slow scale-and-translate float, which is the motion
   the designer declared as `cc-drift` in her stylesheet but never
   applied to anything.

   The 1.08 baseline scale is what makes the drift safe. The art is a
   280x280 viewBox sliced to fill the card, so translating it without
   overscaling first would walk the artwork's edge into view. Everything
   below stays inside that margin.

   Both are composited transforms or opacity — no layout, no filter
   keyframes. Deliberately long and unsynchronised (22s drift against a
   6s breath) so a grid of cards never pulses in step. */
@keyframes uct-breathe { 0%, 100% { opacity: 0.72 } 50% { opacity: 1 } }
/* Her cc-pulse and cc-bloom, from the Aug 2026 revision, which is where the
   per-motif animation lives: the swarm and the dot field pulse, the blooms
   scale and brighten. Durations come from the markup (5s, 4.4s, 6s) via an
   inline animation-duration, so the values stay hers rather than becoming
   a set of near-identical class names here. */
@keyframes uct-pulse { 0%, 100% { opacity: 0.5 } 50% { opacity: 1 } }
/* Her cc-mist-a..d and cc-float, verbatim. The four mist vectors are
   deliberately unequal in both direction and scale; that asymmetry is
   what stops four blobs reading as one shape breathing. */
@keyframes uct-mist-a {
  0%, 100% { transform: translate(0, 0) scale(1) }
  50%      { transform: translate(38px, -30px) scale(1.2) }
}
@keyframes uct-mist-b {
  0%, 100% { transform: translate(0, 0) scale(1.1) }
  50%      { transform: translate(-34px, 28px) scale(1) }
}
@keyframes uct-mist-c {
  0%, 100% { transform: translate(0, 0) scale(1) }
  50%      { transform: translate(28px, 34px) scale(1.24) }
}
@keyframes uct-mist-d {
  0%, 100% { transform: translate(0, 0) scale(1.06) }
  50%      { transform: translate(-32px, -26px) scale(1.18) }
}
/* Six drift vectors, one per bucket in js/uc-tiles.js. Amplitudes sit in
   her 6-18px band for the tiles; the dots run the same vectors at a much
   shorter duration, which is what makes one read as a drift and the other
   as a current. Written out rather than driven by a custom property
   because var() inside @keyframes has a patchy history in Safari, the same
   reason uct-drift is written out twice below. */
@keyframes uct-drift-0 { 0%,100% { transform: translate(0,0) } 50% { transform: translate(14px, 2px) } }
@keyframes uct-drift-1 { 0%,100% { transform: translate(0,0) } 50% { transform: translate(7px, 11px) } }
@keyframes uct-drift-2 { 0%,100% { transform: translate(0,0) } 50% { transform: translate(-6px, 15px) } }
@keyframes uct-drift-3 { 0%,100% { transform: translate(0,0) } 50% { transform: translate(-13px, -3px) } }
@keyframes uct-drift-4 { 0%,100% { transform: translate(0,0) } 50% { transform: translate(-8px, -12px) } }
@keyframes uct-drift-5 { 0%,100% { transform: translate(0,0) } 50% { transform: translate(5px, -16px) } }
@keyframes uct-spin { to { transform: rotate(1turn) } }
/* Her cc-float1/2/3. Three vectors, not one: the doodle band is six
   drawings on six nearly identical pink cards, and a shared vector is what
   makes six of those read as one repeated card. Her scale(1.14) is dropped
   because these are stroked line art and scaling them thickens the stroke;
   the translation is what carries the drift. */
@keyframes uct-float {
  0%, 100% { transform: translate(0, 0) }
  50%      { transform: translate(-2%, -2.4%) }
}
@keyframes uct-float-2 {
  0%, 100% { transform: translate(0, 0) }
  50%      { transform: translate(2.2%, -1.6%) }
}
@keyframes uct-float-3 {
  0%, 100% { transform: translate(0, 0) }
  50%      { transform: translate(-1.6%, 2%) }
}
/* u5's three per-drawing animations, hers. The port dropped all three on
   the grounds that SMIL cannot be reached by prefers-reduced-motion, which
   is true of SMIL and not a reason to lose the motion — it is a reason to
   express it in CSS, which is what the rest of this file does. */
@keyframes uct-alarm {
  0%, 100% { r: 12px; opacity: 0.8 }
  50%      { r: 30px; opacity: 0 }
}
@keyframes uct-hand { to { transform: rotate(1turn) } }
@keyframes uct-runner { to { offset-distance: 100% } }
@keyframes uct-bloom {
  0%, 100% { transform: scale(1); opacity: 0.82 }
  50%      { transform: scale(1.1); opacity: 1 }
}
/* Pure translation at a CONSTANT scale, deliberately. The scale used to
   animate 1.08 to 1.13, which looked fine unfiltered but is the wrong
   shape of animation for a blurred layer: a scaling filtered element has
   to be re-rasterised every frame, where a translating one can be moved
   as a cached texture. Blur is invisible in a 5% zoom anyway, so nothing
   is lost by holding it still.

   The overscale is a correctness constraint, not taste. The art is a
   280-unit viewBox sliced to fill its box, so a translate walks its edge
   inward and a blur softens it further in; without the overscale the
   surface underneath would show through at the rim.

   Hence two sets rather than one. The CARD is not blurred, so it only has
   to cover the drift's own 1.4% of travel and 1.08 is ample — which is
   also the scale the cards were signed off at, so this keeps them where
   they were. The PAGE is blurred at 14px and needs margin for twice that
   as well, so it runs at 1.16. Written out rather than driven by a
   custom property inside the keyframe, because var() in @keyframes has a
   patchy history in Safari and this cannot be checked in a browser
   from here. */
@keyframes uct-drift {
  0%   { transform: scale(1.08) translate3d(-1.4%, -1%, 0) }
  50%  { transform: scale(1.08) translate3d(1.4%, 1.1%, 0) }
  100% { transform: scale(1.08) translate3d(-1.4%, -1%, 0) }
}
/* There is no uct-drift-page. The detail page's art layer is static by
   design, so it holds a plain scale(1.16) rather than animating one. See
   #uc-page-art .uc-art below. */

/* `isolation` earns its place: it makes the card a stacking context so
   the negative z-index below is contained. Without it a z-index:-1 child
   escapes to the nearest ancestor context and paints behind the card's
   own background, i.e. vanishes.

   And the art MUST be negative rather than z-index:0. Painting order
   puts in-flow block content (the title, the blurb) BELOW positioned
   descendants at z-index 0 or auto, so a z-index:0 art layer covers the
   card's text. The first version of this fixed that by forcing
   `position: relative` onto every card child, which also overrode the
   `position: absolute` on .module-status-tag and knocked the Locked and
   Coming soon badges out of the card corner into the content flow.
   Negative z-index gets the same result without reaching into children
   that have their own positioning for their own reasons. */
/* The Activities view borrows four of these families for its own cards
   (PLA-85). It is listed alongside #useCasesView on every rule below rather
   than handed a copy of the values, for the reason given at the top of the
   palette block: two copies of a gradient drift apart, one property cannot.
   js/activities-view.js maps each activity to a family and mounts the same
   UcTiles.art() layer the use-case cards use. */
#useCasesView [data-uc-card],
#activitiesView [data-uc-card] { isolation: isolate; }
#useCasesView [data-uc-card] .uc-art,
#activitiesView [data-uc-card] .uc-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
  transform-origin: center;
  /* NOT blurred, deliberately. Only the detail page's background is
     softened; a card is small, its art is already low-contrast behind
     opaque text, and blurring 49 of them costs a filtered compositing
     layer each for no legibility gain. No `filter` property at all
     rather than blur(0), which would still create the layer. */
  animation: uct-drift 22s ease-in-out infinite;
}
/* Communicate carries the breath on its inner wash rect, so the tiles
   stay put and only the light moves. The other eight have no separate
   light layer, so the whole art layer breathes as it drifts — both
   animations have to be named in ONE declaration or the second rule
   would replace the drift rather than add to it. */
#useCasesView [data-uc-card] .uc-art.uc-art-breathe,
#activitiesView [data-uc-card] .uc-art.uc-art-breathe {
  animation: uct-drift 22s ease-in-out infinite, uct-breathe 6s ease-in-out infinite;
}
#useCasesView [data-uc-card] .uc-art > .uc-art-breathe,
#activitiesView [data-uc-card] .uc-art > .uc-art-breathe {
  animation: uct-breathe 6s ease-in-out infinite;
}
/* Motif animations, applied INSIDE the art layer rather than to it, so they
   compose with the layer's own drift instead of replacing it. Scoped to
   .uc-art so they cannot reach anything else. Durations are overridden
   inline per family by js/uc-tiles.js. */
.uc-art .uc-art-pulse { animation: uct-pulse 5s ease-in-out infinite; }
/* u4's mist. Four vectors rather than one because the blobs have to move
   RELATIVE to each other: translate the group and it is a sliding
   backdrop, not mist. Unlike the bloom below these ellipses carry no
   filter, so scaling them is a cheap composited transform and her scale
   component is kept. Delays are seeded per blob in js/uc-tiles.js. */
.uc-art .uc-art-mist {
  transform-box: fill-box;
  transform-origin: center;
  animation: uct-mist-a 4s ease-in-out infinite;
}
.uc-art .uc-art-mist--b { animation-name: uct-mist-b; }
.uc-art .uc-art-mist--c { animation-name: uct-mist-c; }
.uc-art .uc-art-mist--d { animation-name: uct-mist-d; }
/* u5's doodles. One slow drift, duration seeded 15s-20s per card so two
   cards side by side never read as synchronised. Translation only: these
   are stroked line art and scaling them would thicken the strokes. */
/* The per-element wander, hers. Every square in the swarm and about half
   the dots in the field carry one; without it the motifs only dim up and
   down and the art reads as a still. Duration and phase are set inline per
   bucket by js/uc-tiles.js, inside her per-family band. */
.uc-art .uc-art-drift { animation: uct-drift-0 5s ease-in-out infinite; }
.uc-art .uc-art-drift--1 { animation-name: uct-drift-1; }
.uc-art .uc-art-drift--2 { animation-name: uct-drift-2; }
.uc-art .uc-art-drift--3 { animation-name: uct-drift-3; }
.uc-art .uc-art-drift--4 { animation-name: uct-drift-4; }
.uc-art .uc-art-drift--5 { animation-name: uct-drift-5; }
/* u3's orbits. Her cc-spin, at her 60-72s. transform-box/origin for the
   same reason the bloom needs them: a rotate on an SVG group pivots on the
   user-space origin otherwise and the rings swing off the card. */
.uc-art .uc-art-spin {
  transform-box: fill-box;
  transform-origin: center;
  animation: uct-spin 60s linear infinite;
}
.uc-art .uc-art-float {
  transform-box: fill-box;
  transform-origin: center;
  animation: uct-float 17s ease-in-out infinite;
}
.uc-art .uc-art-float--2 { animation-name: uct-float-2; }
.uc-art .uc-art-float--3 { animation-name: uct-float-3; }
/* The alarm ring on the incident trace. */
.uc-art .uc-art-alarm { animation: uct-alarm 3.2s ease-in-out infinite; }
/* The clock hand. Rotation about the dial centre, which is a fixed point
   in this drawing rather than the element's own box, so the origin is
   given in user units and transform-box stays at the default. */
.uc-art .uc-art-hand {
  transform-origin: 214px 178px;
  animation: uct-hand 10s linear infinite;
}
/* The dot running the workflow. Hidden by default and revealed only where
   offset-path works, because offset-path is what positions it: without
   support the circle would sit at 0,0 in the corner of the card. */
.uc-art .uc-art-runner { display: none; }
@supports (offset-path: path("M0,0 L1,1")) {
  .uc-art .uc-art-runner {
    display: block;
    offset-path: path("M36,84 C92,84 100,150 152,150 S214,150 244,150");
    animation: uct-runner 4.5s linear infinite;
  }
}
.uc-art .uc-art-bloom {
  animation: uct-bloom 6s ease-in-out infinite;
  /* Without these the scale would pivot on the SVG's user-space origin and
     the group would swing across the card rather than breathe in place. */
  transform-box: fill-box;
  transform-origin: center;
}
/* u4's ripple emitters, hers to the keyTime. Three properties animate per
   ring and each has its own timeline in her SMIL, which CSS reproduces
   exactly: a property absent from a keyframe interpolates across the
   keyframes that do declare it, so the opacity stop at 8% does not bend
   the radius ramp. Linear, because SMIL's default calcMode is linear and
   CSS's default is ease — left on ease the ring eases out of its own
   expansion and reads as a bubble rather than a pulse.

   `r` and `stroke-width` are animated as CSS properties rather than SMIL
   <animate> for the reason every other motion in this file is: no CSS
   selector can switch off a SMIL animation, so prefers-reduced-motion
   cannot reach one. Both are CSS-animatable SVG geometry properties in
   every browser the platform supports. */
@keyframes uct-ripple {
  0%   { r: 1px;  opacity: 0;    stroke-width: 3 }
  8%   {          opacity: 0.7 }
  38%  { r: 46px; opacity: 0;    stroke-width: 0.3 }
  100% { r: 46px; opacity: 0;    stroke-width: 0.3 }
}
@keyframes uct-ripple-in {
  0%   { r: 1px;  opacity: 0 }
  8%   {          opacity: 0.5 }
  38%  { r: 28px; opacity: 0 }
  100% { r: 28px; opacity: 0 }
}
@keyframes uct-ripple-core {
  0%   { opacity: 0.85 }
  12%  { opacity: 0 }
  100% { opacity: 0 }
}
.uc-art .uc-art-ripple {
  stroke-width: 2.6;
  animation: uct-ripple 4s linear infinite;
}
.uc-art .uc-art-ripple--in {
  stroke-width: 1.6;
  animation-name: uct-ripple-in;
}
.uc-art .uc-art-ripple--core { animation-name: uct-ripple-core; }
@media (prefers-reduced-motion: reduce) {
  .uc-art .uc-art-pulse,
  .uc-art .uc-art-bloom,
  .uc-art .uc-art-mist,
  .uc-art .uc-art-drift,
  .uc-art .uc-art-spin,
  .uc-art .uc-art-float,
  .uc-art .uc-art-hand { animation: none; opacity: 1; transform: none; }
  /* Holds at her resting radius rather than mid-pulse. */
  .uc-art .uc-art-alarm { animation: none; r: 12px; opacity: 0.8; }
  /* The runner only exists as a moving dot; parked, it is a sixth node
     the drawing never had, so it goes. */
  .uc-art .uc-art-runner { display: none; }
  /* The rings are an event, not a texture: with the animation off there is
     nothing for them to be, so they hold at their widest and faintest
     rather than stacking three hard circles on the emitter. */
  .uc-art .uc-art-ripple {
    animation: none;
    r: 46px;
    opacity: 0.12;
    stroke-width: 0.3;
  }
  .uc-art .uc-art-ripple--in { r: 28px; }
  .uc-art .uc-art-ripple--core { r: 2.4px; opacity: 0.5; }
}

@media (prefers-reduced-motion: reduce) {
  #useCasesView [data-uc-card] .uc-art,
  #useCasesView [data-uc-card] .uc-art.uc-art-breathe,
  #useCasesView [data-uc-card] .uc-art > .uc-art-breathe,
  #activitiesView [data-uc-card] .uc-art,
  #activitiesView [data-uc-card] .uc-art.uc-art-breathe,
  #activitiesView [data-uc-card] .uc-art > .uc-art-breathe {
    animation: none;
    opacity: 1;
    /* Hold the overscale. Dropping to scale(1) would reveal the sliced
       artwork's edge, which is the one thing the baseline scale exists
       to prevent. */
    transform: scale(1.08);
  }
}

/* ---------- the nine family palettes ----------
   Each family declares its surface ONCE, as custom properties, and both
   consumers read them: the card on the landing, and the whole page on
   a use-case detail view (`body[data-uc-fam]`, set by js/use-cases.js).
   Written as properties rather than as two sets of background rules
   because the point of the detail page picking up its subject's colour
   is that it is the SAME colour as the card you clicked. Two copies of
   a gradient drift apart; one property cannot. */

#useCasesView [data-uc-fam="u1-communicate"],
body[data-uc-fam="u1-communicate"] {
  --uc-surface: radial-gradient(140% 120% at 85% -12%, #1c9fca 0%, #0b87b4 18%, #075a77 46%, #052a3b 100%);
  --uc-edge: rgba(120, 205, 255, 0.22);
}
/* Communicate is the one family with more than one surface. TWO, as of the
   Aug 2026 revision: the first card of a row keeps the corner-lit gradient
   and every other card takes the centred one. The left- and right-lit
   variants are gone, and so is the light source that used to sit at the
   corner. js/uc-tiles.js points each card's radial wash at the same origin
   as its gradient. A detail page always takes variant 0. */
#useCasesView [data-uc-fam="u1-communicate"][data-uc-v="1"],
body[data-uc-fam="u1-communicate"][data-uc-v="1"] {
  --uc-surface: radial-gradient(120% 120% at 50% 50%, #1c9fca 0%, #0b87b4 20%, #075a77 52%, #052a3b 100%);
}

#useCasesView [data-uc-fam="u2-research-analyse"],
#activitiesView [data-uc-fam="u2-research-analyse"],
body[data-uc-fam="u2-research-analyse"] {
  --uc-surface: #1B2F3C;
  --uc-edge: rgba(150, 150, 255, 0.24);
}

#useCasesView [data-uc-fam="u3-plan-decide"],
#activitiesView [data-uc-fam="u3-plan-decide"],
body[data-uc-fam="u3-plan-decide"] {
  --uc-surface: radial-gradient(135% 125% at 50% 38%, #2f8f68 0%, #1e6b4c 42%, #123f2e 74%, #0d2f22 100%);
  --uc-edge: rgba(23, 206, 149, 0.4);
}

/* u4, u5 and u7 are LIGHT surfaces. u7 joined them in the Aug 2026
   revision, when it moved from a green gradient to grey. Their text is
   flipped to ink in the light-surface block further down; a fourth light
   family has to be added there as well as here. */
#useCasesView [data-uc-fam="u4-produce-content"],
body[data-uc-fam="u4-produce-content"] {
  --uc-surface: #96bec2;
  --uc-edge: #8fbfca;
}

/* The pink her doodles are drawn on. She used six different pinks across
   six cards, which is a contact sheet rather than a rule; this is the
   midpoint of that band, held flat so the family reads as one surface. */
/* Six surfaces, one per card, hers in her order. The default (no
   data-uc-v, and the detail page, which shows one family rather than a
   row) is the pale blush that most of her cards sit on. */
#useCasesView [data-uc-fam="u5-operate-document"],
body[data-uc-fam="u5-operate-document"] {
  --uc-surface: #FBE6E6;
  --uc-edge: #E2E8F0;
}
#useCasesView [data-uc-fam="u5-operate-document"][data-uc-v="0"] {
  --uc-surface: linear-gradient(90deg, #FF9EA5, #FFF0F0);
}
/* Restated rather than left to the family default above, even though the
   value is identical. All six of her surfaces then read as one set in one
   place, and `every card-background variant has a rule to land on` can
   tell a deliberate repeat from a variant somebody forgot. */
#useCasesView [data-uc-fam="u5-operate-document"][data-uc-v="1"] {
  --uc-surface: #FBE6E6;
}
#useCasesView [data-uc-fam="u5-operate-document"][data-uc-v="2"] {
  --uc-surface: #ffffff;
}
#useCasesView [data-uc-fam="u5-operate-document"][data-uc-v="3"] {
  --uc-surface: linear-gradient(180deg, #FFE5E5, #FFFFFF);
}
#useCasesView [data-uc-fam="u5-operate-document"][data-uc-v="4"] {
  --uc-surface: #FAE5E4;
}
/* The deep one. It is the only light-family surface dark enough to put
   the secondary ink under pressure, so it carries a WHITE scrim rather
   than the dark navy the other scrimmed families use — see
   --uc-scrim-rgb. The alpha is measured, like all the others. */
#useCasesView [data-uc-fam="u5-operate-document"][data-uc-v="5"] {
  --uc-surface: linear-gradient(290deg, #CA6268, #FDEDEC);
  --uc-scrim-rgb: 255 255 255;
  /* 0.16 is the measured minimum that clears 4.5:1 on the subtitle, which
     is the binding part here (3.86:1 unscrimmed). 0.18 for margin; 0.30
     also worked and washed the rose out for no benefit. */
  --uc-scrim: 0.18;
}

#useCasesView [data-uc-fam="u6-sell-negotiate"],
#activitiesView [data-uc-fam="u6-sell-negotiate"],
body[data-uc-fam="u6-sell-negotiate"] {
  --uc-surface: radial-gradient(135% 125% at 72% -10%, #1c5271 0%, #123a52 32%, #0c2739 64%, #081b28 100%);
  --uc-edge: rgba(92, 213, 255, 0.4);
}

/* Grey, and LIGHT — u7 joins u4 and u5 in the light-ink block below.
   Her eleven cards run #A6A6A6 to #DADADA with no pattern, so this is
   the light end of that band: the scribbles are mid-blue and need the
   contrast, and the card's ink is #1B2F3C. */
#useCasesView [data-uc-fam="u7-build-develop"],
#activitiesView [data-uc-fam="u7-build-develop"],
body[data-uc-fam="u7-build-develop"] {
  --uc-surface: #D0D0D0;
  --uc-edge: #E2E8F0;
}

/* Green now, not violet. The peach wash in the first layer stays: it is
   what keeps the green from reading as flat, and it is the only warm
   note on any of the nine surfaces. */
#useCasesView [data-uc-fam="u8-customer-experience"],
body[data-uc-fam="u8-customer-experience"] {
  --uc-surface:
    radial-gradient(120% 95% at 22% 12%, rgba(255, 206, 180, 0.45) 0%, rgba(255, 206, 180, 0) 55%),
    radial-gradient(135% 125% at 50% 40%, #4fae82 0%, #2f9163 40%, #226b4d 72%, #17503a 100%);
  --uc-edge: rgba(34, 107, 77, 0.4);
}

/* Near-black now, not navy. The fluting is drawn at #050506/#070708 and
   needs a surface darker than the ridges to sit on. */
#useCasesView [data-uc-fam="u9-govern-comply"],
body[data-uc-fam="u9-govern-comply"] {
  --uc-surface: #070708;
  --uc-edge: rgba(150, 150, 180, 0.28);
}

/* The two consumers. A card paints its own box; the detail page paints a
   fixed layer behind everything (see #uc-page-art below). */
#useCasesView [data-uc-card][data-uc-fam],
#activitiesView [data-uc-card][data-uc-fam] {
  background: var(--uc-surface);
  border-color: var(--uc-edge);
}

/* ---------- the contrast scrim ----------
   MEASURED, not guessed. The generative art puts near-white pixels
   wherever a bright tile cluster, orbit ring, bloom core or aurora blob
   lands, and the card's text sits directly on it. Sampling the composited
   pixel under every text run and computing WCAG against it, 33 of 45
   (family, text-part) pairs failed AA 4.5:1 at their worst pixel, and it
   was not only the small print: the solid-white title failed at 1.60:1 on
   plan & decide, where a white orbit ring passes behind it.

   Raising the dimmed inks below fixes all three light families outright.
   The dark ones cannot be fixed that way, because their binding constraint
   is white text that is already opaque: the only remaining variable is the
   background. Hence a scrim between the art and the text.

   The alpha is PER FAMILY because the requirement genuinely varies with
   how bright each motif gets: research & analyse needs 0.20, plan & decide
   needs 0.56. One pooled worst case would flatten the faint motifs to pay
   for the bright ones. Same reasoning, and same shape, as --uc-art-blur.

   z-index -1 puts it above the art and below the text: the art layer is
   also -1, and a pseudo-element is generated after every child, so at
   equal z-index tree order paints it on top. In-flow text paints above
   both. ::before is taken by .module-card's hover gradient. */
#useCasesView [data-uc-card][data-uc-fam]::after,
#activitiesView [data-uc-card][data-uc-fam]::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: rgb(var(--uc-scrim-rgb, 5 20 30) / var(--uc-scrim, 0));
}
#useCasesView [data-uc-fam="u1-communicate"] { --uc-scrim: 0.46; }
#useCasesView [data-uc-fam="u2-research-analyse"] { --uc-scrim: 0.22; }
#useCasesView [data-uc-fam="u3-plan-decide"] { --uc-scrim: 0.56; }
#useCasesView [data-uc-fam="u6-sell-negotiate"] { --uc-scrim: 0.4; }
#useCasesView [data-uc-fam="u8-customer-experience"] { --uc-scrim: 0.42; }
#useCasesView [data-uc-fam="u9-govern-comply"] { --uc-scrim: 0.12; }

/* ---------- dark-surface text ----------
   The base card's inks (rgba white at .75 / .6) were set for a flat navy
   card and are too thin over art. Raised here, and scoped to
   [data-uc-fam] so the course and module cards elsewhere on the site keep
   the values they were designed with.

   The meta row also gets the low-opacity backing it was missing. The
   scrim is what carries the AA guarantee, so this is legibility rather
   than compliance: it gives the utility and effort figures a substrate of
   their own, and reads the pair as one unit rather than four loose words
   floating over a swarm. */
#useCasesView [data-uc-fam] .module-subtitle { color: rgba(255, 255, 255, 0.92); }
#useCasesView [data-uc-fam] .module-meta,
#useCasesView [data-uc-fam] .module-meta-item { color: rgba(255, 255, 255, 0.88); }
#useCasesView [data-uc-fam] .uc-card-rungs-lbl { color: rgba(255, 255, 255, 0.85); }
/* The chips DARKEN on a dark card. This looks like a detail and is not:
   a translucent white backing behind white text raises the substrate
   toward the ink and eats the contrast it was added to buy. It is what
   left plan & decide's platform row at 4.43:1 when everything else on the
   card had cleared 4.5 — the scrim underneath was doing the work and the
   chip was undoing part of it. Light families keep a white chip, where
   lightening is the right direction under dark ink. */
#useCasesView [data-uc-fam] .uc-plat {
  color: rgba(255, 255, 255, 0.9);
  border-color: rgba(255, 255, 255, 0.22);
  background: rgba(3, 18, 28, 0.38);
}
#useCasesView [data-uc-fam] .module-meta { gap: 8px; }
#useCasesView [data-uc-fam] .module-meta-item {
  padding: 0.14rem 0.45rem;
  border-radius: var(--radius-sm);
  background: rgba(3, 18, 28, 0.38);
}
#useCasesView [data-uc-fam] .module-meta-icon { opacity: 0.75; }

/* ---------- the rung badges ----------
   These carry the --type-* tokens from the top of this file, and those are
   documented there as "accessible on light surfaces" — which they are, and
   which is the whole problem: nothing had ever put them on a dark one. On
   the six dark families the skill badge measured 1.00:1 and the agent
   badge 1.24:1, i.e. the word was invisible, on every card. The first pass
   of this audit missed it too, because the badges were not in the probe;
   it was caught by looking at a rendered card.

   So the dark families invert: a dark chip, like every other chip on these
   cards, with the BRIGHT end of each accent as ink rather than the dark
   end picked for white paper. */
#useCasesView [data-uc-fam] .uc-card-rungs .uc-badge {
  background: rgba(3, 18, 28, 0.55);
}
#useCasesView [data-uc-fam] .uc-badge--skill { color: #4FE3B4; }
#useCasesView [data-uc-fam] .uc-badge--agent { color: #B9B9FF; }
#useCasesView [data-uc-fam] .uc-badge--technique { color: #7FDDFF; }
#useCasesView [data-uc-fam] .uc-badge--loop { color: #EDB4F5; }
#useCasesView [data-uc-fam] .uc-badge--use_case { color: rgba(255, 255, 255, 0.92); }

/* ---------- light-surface text (u4, u5, u7) ----------
   Everything the dark base card sets in white-alpha has to be restated
   in ink here, including the two rows that were only ever styled for a
   dark card (.uc-plat, .uc-card-rungs-lbl). Selector-grouped rather
   than driven off a custom property because .uc-plat's border and
   background need different treatment on light, not just a hue swap. */
#useCasesView [data-uc-fam="u4-produce-content"] .module-title,
#useCasesView [data-uc-fam="u5-operate-document"] .module-title,
#useCasesView [data-uc-fam="u7-build-develop"] .module-title { color: #1B2F3C; }

#useCasesView [data-uc-fam="u4-produce-content"] .module-subtitle,
#useCasesView [data-uc-fam="u5-operate-document"] .module-subtitle,
#useCasesView [data-uc-fam="u7-build-develop"] .module-subtitle,
#useCasesView [data-uc-fam="u4-produce-content"] .module-meta,
#useCasesView [data-uc-fam="u5-operate-document"] .module-meta,
#useCasesView [data-uc-fam="u7-build-develop"] .module-meta,
#useCasesView [data-uc-fam="u4-produce-content"] .module-meta-item,
#useCasesView [data-uc-fam="u5-operate-document"] .module-meta-item,
#useCasesView [data-uc-fam="u7-build-develop"] .module-meta-item,
#useCasesView [data-uc-fam="u4-produce-content"] .uc-card-rungs-lbl,
#useCasesView [data-uc-fam="u5-operate-document"] .uc-card-rungs-lbl,
#useCasesView [data-uc-fam="u7-build-develop"] .uc-card-rungs-lbl { color: #3A3A39; }

/* #575756 was the brand's secondary ink and it failed AA over all three
   of these motifs: 3.35:1 under the mist, 4.22:1 under the cyan
   scribbles. Darkening it to #3A3A39 clears 4.5:1 on every pixel of all
   three families with no scrim at all, which is why none of them carries
   one. The measured margin is in tests/uc-contrast.test.mjs. */
#useCasesView [data-uc-fam="u4-produce-content"] .module-meta-item,
#useCasesView [data-uc-fam="u5-operate-document"] .module-meta-item,
#useCasesView [data-uc-fam="u7-build-develop"] .module-meta-item {
  background: rgba(255, 255, 255, 0.55);
}
#useCasesView [data-uc-fam="u4-produce-content"] .module-meta-icon,
#useCasesView [data-uc-fam="u5-operate-document"] .module-meta-icon,
#useCasesView [data-uc-fam="u7-build-develop"] .module-meta-icon { opacity: 0.8; }

#useCasesView [data-uc-fam="u4-produce-content"] .uc-plat,
#useCasesView [data-uc-fam="u5-operate-document"] .uc-plat,
#useCasesView [data-uc-fam="u7-build-develop"] .uc-plat {
  color: #1B2F3C;
  border-color: rgba(0, 0, 0, 0.14);
  background: rgba(255, 255, 255, 0.42);
}

/* The rung badges carry their own accent-on-tint colours from the
   --type-* tokens at the top of this file. Those accents were picked to
   be accessible on light surfaces, so they need no override; only their
   translucent backgrounds do, since a `rgba(x, 0.1)` tint reads as mud
   over blush or grey. */
/* 0.62 let enough of the motif through that the badges still failed here
   too, though less dramatically than on the dark cards: 4.09:1 for skill
   under the mist, 3.47:1 for agent. Raised to 0.9, which is opaque enough
   that the accent sits on near-white rather than on whatever the art is
   doing underneath. These rules come AFTER the dark-family block above and
   match at the same specificity, so they win on source order. */
#useCasesView [data-uc-fam="u4-produce-content"] .uc-card-rungs .uc-badge,
#useCasesView [data-uc-fam="u5-operate-document"] .uc-card-rungs .uc-badge,
#useCasesView [data-uc-fam="u7-build-develop"] .uc-card-rungs .uc-badge {
  background: rgba(255, 255, 255, 0.9);
}
/* And the accents go back to the dark end on these three, since the block
   above set the bright end for every [data-uc-fam] card. #6161FF measures
   4.5:1 on pure white — exactly on the line, so it fails the moment any
   art shows through — hence the darker #4141C4 here. */
#useCasesView [data-uc-fam="u4-produce-content"] .uc-badge--skill,
#useCasesView [data-uc-fam="u5-operate-document"] .uc-badge--skill,
#useCasesView [data-uc-fam="u7-build-develop"] .uc-badge--skill { color: var(--type-skill); }
#useCasesView [data-uc-fam="u4-produce-content"] .uc-badge--agent,
#useCasesView [data-uc-fam="u5-operate-document"] .uc-badge--agent,
#useCasesView [data-uc-fam="u7-build-develop"] .uc-badge--agent { color: #4141C4; }
#useCasesView [data-uc-fam="u4-produce-content"] .uc-badge--technique,
#useCasesView [data-uc-fam="u5-operate-document"] .uc-badge--technique,
#useCasesView [data-uc-fam="u7-build-develop"] .uc-badge--technique { color: var(--type-technique); }
#useCasesView [data-uc-fam="u4-produce-content"] .uc-badge--loop,
#useCasesView [data-uc-fam="u5-operate-document"] .uc-badge--loop,
#useCasesView [data-uc-fam="u7-build-develop"] .uc-badge--loop { color: var(--type-loop); }
#useCasesView [data-uc-fam="u4-produce-content"] .uc-badge--use_case,
#useCasesView [data-uc-fam="u5-operate-document"] .uc-badge--use_case,
#useCasesView [data-uc-fam="u7-build-develop"] .uc-badge--use_case { color: var(--type-use_case); }

/* ====================================================================
   Detail page surface (use-case.html)
   --------------------------------------------------------------------
   A use-case detail page takes the surface of the family it belongs to,
   so clicking a green card lands you on a green page. js/use-cases.js
   sets data-uc-fam / data-uc-v on <body> and mounts #uc-page-art.

   Why a fixed layer rather than a background on <body>: the surface is a
   percentage-based radial gradient, and on <body> it would size to the
   whole scroll height, so a long page would show a differently-framed
   gradient from a short one and neither would match the card. A fixed
   viewport-sized layer frames it the same way the card does, and holds
   still while the content scrolls over it.

   z-index -1 keeps it under everything. The header and footer are their
   own opaque dark surfaces and the content is in flow, so both paint
   above a negative layer without needing a z-index of their own.
   ==================================================================== */
/* Blur applies to the DETAIL PAGE only. Cards are left sharp: that is
   what was asked for, and it is also the cheaper answer, since blurring
   49 card layers buys no legibility. The card art rule above therefore
   carries no `filter` at all.

   Heavier than a card's would have been. The layer is viewport-sized, so the same visual
   softness needs a bigger radius, and the overscale margin scales with it
   (8% of a 1440px viewport is 115px against a 14px radius). This is also
   the surface most likely to compete with the text, since the content
   column sits directly on it rather than on an opaque card. */
body[data-uc-fam] { --uc-art-blur: 14px; }
/* AFTER the generic rule, and that is not cosmetic: `body[data-uc-fam]`
   and `body[data-uc-fam="u3-plan-decide"]` have identical specificity
   (0-1-1 either way — an attribute selector counts the same with or
   without a value), so source order is the only thing that decides which
   wins. Placed above, this override is dead code that looks correct. */
/* Two motifs are outline drawings rather than fields of shapes: u3's six
   orbit rings and u9's six hex shields, at 0.8 to 1.5 stroke units and
   around 30% opacity, which on this layer renders near 1.5px. Blur
   spreads a line's ink over about twice its radius, so at 14px those two
   do not soften, they vanish, and their subjects lose the identity the
   other seven keep. Thickening the strokes would change the cards, which
   are signed off, so the radius gives way instead. */
body[data-uc-fam="u3-plan-decide"],
body[data-uc-fam="u9-govern-comply"] { --uc-art-blur: 5px; }

#uc-page-art {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: var(--uc-surface);
}
/* ---------- the detail page's contrast scrim ----------
   Same mechanism as the card's, and NOT the same numbers, which is the
   point of giving it its own property. The page art is blurred (14px, 5px
   on the outline motifs) and framed to the viewport rather than to a
   300px box, so the distribution of bright pixels behind the text is
   different: measured against the real page, communicate needs 0.28 where
   its card needed 0.46, and customer experience needs 0.50 where its card
   needed 0.42. Reusing --uc-scrim would have been wrong in both
   directions at once.

   This layer was missed entirely on the first pass, because the pixel
   audit only ever loaded cards. It cost 13 more failures across four
   families, including a 36px bold hero at 2.50:1.

   Painted as ::after on #uc-page-art so it sits above the art svg (a
   child, so earlier in tree order) and below everything in the document,
   which is what #uc-page-art's own z-index: -1 already guarantees. */
#uc-page-art::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: rgb(var(--uc-scrim-rgb, 5 20 30) / var(--uc-page-scrim, 0));
}
body[data-uc-fam="u1-communicate"] { --uc-page-scrim: 0.3; }
body[data-uc-fam="u3-plan-decide"] { --uc-page-scrim: 0.36; }
body[data-uc-fam="u6-sell-negotiate"] { --uc-page-scrim: 0.44; }
body[data-uc-fam="u8-customer-experience"] { --uc-page-scrim: 0.52; }

#uc-page-art .uc-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform-origin: center;
  filter: blur(var(--uc-art-blur, 0));
  /* STATIC, deliberately, and this is the whole rule for this layer.
     Motion belongs to the cards; the detail page background holds still.

     It used to drift and breathe at 40s/9s, on the reasoning that a
     viewport-sized layer needs a slower tempo than a card. The tempo was
     never the problem. A card is a 300px object you look AT, so movement
     inside it reads as the object being alive. This layer is the page
     itself, behind the text you are trying to read, at nine times the
     area — so the same gesture reads as the page sliding under you, and
     it competes with the one thing on screen that should be moving.

     The overscale stays. It is not a leftover of the animation: the art
     is `preserveAspectRatio="xMidYMid slice"` under a blur, so the layer
     has to sit wider than the viewport or the blurred edge of the
     artwork shows along the sides. `each blurred layer has the margin
     its radius needs` in tests/uc-tiles.test.mjs is what keeps the two
     numbers in step. */
  transform: scale(1.16);
}
/* And nothing INSIDE it moves either. Stopping the layer alone still
   leaves the tiled motifs running their own animations — the swarm
   pulsing, the mist drifting, the orbits turning, the ripples firing —
   which is most of the movement on the page and all of it behind body
   copy. The ID makes this outrank the `.uc-art .uc-art-*` motif rules
   without !important, and the universal selector means a motif added
   later is static here by default rather than by remembering to add it. */
#uc-page-art .uc-art * { animation: none; }
/* Two motifs are defined by their animation rather than decorated with
   it, so stopping them needs a resting state or they vanish. Same values
   the reduced-motion block uses, for the same reason. */
#uc-page-art .uc-art .uc-art-ripple {
  r: 46px;
  opacity: 0.12;
  stroke-width: 0.3;
}
#uc-page-art .uc-art .uc-art-ripple--in { r: 28px; }
#uc-page-art .uc-art .uc-art-ripple--core { r: 2.4px; opacity: 0.5; }
/* The runner only exists as a moving dot; parked it is a node the
   drawing never had. */
#uc-page-art .uc-art .uc-art-runner { display: none; }

/* The hero stops being a white panel and becomes part of the page, which
   is the whole point of the request: the card's background IS the page's
   background now, so a panel boxed on top of it would fight it. The
   .dsection panels below stay white and opaque, so all the body copy
   keeps its original contrast and none of it is restyled here. */
body[data-uc-fam] #useCasesView .dhero {
  background: none;
  border-color: transparent;
  box-shadow: none;
  padding-left: 0;
  padding-right: 0;
}
/* Only the four things that now sit on the surface rather than on white.
   Everything else in the hero is an opaque chip (.back, .plat) or the
   accent-gradient CTA, and reads on any of the nine surfaces unchanged. */
body[data-uc-fam] #useCasesView .dhero h1 { color: #fff; }
body[data-uc-fam] #useCasesView .dhero .outcome,
body[data-uc-fam] #useCasesView .uc-type-caption,
body[data-uc-fam] #useCasesView .uc-platform-pref label { color: rgba(255, 255, 255, 0.78); }

/* The spec plate is a dark gradient panel. On a dark page it needs an
   edge or it dissolves into the surface it is supposed to sit on. */
body[data-uc-fam] #useCasesView .bigplate {
  border: 1px solid rgba(255, 255, 255, 0.16);
}

/* The THREE light families again (see the card block above). Same reason,
   different surface: white hero text on #EFACA8 is about 1.7:1.

   u7 was missing from this block, and had been since it became a light
   family. Its detail page took the generic `body[data-uc-fam]` rule above
   and rendered a white hero on #D0D0D0 grey: 1.60:1, a heading you cannot
   read. The card block got its override and the detail block did not,
   because the test that guards this asserted the LIST of light families
   rather than deriving it, so a third one joining could not fail it. Same
   antipattern as the card-variant check, same fix.

   Ink is #3A3A39 rather than the brand's #575756 for the same reason the
   cards use it, plus one specific to here: #575756 on u7's #D0D0D0 is
   4.45:1 on the flat surface alone, before any art. */
body[data-uc-fam="u4-produce-content"] #useCasesView .dhero h1,
body[data-uc-fam="u5-operate-document"] #useCasesView .dhero h1,
body[data-uc-fam="u7-build-develop"] #useCasesView .dhero h1 { color: #1B2F3C; }
body[data-uc-fam="u4-produce-content"] #useCasesView .dhero .outcome,
body[data-uc-fam="u5-operate-document"] #useCasesView .dhero .outcome,
body[data-uc-fam="u7-build-develop"] #useCasesView .dhero .outcome,
body[data-uc-fam="u4-produce-content"] #useCasesView .uc-type-caption,
body[data-uc-fam="u5-operate-document"] #useCasesView .uc-type-caption,
body[data-uc-fam="u7-build-develop"] #useCasesView .uc-type-caption,
body[data-uc-fam="u4-produce-content"] #useCasesView .uc-platform-pref label,
body[data-uc-fam="u5-operate-document"] #useCasesView .uc-platform-pref label,
body[data-uc-fam="u7-build-develop"] #useCasesView .uc-platform-pref label { color: #3A3A39; }
body[data-uc-fam="u4-produce-content"] #useCasesView .bigplate,
body[data-uc-fam="u5-operate-document"] #useCasesView .bigplate,
body[data-uc-fam="u7-build-develop"] #useCasesView .bigplate {
  border-color: rgba(0, 0, 0, 0.14);
}
