/* stack_card.css — shared shell + card styles for /catalog and /memory. * * Visual parity with /marketplace: hero, tab strip, filter chips, card * grid and empty state all share the marketplace.html .mp-* look so the * three pages read as one product. Class names stay `stack-*` (not * `mp-*`) because tests + JS hook on these names already; the CSS * underneath mirrors marketplace.html rule-for-rule (palette, padding, * border-radius, shadow, hover lift, grid breakpoints). * * Borders and badges are dual-encoded (color + text) per the design * spec's a11y constraint — color alone never carries the semantic. */ /* ── Hero (gradient, mirrors marketplace.html .mp-hero) ──────────────── */ /* Search-driven hero (catalog, corporate-memory) — same box as the * canonical `.page-header--hero` rule in style-custom.css. The * container (`.container`) provides max-width + gutters; the hero * just owns its own padding + gradient + radius + shadow. */ .stack-hero { position: relative; overflow: hidden; /* Hero gradient + shadow flip per theme via `--ds-hero-*`. */ background: linear-gradient(135deg, var(--ds-hero-bg) 0%, var(--ds-hero-bg-deep) 100%); border-radius: 14px; padding: 28px 32px 24px; margin: 0 0 var(--space-5); box-sizing: border-box; box-shadow: 0 4px 16px var(--ds-hero-shadow); color: #fff; } .stack-hero .eyebrow { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; color: rgba(255, 255, 255, 0.75); margin-bottom: 8px; } .stack-hero h1 { margin: 0; font-size: 28px; font-weight: 700; letter-spacing: -0.4px; } .stack-hero .sub { margin: 6px 0 0; font-size: 14px; color: rgba(255, 255, 255, 0.85); } /* Embedded hero search — mirrors marketplace .mp-hero .search-row. * Floats on top of the gradient like a card; gives the hero a real * affordance to interact with instead of being purely decorative. */ .stack-hero__search-row { display: flex; align-items: stretch; margin-top: 18px; background: #fff; border-radius: 10px; padding: 4px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18); max-width: 760px; } .stack-hero__search-wrap { flex: 1; position: relative; min-width: 0; } .stack-hero__search-row input[type="search"] { width: 100%; padding: 11px 14px 11px 40px; border: none; border-radius: 8px; font-size: 14px; font-family: inherit; background: transparent; color: var(--text-primary, #202124); outline: none; } .stack-hero__search-row input[type="search"]::placeholder { color: var(--text-secondary, #5f6368); opacity: 0.75; } /* v51 lifecycle status filter row — sits in the hero below the search. * White checkbox set on the gradient background; click any combination * to filter the card grid by `data-status`. Empty selection = show all. */ .stack-hero__status-row { display: flex; align-items: center; gap: 16px; margin-top: 14px; font-size: 12px; color: rgba(255, 255, 255, 0.92); flex-wrap: wrap; } .stack-hero__status-row label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; } .stack-hero__status-row input[type="checkbox"] { accent-color: #0EA5B5; cursor: pointer; } .stack-hero__status-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.6px; color: rgba(255, 255, 255, 0.7); font-weight: 600; } .stack-hero__search-icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--text-secondary, #5f6368); pointer-events: none; } /* Green Search button anchored to the right edge of the pill. Same * fill + spacing as marketplace's `.mp-hero .search-btn` so /catalog, * /memory, /marketplace all wear the same search affordance. */ .stack-hero__search-btn { appearance: none; border: none; background: var(--ds-primary); color: #fff; padding: 0 24px; border-radius: 8px; font-size: 13px; font-weight: 600; font-family: inherit; cursor: pointer; flex-shrink: 0; transition: background 0.15s ease; } .stack-hero__search-btn:hover { background: var(--ds-primary-dark); } .stack-hero__search-btn:active { transform: scale(0.98); } /* ── Curator info block (marketplace .mp-curator-block) ──────────────── */ /* Light card with a primary-blue left border + bold title + body text; * mirrors the trust/info pattern marketplace uses below the hero to * explain the page purpose. The slot sits between hero and tab strip * so it feels like part of the page chrome, not a banner. */ .stack-curator-block { background: rgba(0, 115, 209, 0.06); border: 1px solid rgba(0, 115, 209, 0.18); border-left: 3px solid var(--primary, #0073D1); border-radius: 8px; padding: 12px 16px; margin-bottom: 18px; } .stack-curator-block__title { font-size: 13px; font-weight: 600; color: var(--text-primary, #202124); margin-bottom: 2px; } .stack-curator-block__body { font-size: 13px; color: var(--text-secondary, #5f6368); line-height: 1.5; } /* ── Tab strip + filter chips (marketplace .mp-tabs / .mp-tabs-row) ──── */ .stack-tabs-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; } /* Right-of-tabs action slot (marketplace .mp-actions parity). The * tab strip is the left child of .stack-tabs-row; this slot sits on * the right with the admin-only CTA (+ New Data Package on /catalog, * Manage domains → on /memory). Hidden gracefully when no admin * actions render. */ .stack-tabs-row__actions { display: flex; gap: 8px; align-items: center; } /* Admin action button — green primary fill matching `.btn-primary` * across the app (and /home's "Copy install script to clipboard" * CTA). The right slot of the tab row carries +Recipe / +Data * Package on /catalog and +Domain on /memory. `inline-flex` + * `line-height: 1` so an `` and a `