/*
  Catalog-specific styles, layered on top of /css/etaia.css (loaded first by
  the shared layout) -- same convention as bok/webapp/public/css/bok.css.
*/

/* Header logo wrapped in a link to / (see partials/header.handlebars) --
   keeps the <img> laid out exactly as a direct .site-header-left flex item. */
.logo-link {
  display: flex;
  flex-shrink: 0;
}

:root {
  /* Comfortably covers .site-footer's tallest realistic state (its
     footnote links wrapping onto a 2nd line on a narrow viewport), now that
     it's pinned to the bottom of the viewport instead of sitting in normal
     document flow -- reserved as bottom padding on .page-content and
     subtracted from every 100vh-capped sidebar panel below so the fixed
     footer never overlaps their content. */
  --site-footer-height: 4.5rem;
}

/* Overrides etaia.css's own .content { padding: 3rem 0; } -- this app lays
   out its own top/bottom spacing per page (catalog-page's toolbar, asset-page's
   breadcrumb, etc.) rather than relying on a single fixed padding shared
   across every page in the template. */
.content {
  padding: 0;
}

/* Always visible without scrolling, on every page -- overriding the shared
   layout's default sticky-footer behavior (in normal flow, only reachable
   by scrolling past the page's own content). z-index kept below
   .catalog-tooltip's (2000) so a radar tooltip near the bottom of the
   screen still shows above it. */
.site-footer {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 500;
  margin-top: 0;
}

.page-content {
  padding-bottom: var(--site-footer-height);
}

.catalog-eyebrow {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--title-color);
  margin: 0 0 0.3rem;
}

/* Plain <h2> -- color/font-weight ("Secondary title" in @etaia/web-app's own
   style-guide page) already come from etaia.css's shared h1/h2/h3 + h2
   rules; only the size/spacing for this particular spot needs setting. */
.catalog-toolbar-title {
  font-size: 1.1rem;
  margin: 0 0 0.6rem;
}

.content h2 {
  margin-top: 15px;
}

ul.plain {
  margin: 0;
  padding-left: 1.2rem;
}

ul.plain li {
  margin-bottom: 0.5rem;
}

.badge {
  display: inline-flex;
  align-items: center;
  font-size: 0.72rem;
  font-weight: 600;
  background: var(--global-color-3);
  color: var(--link-color-hover);
  padding: 2px 10px;
  border-radius: 20px;
  margin: 0 0.3rem 0.3rem 0;
  text-transform: none;
}

/* GitHub-README-style "shield" badge (see e.g. shields.io's own license/
   pyversions badges) -- a dark label segment + a colored value segment,
   used for the Technical details cartouche's License and Compatible Python
   entries (asset.handlebars) instead of this app's own pill-shaped .badge,
   which doesn't have a label/value split. */
.gh-badge {
  display: inline-flex;
  align-items: stretch;
  border-radius: 3px;
  overflow: hidden;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.8;
  vertical-align: middle;
}

.gh-badge-label,
.gh-badge-value {
  padding: 0 6px;
  color: #fff;
}

.gh-badge-label {
  background: #555;
}

.gh-badge-value {
  text-decoration: none;
}

.gh-badge-value.gh-badge-license { background: #007ec6; }
.gh-badge-value.gh-badge-python { background: #3776ab; }

.badge-status-graduated { background: #dcfce7; color: #166534; }
.badge-status-incubated { background: #fef9c3; color: #854d0e; }
/* Was var(--global-color-3)/var(--link-color-hover) -- identical to a plain
   untyped .badge, so a shortlisted status badge was indistinguishable from
   one. Same blue used elsewhere in this file for an "early/in-progress"
   state (e.g. asset-relevance-under-review). */
.badge-status-shortlisted { background: #dbeafe; color: #1d4ed8; }
.badge-status-retired { background: #e2e8f0; color: #475569; }

/* Strategic Relevance cartouche (asset detail page only) -- 4-state model,
   same badge-color convention as the health/status badges above. */
.asset-relevance-badge { font-weight: 700; }
.asset-relevance-relevant { background: #dcfce7; color: #166534; }
.asset-relevance-under-review { background: #dbeafe; color: #1d4ed8; }
.asset-relevance-contested { background: #fef3c7; color: #b45309; }
.asset-relevance-not-relevant { background: #fee2e2; color: #b91c1c; }

.asset-relevance-date {
  font-size: 0.78rem;
  color: var(--text-muted-color);
  margin-left: 0.3rem;
}

.asset-relevance-history summary {
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--link-color-hover);
  margin-top: 0.5rem;
}

.asset-relevance-history ul.plain {
  margin-top: 0.6rem;
}

/* State of the Art cartouche -- same 4-state pattern as Strategic Relevance
   above, mapped to its own labels (Current/Contested/Under review/Obsolete)
   but the same color semantics (good=green, neutral=blue, warning=amber,
   negative=red). */
.asset-soa-badge { font-weight: 700; }
.asset-soa-current { background: #dcfce7; color: #166534; }
.asset-soa-under-review { background: #dbeafe; color: #1d4ed8; }
.asset-soa-contested { background: #fef3c7; color: #b45309; }
.asset-soa-obsolete { background: #fee2e2; color: #b91c1c; }

/* Export Control cartouche -- 3-state model per Portfolio Management
   Process.md's declared export-control status (renamed from ITAR-free to
   avoid the ITAR-specific term, see README). */
.asset-export-badge { font-weight: 700; }
.asset-export-export-control-clear { background: #dcfce7; color: #166534; }
.asset-export-subject-to-export-control { background: #fef3c7; color: #b45309; }
.asset-export-unknown { background: #fee2e2; color: #b91c1c; }

/* Project Health cartouche -- 5-state model, a manually tracked, historized
   portfolio-manager assessment (real ontology data, see hasProjectHealth in
   repository.js) -- named "wellness" to avoid colliding with the generic
   .asset-health-* naming an earlier, now-removed auto-computed header badge
   used (see git history / computeHealthLabel). */
.asset-wellness-badge { font-weight: 700; }
.asset-wellness-healthy { background: #dcfce7; color: #166534; }
.asset-wellness-under-review { background: #dbeafe; color: #1d4ed8; }
.asset-wellness-aging { background: #fef3c7; color: #b45309; }
.asset-wellness-contested { background: #ffedd5; color: #c2410c; }
.asset-wellness-unhealthy { background: #fee2e2; color: #b91c1c; }

/* Two-column asset page body: portfolio-property cartouches on the left,
   everything else on the right (see asset.handlebars). Falls back to a
   single column (no reserved left gutter) when the asset has neither
   cartouche, so the right column isn't left with a dangling empty aside. */
.asset-body {
  display: grid;
  gap: 1.5rem;
}

.asset-body--with-cartouches {
  grid-template-columns: 340px 1fr;
  align-items: start;
}

/* Organisations + Data sources, mirroring the left cartouches column --
   .asset-body--with-cartouches.asset-body--with-right-cartouches (2 classes)
   beats either alone (1 class) on specificity, so having both cartouche
   columns at once doesn't depend on rule order below. */
.asset-body--with-right-cartouches {
  grid-template-columns: 1fr 340px;
  align-items: start;
}

.asset-body--with-cartouches.asset-body--with-right-cartouches {
  grid-template-columns: 340px 1fr 340px;
}

/* Grid items default to min-width: auto, so a long URL, a rich-text image
   or the BOK diagram would widen their column past the viewport on mobile
   (pushing the bordered tables off-screen) -- let every column shrink. */
.asset-body > * {
  min-width: 0;
}

@media (max-width: 900px) {
  .asset-body--with-cartouches,
  .asset-body--with-right-cartouches,
  .asset-body--with-cartouches.asset-body--with-right-cartouches {
    grid-template-columns: minmax(0, 1fr);
  }
}

.asset-cartouches {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  position: sticky;
  top: 1rem;
  padding-top: 10px;
}

.cartouche {
  border: 1px solid var(--border-color-muted);
  border-radius: 10px;
  padding: 1rem;
}

.cartouche-status-summary {
  background: var(--form-background);
}

.cartouche h3 {
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted-color);
  margin: 0 0 0.6rem;
}

/* Organisations/Data sources cartouches (asset.handlebars) use plain <p>s
   for their content, unlike the portfolio-property cartouches' own
   .cartouche-comment -- same size/line-height so both read consistently. */
.cartouche p {
  font-size: 0.85rem;
  line-height: 1.5;
  margin: 0 0 0.5rem;
}

.cartouche p:last-child {
  margin-bottom: 0;
}

.cartouche-comment {
  font-size: 0.85rem;
  line-height: 1.5;
  margin-top: 0.6rem;
}

.cartouche-date {
  font-size: 0.78rem;
  color: var(--text-muted-color);
  margin-left: 0.3rem;
}

.cartouche-history summary {
  cursor: pointer;
  font-size: 0.82rem;
  color: var(--link-color-hover);
  margin-top: 0.5rem;
}

.cartouche-history ul.plain {
  margin-top: 0.6rem;
  font-size: 0.82rem;
}

/* Methodology block -- the BOK W-cycle diagram, inlined as a plain <svg>
   fragment (partials/bokWCycleDiagram.handlebars, generated from
   docs/ETAIA-W_prod.svg). The SVG carries its own colors as presentation
   attributes; it is only sized here, from its viewBox. */

/* Highlights the diagram box(es) for the top-level BOK activity/activities
   this asset is associated with (see asset-bok-diagram.js) -- e.g. an asset
   tagged with BOK_ID_6_1_2 gets its BOK_ID_6 box highlighted here. A CSS
   fill overrides the shapes' own fill="" presentation attributes; their
   stroke (the engineering-level color) is left alone. */
.cartouche-bok-diagram-frame [data-bok-activity-id].bok-diagram-activity--highlighted {
  fill: var(--etaia-02);
  fill-opacity: 0.3;
  filter: drop-shadow(0 0 6px var(--etaia-02));
  cursor: help;
}

/* Temporary, stronger highlight while a "When to use it" role-usage
   sentence pointing at this box is hovered/focused (asset-bok-diagram.js). */
.cartouche-bok-diagram-frame [data-bok-activity-id].bok-diagram-activity--focused {
  fill: var(--etaia-01);
  fill-opacity: 0.55;
  filter: drop-shadow(0 0 10px var(--etaia-01));
  transition: fill-opacity 0.15s ease;
}

.cartouche-bok-diagram-frame {
  margin-top: 0.6rem;
}

.cartouche-bok-diagram-frame > svg {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 642.3 / 430.308;
}

/* Associated BOK activities, right under the W-cycle diagram: one line
   per activity -- "“<activity>” ↗", plus "from “<top-level activity>” ↗"
   for a sub-activity -- each linking to that activity's page in the BOK web
   app (its /tree/<id> route). Hovering a line highlights its top-level box
   in the diagram (data-bok-root-id, asset-bok-diagram.js), same as the
   "When to use it" role-usage sentences. */
.cartouche-bok-activities {
  margin-top: 0.6rem;
}

.cartouche-bok-activities-label {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--link-color);
  margin: 0 0 0.4rem;
}

.cartouche-bok-activities ul.plain li {
  font-size: 0.82rem;
  color: var(--text-muted-color);
  margin: 0 0 0.25rem -0.3rem;
  padding: 0.1rem 0.3rem;
  border-radius: 4px;
  cursor: default;
  transition: background-color 0.15s ease;
}

.cartouche-bok-activities li.is-bok-focused {
  background: var(--paper-sunk);
}

.cartouche-bok-activities a i {
  font-size: 0.65rem;
}

/* Data sources widget (bottom of the asset page's right column) -- each row
   tags its link with the hosting platform badge server.js derived from the
   real URL (see buildDataSources in src/server.js). */
.asset-data-sources ul.plain li {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
}

.asset-source-badge { font-weight: 700; }
.asset-source-badge i { margin-right: 0.2rem; }
.asset-source-github { background: #24292e; color: #fff; }
.asset-source-gitlab { background: #fc6d26; color: #fff; }
.asset-source-bitbucket { background: #0052cc; color: #fff; }

/* ---------------- catalogue: search + filters + results ---------------- */
/* Fits the whole catalogue (toolbar + filters + radar/list) in one screen,
   with .catalog-layout's own children scrolling internally instead of the
   page itself -- .site-header's height (63px, see etaia.css) and
   --site-footer-height are the only two *real* numbers this needs (not
   guesses): everything else (.content's 3rem top/bottom padding included,
   since `*{box-sizing:border-box}` is set globally) falls out of this one
   height via the flex/grid chain below, rather than each panel separately
   guessing how much chrome sits above it. */
.catalog-page {
  height: calc(100vh - 63px - var(--site-footer-height));
  overflow: hidden;
}

.catalog-page .container {
  width: calc(100% - 2rem);
  height: 100%;
  display: flex;
  flex-direction: column;
}

.catalog-toolbar, .catalog-active-filters, .catalog-auth-hint {
  flex-shrink: 0;
}

.catalog-layout {
  display: grid;
  /* +20% from the previous 220px, per request. */
  grid-template-columns: 264px 1fr;
  gap: 1.5rem;
  align-items: stretch;
  flex: 1 1 auto;
  min-height: 0;
}

@media (max-width: 980px) {
  /* Below the radar-body stacking breakpoint (see .catalog-radar-body's own
     media query further down), fitting everything into one screen would
     squeeze both the filters and the radar/list content into shared,
     already-tight vertical space -- revert to the shared layout's normal
     scroll-the-whole-page behavior instead, same as every other page. */
  .catalog-page {
    height: auto;
    overflow: visible;
  }

  .catalog-page .container {
    height: auto;
    display: block;
  }

  .catalog-layout {
    flex: none;
  }
}

@media (max-width: 780px) {
  .catalog-layout {
    grid-template-columns: 1fr;
  }
}

.catalog-filters {
  border: 1px solid var(--border-color-muted);
  border-radius: 10px;
  padding: 1rem;
  background: var(--form-background);
  /* .catalog-layout's align-items:stretch already sizes this to the row's
     real height (no more guessing a separate viewport-relative max-height
     here) -- position:sticky is moot now that .catalog-page itself doesn't
     scroll, overflow-y:auto is what actually handles a long filter list. */
  overflow-y: auto;
}

@media (max-width: 980px) {
  .catalog-filters {
    max-height: none;
    overflow-y: visible;
  }
}

.catalog-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-bottom: 0.8rem;
}

.catalog-search {
  flex: 1 1 320px;
}

.catalog-search input {
  width: 100%;
  padding: 0.55rem 0.7rem;
  border: 1.5px solid var(--border-color-muted);
  border-radius: 8px;
  font-family: inherit;
  font-size: 0.85rem;
}

.catalog-search input:focus {
  outline: none;
  border-color: var(--border-color-purple);
}

/* Toolbar groups: [display: Radar|Pies|List] | [Highlighted, Clear] ...
   [Propose] pushed right. Every control shares one height/radius/font so
   the row reads as a single bar rather than 5 unrelated widgets. */
.catalog-toolbar-group {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex: 0 0 auto;
}

.catalog-toolbar-group + .catalog-toolbar-group {
  padding-left: 0.8rem;
  border-left: 1px solid var(--border-color-muted);
}

.catalog-toolbar .btn,
.catalog-highlight-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  height: 2.1rem;
  padding: 0 0.8rem;
  font-size: 0.8rem;
  font-weight: 600;
  border-radius: 8px;
  white-space: nowrap;
}

/* Segmented control -- joined buttons, the active one filled. */
.catalog-view-switch {
  gap: 0;
}

.catalog-view-switch .btn {
  border-radius: 0;
}

.catalog-view-switch .btn + .btn {
  margin-left: -1px;
}

.catalog-view-switch .btn:first-child {
  border-radius: 8px 0 0 8px;
}

.catalog-view-switch .btn:last-child {
  border-radius: 0 8px 8px 0;
}

.catalog-view-switch .btn[aria-pressed="true"] {
  position: relative;
  background: var(--etaia-02);
  color: #fff;
  border-color: var(--etaia-02);
}

/* Neutral outline while off, amber once on -- the checkbox itself is
   visually hidden but still focusable/clickable through its label. */
.catalog-highlight-toggle {
  position: relative;
  color: var(--text-muted-color);
  background: var(--page-background);
  border: 1.5px solid var(--border-color-muted);
  cursor: pointer;
  user-select: none;
}

.catalog-highlight-toggle input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.catalog-highlight-toggle:hover {
  border-color: #fde68a;
  color: #b45309;
}

.catalog-highlight-toggle:has(input:checked) {
  color: #b45309;
  background: #fef3c7;
  border-color: #f59e0b;
}

.catalog-highlight-toggle:has(input:focus-visible) {
  outline: 2px solid var(--etaia-02);
  outline-offset: 2px;
}

.catalog-clear-all:disabled {
  opacity: 0.45;
  cursor: default;
}

.catalog-propose {
  margin-left: auto;
}

/* Narrow screens: icon-only display switch, labels kept for screen readers
   via each button's title. */
@media (max-width: 640px) {
  .catalog-view-switch .btn span {
    display: none;
  }

  .catalog-propose {
    margin-left: 0;
  }
}

.filter-group {
  border: none;
  border-top: 1px solid var(--border-color-muted);
  padding: 0.7rem 0 0.2rem;
  margin: 0 0 0.2rem;
}

.filter-group legend {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--link-color);
  padding: 0;
  margin-bottom: 0.4rem;
}

.filter-option {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.78rem;
  padding: 0.15rem 0;
  cursor: pointer;
}

/* Asset count per filter option (see catalog-navigator.js's
   renderFilterCounts), pushed to the right edge of the row. */
.filter-count {
  margin-left: auto;
  flex: 0 0 auto;
  min-width: 1.6em;
  padding: 0 6px;
  border-radius: 20px;
  background: var(--global-color-3);
  color: var(--link-color-hover);
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1.6;
  text-align: center;
}

/* Option that would yield no asset given the other active filters. */
.filter-option-empty {
  opacity: 0.45;
}

.catalog-active-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.6rem;
  min-height: 1.6rem;
}

.catalog-auth-hint {
  font-size: 0.8rem;
  color: var(--text-muted-color);
  background: var(--form-background);
  border: 1px solid var(--border-color-muted);
  border-radius: 8px;
  padding: 0.6rem 0.9rem;
  margin-bottom: 1rem;
}

.catalog-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.75rem;
  font-weight: 600;
  background: var(--global-color-3);
  color: var(--link-color-hover);
  padding: 3px 6px 3px 10px;
  border-radius: 20px;
}

.catalog-chip button {
  border: none;
  background: none;
  color: inherit;
  cursor: pointer;
  font-size: 0.85rem;
  line-height: 1;
  padding: 0 4px;
}

.catalog-content-pane {
  min-width: 0;
  min-height: 0;
}

/* Radar is now the only view (see catalog.handlebars) -- fills
   .catalog-content-pane's full stretched height so .catalog-radar-body's own
   panels can compute their height against it, with the result-count line
   pinned above it rather than scrolling away too. */
.catalog-radar-view {
  height: 100%;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.catalog-result-count {
  font-size: 0.8rem;
  color: var(--text-muted-color);
  margin: 0 0 0.8rem;
  flex-shrink: 0;
}

@media (max-width: 980px) {
  .catalog-radar-view {
    height: auto;
    display: block;
  }
}

/* ---------------- radar view ---------------- */
/* Floats over the bottom-right corner of .catalog-radar-svg-wrap (its
   nearest positioned ancestor) instead of sitting above "Matching assets" in
   the chips panel -- its own background/border/shadow keep it legible over
   whatever quadrant wedge or bubble happens to render underneath it. */
.catalog-radar-legend {
  position: absolute;
  bottom: 1rem;
  right: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  background: var(--page-background);
  border: 1px solid var(--border-color-muted);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.catalog-radar-legend-block {
  font-size: 0.72rem;
  color: var(--text-muted-color);
  line-height: 1.6;
}

.catalog-radar-body {
  display: flex;
  gap: 1rem;
  /* Was flex-start: now that .catalog-radar-view gives this its real
     available height (see the cascade above .catalog-result-count), stretch
     is what actually hands that height down to the svg-wrap/chips-panel
     below instead of them each sizing to their own content. */
  align-items: stretch;
  flex: 1 1 auto;
  min-height: 0;
}

.catalog-radar-svg-wrap {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid var(--border-color-muted);
  border-radius: 10px;
  background: var(--page-background);
  padding: 1rem;
  /* height:100% (not max-height): the SVG's own height:100% (see
     .catalog-radar-svg) needs a definite box to resolve against, and
     .catalog-radar-body's stretch is what supplies that -- no more
     separately guessing a viewport-relative number here. */
  height: 100%;
  /* Positioning context for .catalog-radar-legend, floated in its
     bottom-right corner. */
  position: relative;
}

/* The "List" view (catalog-radar.js's renderCatalogRadar) toggles this element's plain
   `hidden` attribute -- without this, `display: flex` above (an author
   rule) would beat the browser's own `[hidden]{display:none}` regardless of
   specificity, the same bug already hit once for .catalog-radar-view/
   #catalogListView. #catalogRadarSvgWrap[hidden]'s specificity (1 id + 1
   attribute) beats the plain class rule above either way. */
#catalogRadarSvgWrap[hidden] {
  display: none;
}

/* Generates no box of its own -- its child (the <svg>, rebuilt on every
   render by catalog-radar.js) becomes a direct flex item of
   .catalog-radar-svg-wrap instead, keeping the centering/sizing above
   working unchanged. Existing purely so that container can be targeted for
   innerHTML resets without also wiping out .catalog-radar-legend, its
   sibling. */
.catalog-radar-svg-inner {
  display: contents;
}

/* Same author-rule-beats-[hidden] trap as #catalogRadarSvgWrap above --
   catalog-radar.js toggles `hidden` on these three when switching between
   the radar and pies views. */
.catalog-radar-svg-inner[hidden],
.catalog-radar-legend[hidden],
.catalog-pies-grid[hidden] {
  display: none;
}

/* ---------------- pies view (alternative to the radar) ---------------- */
/* 2x2 panels filling .catalog-radar-svg-wrap, one donut per dimension. */
.catalog-pies-grid {
  align-self: stretch;
  width: 100%;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}

.catalog-pie-panel {
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
  border: 1.5px solid var(--pie-accent, var(--border-color-muted));
  border-radius: 10px;
  background: var(--pie-tint, var(--page-background));
  padding: 0.7rem 0.8rem;
}

/* Same tint/accent pairs as the radar's .catalog-radar-quadrant-bg-* so a
   dimension keeps its color across both views. */
.catalog-pie-panel-trustworthy-attributes { --pie-tint: #f0fdf4; --pie-accent: #166534; }
.catalog-pie-panel-problem-typology { --pie-tint: #eff6ff; --pie-accent: #1d4ed8; }
.catalog-pie-panel-engineering-roles { --pie-tint: #fffbeb; --pie-accent: #b45309; }
.catalog-pie-panel-end-to-end-activities { --pie-tint: #faf5ff; --pie-accent: #7e22ce; }

.catalog-pie-title {
  margin: 0 0 0.5rem;
  font-size: 1rem;
  font-weight: 700;
  color: var(--pie-accent, var(--link-color));
}

.catalog-pie-empty {
  margin: auto;
  font-size: 0.8rem;
  color: var(--text-muted-color);
}

.catalog-pie-body {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.8rem;
  align-items: center;
}

.catalog-pie-svg {
  width: 100%;
  height: 100%;
  max-height: 100%;
  min-height: 0;
}

.catalog-pie-slice {
  stroke: var(--page-background);
  stroke-width: 1.5;
  cursor: pointer;
  transition: opacity 0.15s;
}

.catalog-pie-slice:hover {
  filter: brightness(0.9);
}

.catalog-pie-slice.is-selected {
  stroke: var(--text-color, #111);
  stroke-width: 2.5;
}

.catalog-pie-slice.is-dimmed,
.catalog-pie-legend-item.is-dimmed {
  opacity: 0.35;
}

.catalog-pie-slice-count {
  font-size: 11px;
  font-weight: 700;
  fill: #fff;
  pointer-events: none;
}

.catalog-pie-total {
  font-size: 26px;
  font-weight: 700;
  fill: var(--pie-accent, var(--link-color));
}

.catalog-pie-total-caption {
  font-size: 11px;
  fill: var(--text-muted-color);
}

.catalog-pie-legend {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 100%;
  overflow-y: auto;
  font-size: 0.75rem;
}

.catalog-pie-legend-item {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  padding: 0.15rem 0.3rem;
  border: 1px solid transparent;
  border-radius: 4px;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.catalog-pie-legend-item:hover {
  background: rgba(0, 0, 0, 0.05);
}

.catalog-pie-legend-item.is-selected {
  border-color: var(--pie-accent, var(--border-color-muted));
  font-weight: 700;
}

.catalog-pie-legend-swatch {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  background: var(--slice-color);
}

.catalog-pie-legend-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}

.catalog-pie-legend-count {
  flex: 0 0 auto;
  color: var(--text-muted-color);
  font-variant-numeric: tabular-nums;
}

/* Fixed categorical palette, cycled past 10 slices (PIE_PALETTE_SIZE in
   catalog-radar.js). --slice-color feeds the legend swatch; fill paints the
   SVG slice itself. */
.catalog-pie-slice-0 { --slice-color: #4e79a7; fill: #4e79a7; }
.catalog-pie-slice-1 { --slice-color: #f28e2b; fill: #f28e2b; }
.catalog-pie-slice-2 { --slice-color: #e15759; fill: #e15759; }
.catalog-pie-slice-3 { --slice-color: #76b7b2; fill: #76b7b2; }
.catalog-pie-slice-4 { --slice-color: #59a14f; fill: #59a14f; }
.catalog-pie-slice-5 { --slice-color: #edc948; fill: #edc948; }
.catalog-pie-slice-6 { --slice-color: #b07aa1; fill: #b07aa1; }
.catalog-pie-slice-7 { --slice-color: #ff9da7; fill: #ff9da7; }
.catalog-pie-slice-8 { --slice-color: #9c755f; fill: #9c755f; }
.catalog-pie-slice-9 { --slice-color: #8c8c8c; fill: #8c8c8c; }

@media (max-width: 980px) {
  .catalog-pies-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
  }

  .catalog-pie-svg {
    max-height: 220px;
  }
}

@media (max-width: 520px) {
  .catalog-pie-body {
    grid-template-columns: minmax(0, 1fr);
  }
}

.catalog-radar-chips-panel {
  flex: 0 0 700px;
  overflow-y: auto;
  border: 1px solid var(--border-color-muted);
  border-radius: 10px;
  padding: 0.8rem;
  background: var(--page-background);
}

/* The "List" view (catalog-radar.js's renderCatalogRadar) hides the diagram via the
   plain `hidden` attribute -- when it does, its sibling grows to fill the
   freed-up width instead of leaving it empty, since the chips panel is the
   actual results list now that there's no separate list view. :only-child
   covers the same "no diagram" outcome for an anonymous visitor, for whom
   #catalogRadarSvgWrap isn't rendered at all (see catalog.handlebars) rather
   than merely hidden -- there's no preceding [hidden] sibling to match in
   that case, just this panel alone. */
#catalogRadarSvgWrap[hidden] + .catalog-radar-chips-panel,
.catalog-radar-chips-panel:only-child {
  flex: 1 1 auto;
}

/* 2 fixed columns fit the panel's usual 700px width alongside the radar.
   Once the radar's hidden and the panel above grows to fill the freed-up
   width instead, auto-fill/minmax reflows to however many 340px-wide cards
   (same card-width budget .catalog-results used before it was removed)
   actually fit -- 6-7 on a typical desktop width, more on an ultrawide,
   fewer on a narrow one, rather than a number hardcoded for one specific
   width. */
#catalogRadarSvgWrap[hidden] + .catalog-radar-chips-panel .catalog-radar-chips,
.catalog-radar-chips-panel:only-child .catalog-radar-chips {
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
}

@media (max-width: 980px) {
  .catalog-radar-body {
    flex-direction: column;
    flex: none;
  }

  .catalog-radar-chips-panel {
    flex-basis: auto;
    width: 100%;
    max-height: 320px;
  }

  .catalog-radar-svg-wrap {
    height: auto;
  }
}

.catalog-radar-chips-title {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--link-color);
  margin: 0 0 0.6rem;
}

.catalog-radar-chips {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.4rem;
}

/* Swatch-card reuse (see renderChips in catalog-radar.js): border/radius/
   background/hover/focus all come from the shared .card/.card--swatch/
   .card--interactive classes already added alongside this one. Two things
   still need overriding for this compact, 2-per-row list: the color band
   (etaia.css's .card--swatch .swatch-color is 74px, sized for a full-width
   card) and the description line below. */
.catalog-radar-chip.card--swatch .swatch-color {
  height: 10px;
}

/* Positioning context for .catalog-radar-chip-primary-link's "stretched
   link" (see renderChips in catalog-radar.js -- the chip itself is a <div>,
   not an <a>, precisely so the repo/doc links below can be real, separately
   clickable <a>s without nesting one inside another). */
.catalog-radar-chip {
  position: relative;
}

.catalog-radar-chip-primary-link {
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* Visually hidden but still announced by a screen reader -- the icon-only
   .swatch-link cells below carry their label this way instead of as visible
   text, to stay compact in a 2-per-row list. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* 2-cell grid at the bottom of the card: repository + documentation, always
   both cells present so a missing one reads as a visible gap (see
   .swatch-link--disabled) rather than the grid silently losing a column. */
/* .card is already display:flex/flex-direction:column (etaia.css), and
   .catalog-radar-chips's grid stretches every card in a row to match its
   tallest sibling -- so .swatch-meta needs to actually grow into that extra
   height (flex:1 1 auto) instead of just sizing to its own content, for
   .swatch-links's margin-top:auto below to have real empty space to push
   into and land at the card's bottom edge instead of right after
   swatch-hex. */
.catalog-radar-chip .swatch-meta {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}

.swatch-links {
  display: grid;
  gap: 0.4rem;
  margin-top: auto;
  padding-top: 0.5rem;
  border-top: 1px solid var(--border-color-muted);
}

/* Software: repository + documentation. */
.swatch-links--2 {
  grid-template-columns: 1fr 1fr;
}

/* Documentation: just the delivered file. */
.swatch-links--1 {
  grid-template-columns: 1fr;
}

.swatch-link {
  /* Stacked above .catalog-radar-chip-primary-link (z-index:1) so this
     still gets its own click instead of the card's. */
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.35rem 0;
  border-radius: 6px;
  color: var(--link-color);
  text-decoration: none;
}

.swatch-link:hover {
  background: var(--border-color-muted);
}

.swatch-link--disabled {
  color: var(--text-muted-color);
  opacity: 0.45;
  cursor: default;
  pointer-events: none;
}

.catalog-radar-chip .swatch-hex {
  text-transform: none;
  font-variant-numeric: normal;
  line-height: 1.4;
  margin-top: 0.2rem;
  /* Clamp to 2 lines instead of letting a long shortDescription blow out
     every card's height in what's meant to be a compact companion list. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Status/license/maintainer line, between the name and the description. */
/* Name + status badge on one line (see renderChips): the name takes the
   remaining width and wraps as needed, the badge stays right-aligned at its
   own size on the first line. */
.swatch-title-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.4rem;
  /* The name <p>'s own default margins (1em at .swatch-name's 0.88rem),
     moved up to the row so the card's vertical spacing is unchanged. */
  margin: 0.88rem 0;
}

.swatch-title-row .swatch-name {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  overflow-wrap: anywhere;
}

.swatch-title-row .badge {
  flex: 0 0 auto;
  white-space: nowrap;
}

.swatch-info-line {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 0.2rem 0 0;
}

.swatch-info-text {
  font-size: 0.78rem;
  color: var(--text-muted-color);
}

.meta-icon {
  color: var(--text-muted-color);
  font-size: 0.72rem;
  margin-right: 0.2rem;
}

.catalog-radar-legend-block strong {
  color: var(--link-color);
  font-weight: 700;
}

.catalog-radar-svg {
  /* Height-driven now (fills .catalog-radar-svg-wrap's height, shrinking on
     a shorter window instead of overflowing it), width follows via the SVG's
     own square viewBox aspect ratio -- max-width is the same "-10% from the
     previous 1170px, per request (radar felt too big)" ceiling as before,
     now just guarding the width this sizing direction derives instead of
     being the driving dimension itself. */
  max-width: 1053px;
  width: auto;
  height: 100%;
  max-height: 100%;
}

/* Quadrant background wedges ("4 camemberts dans un rond") -- one pale tint
   per dimension, distinct from the bubble/badge palette elsewhere so they
   read as a soft backdrop rather than competing with the data itself. Each
   wedge's own stroke marks its own edges (radial sides + inner/outer arcs,
   the path is closed) in a darker shade of the same hue as its fill, rather
   than one shared border color for all 4. */
.catalog-radar-quadrant-bg {
  stroke-width: 1.5;
}

.catalog-radar-quadrant-bg-trustworthy-attributes { fill: #f0fdf4; stroke: #166534; }
.catalog-radar-quadrant-bg-problem-typology { fill: #eff6ff; stroke: #1d4ed8; }
.catalog-radar-quadrant-bg-engineering-roles { fill: #fffbeb; stroke: #b45309; }
.catalog-radar-quadrant-bg-end-to-end-activities { fill: #faf5ff; stroke: #7e22ce; }

.catalog-radar-ring {
  fill: none;
  stroke: var(--border-color-muted);
  stroke-width: 1;
}

.catalog-radar-segment-divider {
  stroke: var(--border-color-muted);
  stroke-width: 0.5;
  stroke-dasharray: 2 3;
}

.catalog-radar-quadrant-label {
  /* +25% from the previous 13px, per request -- see catalog-radar.js's
     renderCatalogRadar for the matching position recalculation this forced
     (maxRadius's reserved margin and the label's own radial offset both
     grew to keep clear of .catalog-radar-segment-tick's reach, which grew
     for the same reason when its own font-size got the same +25%). */
  font-size: 16.25px;
  font-weight: 700;
  fill: var(--title-color);
}

/* Tie each label's color to its own quadrant's background instead of one
   fixed color for all 4 -- same stroke colors as .catalog-radar-quadrant-bg-*
   above, so the label reads as "this quadrant's own text", not a generic
   heading floating over an unrelated tint. */
.catalog-radar-quadrant-label-trustworthy-attributes { fill: #166534; }
.catalog-radar-quadrant-label-problem-typology { fill: #1d4ed8; }
.catalog-radar-quadrant-label-engineering-roles { fill: #b45309; }
.catalog-radar-quadrant-label-end-to-end-activities { fill: #7e22ce; }

.catalog-radar-segment-tick {
  /* +25% from the previous 9.5px, per request. */
  font-size: 11.875px;
  fill: var(--text-muted-color);
}

/* Ticks and their segment's hit wedge (see catalog-radar.js) both toggle
   that value's sidebar filter on click, with name + asset count shown on
   hover via the shared #catalogTooltip. */
.catalog-radar-segment-tick {
  cursor: pointer;
}

.catalog-radar-segment-tick:hover,
.catalog-radar-segment-tick.is-selected {
  fill: var(--etaia-02);
  font-weight: 700;
}

/* Invisible until hovered/selected -- just a click target covering the
   segment's whole angular span, drawn under its bubbles. */
.catalog-radar-segment-hit {
  fill: transparent;
  cursor: pointer;
}

.catalog-radar-segment-hit:hover {
  fill: rgba(0, 0, 0, 0.05);
}

.catalog-radar-segment-hit.is-selected {
  fill: color-mix(in srgb, var(--etaia-02) 18%, transparent);
  stroke: var(--etaia-02);
  stroke-width: 1.5;
}

.catalog-radar-bubble {
  fill: var(--link-color);
  stroke: var(--page-background);
  stroke-width: 1;
  cursor: pointer;
}

.catalog-radar-bubble:hover {
  filter: brightness(0.85);
  r: 7;
}

/* Category colors, shared by radar bubbles, the compact radar chip list and
   the legend swatches -- one fixed hue per Portfolio Category (§1), kept
   distinct from the status-ring encoding (radial position) and the
   quadrant/axis encoding (which dimension a bubble sits in). */
.catalog-category-software { fill: #2563eb; }
.catalog-category-documentation { fill: #dc2626; }
.catalog-category-demonstrators { fill: #16a34a; }
.catalog-category-use-cases { fill: #d97706; }
.catalog-category-education { fill: #db2777; }

.catalog-radar-legend-swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  margin-left: 6px;
}

.catalog-radar-legend-swatch.catalog-category-software { background: #2563eb; }
.catalog-radar-legend-swatch.catalog-category-documentation { background: #dc2626; }
.catalog-radar-legend-swatch.catalog-category-demonstrators { background: #16a34a; }
.catalog-radar-legend-swatch.catalog-category-use-cases { background: #d97706; }
.catalog-radar-legend-swatch.catalog-category-education { background: #db2777; }

/* Category filter options (catalog.handlebars): same color as the cards'
   header band (.swatch-color below) for that category. */
.filter-category-swatch {
  flex: 0 0 auto;
  width: 10px;
  height: 10px;
  border-radius: 3px;
  background: var(--border-color-muted);
}

.filter-category-swatch.catalog-category-software { background: #2563eb; }
.filter-category-swatch.catalog-category-documentation { background: #dc2626; }
.filter-category-swatch.catalog-category-demonstrators { background: #16a34a; }
.filter-category-swatch.catalog-category-use-cases { background: #d97706; }
.filter-category-swatch.catalog-category-education { background: #db2777; }

/* Same vivid colors as .catalog-radar-legend-swatch above (same category ->
   same color everywhere), now painting the swatch-card's color band instead
   of tinting the whole chip's background/text like the old pill design did.
   .usecase-asset-card shares this same color band -- one shared rule per
   category rather than repeating the same 5 colors under a second
   selector. */
.catalog-radar-chip.catalog-category-software .swatch-color,
.usecase-asset-card.catalog-category-software .swatch-color { background: #2563eb; }
.catalog-radar-chip.catalog-category-documentation .swatch-color,
.usecase-asset-card.catalog-category-documentation .swatch-color { background: #dc2626; }
.catalog-radar-chip.catalog-category-demonstrators .swatch-color,
.usecase-asset-card.catalog-category-demonstrators .swatch-color { background: #16a34a; }
.catalog-radar-chip.catalog-category-use-cases .swatch-color,
.usecase-asset-card.catalog-category-use-cases .swatch-color { background: #d97706; }
.catalog-radar-chip.catalog-category-education .swatch-color,
.usecase-asset-card.catalog-category-education .swatch-color { background: #db2777; }

.catalog-tooltip {
  position: fixed;
  z-index: 2000;
  pointer-events: none;
  background: var(--text-color);
  color: var(--text-color-inverted);
  font-size: 0.78rem;
  padding: 4px 10px;
  border-radius: 6px;
  white-space: nowrap;
}

/* BOK phase hover card (catalog-radar.js's showBokPopover) -- same dark
   look as .catalog-tooltip above, but it takes pointer events (and wraps)
   so its BOK link can be clicked. */
.catalog-bok-popover {
  position: fixed;
  z-index: 2000;
  max-width: min(280px, calc(100vw - 16px));
  background: var(--text-color);
  color: var(--text-color-inverted);
  font-size: 0.78rem;
  padding: 4px 10px;
  border-radius: 6px;
}

.catalog-bok-popover[hidden] {
  display: none;
}

.catalog-bok-popover-title {
  display: block;
  font-weight: 700;
  color: inherit;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
}

.catalog-bok-popover-title:hover {
  text-decoration-color: currentColor;
}

.catalog-bok-popover-count {
  margin: 0;
  font-size: 0.72rem;
  opacity: 0.75;
}

.catalog-bok-popover-title i {
  font-size: 0.65em;
}

/* ---------------- asset detail page ---------------- */
/* Wider than the shared 1080px cap (same override pattern as
   .catalog-page .container) -- the two-column body (cartouches + main
   content) and the header's own left/right split both want the room. */
.asset-page .container {
  width: min(2000px, calc(100% - 2rem));
}

.asset-breadcrumb {
  font-size: 0.82rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
}

/* Members: buttons to this version's "Comment" (assetComment.handlebars)
   and "Propose a change" (assetForm.handlebars) forms, side by side on the
   right -- same size/shape as the catalogue toolbar's buttons. */
.asset-breadcrumb-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.asset-breadcrumb-actions .btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  height: 2.1rem;
  padding: 0 0.8rem;
  font-size: 0.8rem;
  font-weight: 600;
  border-radius: 8px;
  white-space: nowrap;
  text-decoration: none;
}

.asset-header-body {
  display: flex;
  justify-content: space-between;
  /* stretch (not flex-start) so .asset-header-status matches
     .asset-header-main's full height instead of just hugging its own
     content. */
  align-items: stretch;
  gap: 1.5rem;
}

.asset-header-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.8rem;
}

.asset-header-status {
  flex: 0 0 325px;
}

.asset-logo {
  display: block;
  max-height: 48px;
  max-width: 160px;
  object-fit: contain;
}

/* Same gradient as etaia.css's .hero -- padded/rounded so it reads as a
   panel inside .container rather than a full-bleed band. */
.asset-header {
  background: linear-gradient(180deg, #f3ecfa 0%, var(--paper-sunk) 100%);
  border-radius: 10px;
  padding: 1.2rem 1.5rem;
}

.asset-header h1 {
  margin: 0.4rem 0 0.6rem;
  flex: 1 1 auto;
  min-width: 0;
}

.asset-version {
  font-size: 0.9rem;
  font-weight: 400;
  color: var(--text-muted-color);
}

.asset-version i {
  margin-right: 0.15rem;
}

.asset-abstract {
  font-size: 1rem;
  line-height: 1.6;
  /* Forces this onto its own row below the logo+h1 row above, rather than
     sitting beside them -- .asset-header-main is a flex row now (see
     above) so a plain block child would otherwise still try to share the
     row with whatever space is left. */
  flex: 1 1 100%;
}

.asset-section {
  padding: 1.2rem 0;
}

.asset-section h2 {
  font-size: 1rem;
}

.asset-section p {
  font-size: 0.88rem;
  line-height: 1.6;
}

/* "No information yet" note under a section title whose field is empty
   (partials/noKnowledgeData) -- muted and italic so it reads as a status,
   not as the asset's own content. */
.asset-section p.asset-section-empty {
  font-size: 0.82rem;
  font-style: italic;
  color: var(--text-muted-color);
}

/* Rich-text fields (shortDescription, description.context/valueProposition/
   whenToUse) rendered through the richText helper (src/lib/richText.js) --
   same "anchors" mini-markdown as Bok's hasPurpose/hasSteps, label-above-body
   layout to match (a heading line inside the text can't nest in a <p>, which
   is why these use a label + separate body <div> instead of one <p>). */
.asset-rich-field {
  margin-bottom: 1rem;
}

.asset-rich-field-label {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--link-color);
  margin: 0 0 0.3rem;
}

.asset-rich-text {
  font-size: 0.88rem;
  line-height: 1.6;
  /* Free text from the ontology can carry real line breaks -- preserve them,
     same as Bok's .bok-insp-body. */
  white-space: pre-line;
  /* Long URLs/identifiers wrap instead of widening the page on mobile. */
  overflow-wrap: anywhere;
}

.asset-rich-text img,
.asset-rich-text video {
  max-width: 100%;
  height: auto;
}

/* No height:auto for iframes: an iframe has no intrinsic height, so "auto"
   collapses it to the browser default 150px and overrides etaia.css'
   .richtext-inline-pdf height (500px) for anchor:pdf: embeds. */
.asset-rich-text iframe {
  max-width: 100%;
}

/* anchor:pdf: embeds in a description: same reader height as the Content
   tab's .asset-pdf-reader-frame, rather than etaia.css' 500px inline base. */
.asset-rich-text .richtext-inline-pdf {
  height: 80vh;
  min-height: 500px;
}

/* Headings/links/images/pdf/video anchors' base look (.richtext-inline-*)
   now comes from @etaia/web-app's own etaia.css, loaded before this file --
   see src/lib/richText.js, a thin wrapper around that package's
   createRichTextRenderer. Only catalog's own anchor kind needs styling here. */

/* [label](anchor:asset:<shortId>) -- a real internal link to another asset's
   page, unlike Bok's version of this (an inert span until JS resolves it
   against the current SVG diagram): the catalogue has no diagram to resolve
   against, every asset already has a real route, so this just IS that link. */
.asset-inline-anchor {
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}

.asset-links a {
  margin-right: 0.3rem;
}

.asset-private-section {
  background: var(--form-background);
  border-radius: 10px;
  padding: 1.2rem;
  border-top: none;
}

.asset-private-hint {
  font-size: 0.85rem;
  color: var(--text-muted-color);
  padding: 1rem 0;
}

/* "Data flow" diagram (dataTypeInputs/dataTypeOutputs) -- class names/
   animations adapted from a standalone snippet supplied for this purpose,
   renamed to this file's asset-io-* convention. Two dead-code rules from
   that snippet (.io-diagram, .left-arrows/.right-arrows) weren't referenced
   by its markup and are dropped here; .asset-io-arrow is `position:
   relative` (the original had `position: static`), which its own
   `::after` triangle needs to position against -- static was a bug, not a
   deliberate choice. */
.asset-io-container {
  margin: 24px 0;
  padding: 40px 20px;
  border-radius: 12px;
  /* Fixed-gap flow diagram: scrolls on its own on narrow screens instead
     of widening the page. */
  overflow-x: auto;
}

.asset-io-connector-container {
  position: relative;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 40px;
}

.asset-io-container h4 {
  color: #500e7c;
  font-weight: bold;
  margin: 0;
  font-size: 0.95em;
  text-transform: uppercase;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
}

.asset-io-output-title {
  transform: rotate(0deg);
}

.asset-io-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: flex-start;
}

.asset-io-items {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.asset-io-item {
  display: flex;
  align-items: center;
}

.asset-io-item.input {
  justify-content: flex-end;
}

.asset-io-item.output {
  justify-content: flex-start;
}

.asset-io-input-item,
.asset-io-output-item {
  background: white;
  border: 2px solid #500e7c;
  color: #500e7c;
  padding: 10px 16px;
  border-radius: 6px;
  font-weight: 600;
  font-size: 0.9em;
  text-align: center;
  white-space: nowrap;
  animation: assetIoSlideIn 0.6s ease-out forwards;
  opacity: 0;
}

.asset-io-input-item {
  margin-right: 30px;
}

.asset-io-output-item {
  margin-left: 40px;
}

@keyframes assetIoSlideIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.asset-io-component-box {
  width: 140px;
  height: 140px;
  background: linear-gradient(135deg, #500e7c 0%, #7a2d9f 100%);
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-weight: bold;
  text-align: center;
  padding: 16px;
  font-size: 0.85em;
  box-shadow: 0 10px 30px rgba(80, 14, 124, 0.3);
  animation: assetIoBoxPulse 5s ease-in-out infinite;
}

@keyframes assetIoBoxPulse {
  0%,
  100% {
    box-shadow: 0 10px 30px rgba(80, 14, 124, 0.3);
    transform: scale(1);
  }
  50% {
    box-shadow: 0 15px 40px rgba(80, 14, 124, 0.4);
    transform: scale(1.02);
  }
}

.asset-io-arrow {
  position: relative;
  width: 30px;
  height: 2px;
  background: linear-gradient(to right, #500e7c, #7a2d9f);
  animation: assetIoArrowFlow 3s ease-in-out infinite;
}

.asset-io-arrow::after {
  content: "";
  position: absolute;
  right: -6px;
  top: -4px;
  width: 0;
  height: 0;
  border-left: 8px solid #500e7c;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
}

.asset-io-item.output .asset-io-arrow {
  background: linear-gradient(to left, #500e7c, #7a2d9f);
}

@keyframes assetIoArrowFlow {
  0% {
    opacity: 0;
    transform: translateX(0);
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translateX(10px);
  }
}

/* ------------------------- /components: tabs ------------------------- */
/* Generic tab widget (public/js/tabs.js) -- visibility is driven by each
   panel's own [hidden] attribute, not a class here, so there's no author
   `display` rule that could defeat the browser's default [hidden]{display:
   none} the way .catalog-radar-view/#catalogRadarSvgWrap did earlier in this
   app (see their own comments) -- .tab-panel intentionally sets no display
   property at all. */
.tabs {
  margin-top: 1.5rem;
}

.tab-list {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--border-color, #d8dde3);
  margin-bottom: 1.5rem;
}

.tab-button {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 0.6rem 1rem;
  font: inherit;
  font-weight: 600;
  color: var(--text-muted-color, #5b6472);
  cursor: pointer;
}

.tab-button:hover {
  color: var(--link-color-hover);
}

.tab-button.is-active {
  color: var(--link-color-hover);
  border-bottom-color: var(--link-color-hover);
}

/* --------------------- /components: CRUD form demo --------------------- */
/* Generic Create/Edit/Save/Delete form component (public/js/crud-form.js) --
   the field markup it builds reuses .form-card/.form-section/.form-row-2/
   .form-field/.form-label/.form-input straight from etaia.css (the same
   classes @etaia/web-app's own style-guide "Personal information" mockup
   uses), so only the widget's own chrome (toolbar, list, error text) needs
   rules here. */
.crud-form-toolbar {
  margin-bottom: 1rem;
}

.crud-form-list-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  list-style: none;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--border-color, #d8dde3);
}

.crud-form-list-summary {
  font-weight: 600;
}

.crud-form-empty {
  color: var(--text-muted-color, #5b6472);
  font-style: italic;
}

.crud-form-error {
  color: var(--danger-color, #B62039);
  font-weight: 600;
}

.crud-form-card {
  margin-top: 1.5rem;
  max-width: 40rem;
}

.crud-form-actions {
  display: flex;
  gap: 0.75rem;
  margin-top: 1rem;
}

/* ------------- /assets/new: "Propose an asset" (asset-form.js) ------------- */
/* Fields reuse etaia.css' .form-card/.form-section/.form-field markup like the
   CRUD demo above; only the widgets etaia.css has no equivalent for
   (checkbox lists, tags, repeated rows) and the result panel need rules. */
.asset-form-page {
  max-width: 52rem;
}

.asset-form-back {
  margin-bottom: 0.5rem;
}

.asset-form-intro {
  color: var(--text-muted-color, #5b6472);
}

.asset-form-card.form-card--grouped {
  max-width: none;
}

.asset-form-textarea {
  resize: vertical;
  min-height: 6rem;
}

.asset-form-help {
  font-size: 0.78rem;
  color: var(--text-muted-color, #5b6472);
  margin: 0;
}

.asset-form-required {
  color: var(--accent-red, #B62039);
}

.asset-form-multi {
  border: 1.5px solid var(--hairline, #d8dde3);
  border-radius: 8px;
  padding: 0.5rem 0.75rem;
}

.asset-form-multi-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.asset-form-multi-head:empty {
  display: none;
}

.asset-form-multi-filter {
  flex: 1;
  margin-bottom: 0.4rem;
}

.asset-form-multi-count {
  font-size: 0.78rem;
  color: var(--etaia-01, #0b5cad);
  font-weight: 600;
  white-space: nowrap;
}

.asset-form-multi-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 0.2rem 1rem;
  max-height: 14rem;
  overflow-y: auto;
}

.asset-form-multi-option {
  color: var(--text-color, #1d2430);
  cursor: pointer;
}

.asset-form-multi-option[hidden] {
  display: none;
}

.asset-form-tags-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}

.asset-form-tags-chips:empty {
  display: none;
}

.asset-form-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.asset-form-tag-remove {
  border: none;
  background: none;
  padding: 0;
  cursor: pointer;
  font-size: 1rem;
  line-height: 1;
  color: inherit;
}

.asset-form-repeater-rows {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  margin-bottom: 0.75rem;
}

.asset-form-repeater-row {
  border: 1px solid var(--hairline, #d8dde3);
  border-radius: 10px;
  padding: 1rem 1rem 0.5rem;
  margin: 0;
}

.asset-form-repeater-remove {
  margin-bottom: 0.5rem;
}

.asset-form-errors {
  border: 1px solid var(--accent-red, #B62039);
  border-radius: 8px;
  padding: 0.75rem 1rem;
  margin-bottom: 1.5rem;
  color: var(--accent-red, #B62039);
}

.asset-form-errors-title {
  font-weight: 700;
  margin: 0 0 0.3rem;
}

.asset-form-errors ul {
  margin: 0;
  padding-left: 1.2rem;
}

/* "Propose a change": published values the form can't carry over. */
.asset-form-notices {
  border: 1px solid var(--accent-amber, #AA610E);
  border-radius: 8px;
  padding: 0.75rem 1rem;
  margin-bottom: 1.5rem;
  font-size: 0.9rem;
}

.asset-form-notices-title {
  font-weight: 700;
  margin: 0 0 0.3rem;
}

.asset-form-notices ul {
  margin: 0;
  padding-left: 1.2rem;
}

.asset-form-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

/* Tabs of the form (asset-form.js' buildTabs): the generic .tab-list/
   .tab-button look, the panels' own [hidden] doing the switching. */
.asset-form-tab-list {
  margin-bottom: 0.5rem;
}

.asset-form-tab-nav {
  display: flex;
  justify-content: flex-end;
  margin-top: 1rem;
}

/* display:flex above would otherwise defeat [hidden] (last shown tab). */
.asset-form-tab-nav[hidden] {
  display: none;
}

.asset-form-thanks {
  font-weight: 600;
}

/* Submit stands apart from the tabs (top divider) and from the reset
   button (pushed to the right end of the row). */
.asset-form-actions {
  padding-top: 1.25rem;
  border-top: 1px solid var(--border-color, #d8dde3);
}

.asset-form-submit {
  margin-left: auto;
}

.asset-form-draft-note {
  font-size: 0.78rem;
  color: var(--text-muted-color, #5b6472);
}

.asset-form-result {
  margin-top: 2rem;
}

@media (max-width: 640px) {
  .asset-form-page .form-row-2 {
    grid-template-columns: 1fr;
  }
}

/* ---------------- use-case fiche (usecase.handlebars) ---------------- */
/* Header: name/version/summary on the left, banner on the right. */
.usecase-header--with-banner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 520px);
  gap: 1.5rem;
  align-items: center;
}

.usecase-header-main .asset-logo {
  margin-bottom: 0.4rem;
}

.usecase-header-status {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 0.6rem;
}

.usecase-banner {
  display: block;
  width: 100%;
  max-height: 240px;
  /* Whole banner always visible, undistorted (cover would crop any text or
     figure near its edges): a banner taller than 240px is scaled down and
     centered, leaving empty side bands. */
  object-fit: contain;
  border-radius: 10px;
}

/* Bordered 3-cell tables of the use-case body (intended purpose |
   operational domain + ODD | datasets; 2 cells with .usecase-table--2col),
   beside the usual 340px right cartouche column. */
.usecase-table {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border: 1px solid var(--border-color-muted);
  border-radius: 10px;
  margin: 1.2rem 0;
}

.usecase-table-cell {
  padding: 1rem 1.2rem;
  min-width: 0;
}

.usecase-table-cell + .usecase-table-cell {
  border-left: 1px solid var(--border-color-muted);
}

.usecase-table-cell h2 {
  font-size: 1.1rem;
  margin: 0 0 0.6rem;
}

.usecase-table-cell .asset-rich-text + h2 {
  margin-top: 1.2rem;
}

/* Sections stacked inside one cell (context, description...). */
.usecase-table-cell .asset-section {
  padding: 0;
}

.usecase-table-cell .asset-section + .asset-section {
  margin-top: 1.4rem;
}

.usecase-table-cell h2 abbr {
  font-weight: 400;
  color: var(--text-muted-color);
  text-decoration: none;
}

@media (max-width: 1200px) {
  .usecase-table {
    grid-template-columns: minmax(0, 1fr);
  }

  .usecase-table-cell + .usecase-table-cell {
    border-left: none;
    border-top: 1px solid var(--border-color-muted);
  }
}

/* Overview tabs (software + use-case fiches): the use-case table's grid
   without its borders, a wide gutter between columns instead, and a dotted
   rule between stacked sections. Software: 2 cells (context + value
   proposition | when to use it + BOK diagram), rule in the left cell only.
   Use case (.usecase-table--open): 3 cells, rule in every cell, and the
   2nd table split from the 1st by the same dotted rule. */
.software-table {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.software-table,
.usecase-table--open {
  column-gap: 4rem;
  row-gap: 2rem;
  border: none;
  border-radius: 0;
}

.usecase-table--open {
  column-gap: 2.5rem;
}

.software-table .usecase-table-cell,
.usecase-table--open .usecase-table-cell {
  padding: 0;
}

/* Software overview: extra side breathing room around each column's text
   (wide 2-column layout only -- see the max-width:1200px/600px overrides). */
.software-table .usecase-table-cell {
  padding-left: 50px;
  padding-right: 50px;
}

.software-table .usecase-table-cell + .usecase-table-cell,
.usecase-table--open .usecase-table-cell + .usecase-table-cell {
  border: none;
}

.software-table .usecase-table-cell:first-child .asset-section + .asset-section,
.usecase-table--open .usecase-table-cell .asset-section + .asset-section {
  margin-top: 1.4rem;
  padding-top: 1.4rem;
  border-top: 2px dotted var(--border-color-muted);
}

.usecase-table--open + .usecase-table--open {
  margin-top: 1.6rem;
  padding-top: 1.6rem;
  border-top: 2px dotted var(--border-color-muted);
}

.software-when-to-use {
  margin-bottom: 1.4rem;
}

/* Software fiche body tabs (Overview / Related assets / Details) -- the
   generic .tabs widget, with the header's own spacing above it instead. */
.asset-tabs {
  margin-top: 1rem;
}

/* Details tab (software fiche), compact: a single column of borderless
   sections (data flow, technical details, functional constraints,
   classification, organisations & sources), split by the same dotted rule
   as the Overview tab's left column. Tight paddings/type sizes -- this tab
   is a reference sheet, not reading. */
.details-layout {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.details-card {
  padding: 0.9rem 0;
  min-width: 0;
}

.details-layout > * + * {
  border-top: 2px dotted var(--border-color-muted);
}

.details-layout > :first-child {
  padding-top: 0;
}

.details-card-title {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 0.6rem;
}

.details-card-title i {
  color: var(--link-color);
}

/* Technical details: its groups (Identity, Python stack, ...) side by side. */
.details-groups {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 0.6rem 1.25rem;
}

.details-group {
  min-width: 0;
}

/* Small uppercase label introducing a group of rows/chips inside a card. */
.details-group-title {
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--link-color);
  margin: 0.5rem 0 0.2rem;
}

.details-group .details-group-title,
.details-card-title + .details-group-title {
  margin-top: 0;
}

/* Label/value sheet: label column + value column, light row separators. */
.details-sheet {
  display: grid;
  grid-template-columns: 105px minmax(0, 1fr);
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.4;
}

.details-sheet dt,
.details-sheet dd {
  margin: 0;
  padding: 0.2rem 0;
  border-top: 1px solid var(--paper-sunk);
}

.details-sheet dt {
  color: var(--text-muted-color);
  font-weight: 600;
  padding-right: 0.5rem;
}

.details-sheet > :nth-child(-n + 2) {
  border-top: none;
}

.details-sheet code {
  font-size: 0.75rem;
}

.details-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin: 0 0 0.3rem;
}

.details-chip,
.details-chips .badge {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-size: 0.72rem;
  line-height: 1.5;
  margin: 0;
}

.details-chip {
  background: var(--paper-sunk);
  border: 1px solid var(--border-color-muted);
}

.details-links {
  margin: 0;
}

.details-links li {
  font-size: 0.78rem;
  margin-bottom: 0.15rem;
}

.details-links i {
  color: var(--text-muted-color);
}

.details-card .gh-badge {
  font-size: 0.72rem;
}

.details-card .asset-data-sources ul.plain li {
  font-size: 0.78rem;
  margin-bottom: 0.25rem;
}

/* Bottom row: Classification | Organisations | Sources | Data flow, same
   group-title logic as Technical details; 2 columns below 1100px, 1 below
   600px. */
.details-columns {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem 1.5rem;
}

.details-column {
  min-width: 0;
}

.details-text {
  margin: 0 0 0.3rem;
  font-size: 0.78rem;
  line-height: 1.4;
}

/* Data flow as a horizontal inputs -> asset -> outputs strip, sized for a
   details column: each end stacks its chips vertically so the 3 parts fit
   side by side; scrolls on its own rather than overflowing if it can't. */
.details-flow {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  overflow-x: auto;
}

.details-flow-end {
  flex: 0 1 auto;
  min-width: 0;
}

.details-flow-end .details-chips {
  flex-direction: column;
  align-items: flex-start;
  margin: 0;
}

.details-flow-box {
  flex: 0 1 auto;
  max-width: 7rem;
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
  background: linear-gradient(135deg, #500e7c 0%, #7a2d9f 100%);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.3;
  text-align: center;
}

.details-flow-arrow {
  flex: 0 0 auto;
  color: var(--link-color);
  font-size: 0.75rem;
}

@media (max-width: 1100px) {
  .details-columns {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 600px) {
  .details-columns {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Functional constraints: compact amber note, theme amber/ivory accents. */
.details-callout {
  padding: 0.6rem 0.9rem;
  border-radius: 8px;
  border-left: 3px solid var(--accent-amber);
  background: var(--accent-ivory);
}

/* The callout is its own visual block: no dotted rule above it. */
.details-layout > .details-callout {
  border-top: none;
  margin: 0.4rem 0 0.9rem;
}

.details-callout-icon {
  color: var(--accent-amber);
}

/* Icon inline with the title, on the same baseline-centred row. */
.details-callout-title {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 0.15rem;
  color: var(--accent-amber);
}

.details-callout p {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
}

@media (max-width: 600px) {
  .details-sheet {
    grid-template-columns: minmax(0, 1fr);
  }

  .details-sheet dd {
    border-top: none;
    padding-top: 0;
  }

  .tab-list {
    overflow-x: auto;
  }
}

/* Per-role usages (engineeringRoleUsages) listed under the when-to-use text:
   role label, its user story, then the BOK activity badge -- same badge
   link-out as .cartouche-bok-activities. */
.role-usages {
  margin-top: 0.8rem;
}

.role-usage {
  padding-left: 0.7rem;
  border-left: 3px solid var(--link-color);
  margin-bottom: 0.8rem;
}

.role-usage-role {
  font-weight: 700;
  margin: 0 0 0.15rem;
}

/* Use-case fiche: the role after the asset's name ("Data Quality Metrics
   — ML Algorithm Engineer"). */
.role-usage-by {
  font-weight: 400;
  color: var(--text-muted-color);
}

/* Use-case fiche's 2-column tables (usecase.handlebars): the Overview
   (context + definition | engineering issues) and the Applied assets tab's
   "How the assets are used" (usages | W-cycle diagram). */
.usecase-table--2col {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* "Described in the sub-activity “…” ↗ from the activity “…” ↗" -- a plain
   sentence; hovering it highlights the root box in the W-cycle diagram. */
.role-usage-activity {
  font-size: 0.8rem;
  font-style: italic;
  color: var(--text-muted-color);
  margin: 0.3rem 0 0;
  padding: 0.1rem 0.3rem;
  margin-left: -0.3rem;
  border-radius: 4px;
  cursor: default;
  transition: background-color 0.15s ease;
}

.role-usage-activity.is-bok-focused {
  background: var(--paper-sunk);
}

/* anchor:activity:<BOK_ID> links in rich text (richText.js) -- hovering one
   focuses its root box in the W-cycle diagram, like .role-usage-activity. */
.bok-activity-inline-anchor {
  font-weight: 600;
  padding: 0 0.2rem;
  margin: 0 -0.2rem;
  border-radius: 4px;
  transition: background-color 0.15s ease;
}

.bok-activity-inline-anchor.is-bok-focused {
  background: var(--paper-sunk);
}

.bok-activity-inline-anchor i {
  font-size: 0.65rem;
}

.role-usage-activity a {
  font-style: normal;
  white-space: nowrap;
}

.role-usage-activity a i {
  font-size: 0.65rem;
}

@media (max-width: 1200px) {
  .software-table,
  .usecase-table--2col {
    grid-template-columns: minmax(0, 1fr);
  }

  .software-table .usecase-table-cell {
    padding-left: 1.5rem;
    padding-right: 1.5rem;
  }
}

@media (max-width: 600px) {
  .software-table .usecase-table-cell {
    padding-left: 0;
    padding-right: 0;
  }
}

@media (max-width: 600px) {
  .usecase-table-cell {
    padding: 0.8rem;
  }
}

@media (max-width: 900px) {
  .usecase-header--with-banner {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Same compact swatch-card shape as the catalogue list's chips. */
.usecase-asset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 0.6rem;
}

.usecase-asset-card {
  color: inherit;
  text-decoration: none;
}

.usecase-asset-card.card--swatch .swatch-color {
  height: 10px;
}

.usecase-asset-card .swatch-name {
  margin: 0 0 0.3rem;
}

.usecase-asset-card .swatch-hex {
  text-transform: none;
  font-variant-numeric: normal;
  line-height: 1.4;
  margin: 0.3rem 0 0;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* In-page PDF reader for a fiche's delivered PDF files (software.handlebars'
   .asset-pdf-reader) -- etaia.css' .richtext-inline-pdf base, taller since
   the document is the page's main content here, not an inline aside. */
.asset-pdf-reader-frame {
  height: 80vh;
  min-height: 500px;
}

/* Content tab's player for a delivered video file or YouTube video/playlist
   (software.handlebars' .asset-video-player): full width, 16:9. */
.asset-video-player-frame {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 0;
  border-radius: 6px;
  background: #000;
}

/* Successive delivered files in the Content tab stay visually separate, and
   an anchor jump from the summary menu lands below the sticky site header
   (63px, etaia.css) instead of under it. */
#tab-panel-content > .asset-section + .asset-section {
  margin-top: 1.5rem;
}

#tab-panel-content > .asset-section {
  scroll-margin-top: 80px;
}

/* Content tab's summary menu (software.handlebars' .asset-content-menu):
   one row per delivered file, shown above them when there's more than one. */
.asset-content-menu {
  margin-top: 1.2rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--border-color-light);
  border-radius: 6px;
}

.asset-content-menu-title {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted-color);
}

.asset-content-menu-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.asset-content-menu-link {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.4rem 0.5rem;
  border-radius: 4px;
  color: var(--link-color);
  text-decoration: none;
}

.asset-content-menu-link:hover,
.asset-content-menu-link:focus-visible {
  background: var(--border-color-light);
}

.asset-content-menu-label {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}

.asset-content-menu-kind {
  font-size: 0.8rem;
  color: var(--text-muted-color);
}

/* Content tab's download widget for a delivered .zip (software.handlebars'
   .asset-zip-widget): archive icon, label + file name, Download button. */
.asset-zip-widget {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.25rem;
  border: 1px solid var(--border-color-light);
  border-radius: 6px;
}

.asset-zip-widget-icon {
  font-size: 2rem;
  color: var(--link-color);
}

.asset-zip-widget-meta {
  flex: 1;
  min-width: 0;
}

.asset-zip-widget-meta h2 {
  margin: 0;
}

.asset-zip-widget-file {
  margin: 0.2rem 0 0;
  overflow-wrap: anywhere;
  color: var(--text-muted-color);
}
