Component library
Back to catalog

Tag title banner

An inner-page banner as a split: breadcrumb and a heavy uppercase title with a stamped tag on a navy field, and an optional full-height photo panel meeting it at an accent seam (a closing strip below 700px). Rises in on load and clears a fixed pill header.

page headerbannerbreadcrumbinner pageload-intideway

Open preview in a new tab

Use this component

Three ways to get Tag title banner into one of your own projects. The first two carry the component's files with them, so nothing has to fetch this page.

Start here

Placement prompt

The whole thing: what to do, where it goes, what must not change, and every one of the component's 2 files appended underneath with the path each belongs at. Paste it into Claude Code inside the destination project — it fetches nothing and needs nothing else.

Read it first — the files are added underneath when you copy
Add Tag title banner from my Astro Component Library to this Astro project.

Library page, for reference only:
https://astro.baysixmedia.com/components/tag-title-banner/

Place it in:
[ENTER PAGE, FILE, OR ROUTE]

Position:
[ENTER WHERE IT SHOULD APPEAR]

Every file you need is appended below, each fenced with the path it belongs at. Write them there, relative to the project root. Do not import anything from the deployed library at runtime, and do not fetch the library page — the files below are the source of truth.

Adapt its demo content, links, colors, typography, and images to this project through documented props where possible. Preserve its responsive behavior, accessibility, interaction logic, reduced-motion behavior, and support for multiple instances. Avoid changing unrelated project code.

Test it at desktop, tablet, and mobile widths. Run the project's available check and build commands. Report the files changed and any differences from the library version. Do not commit or deploy.

Install kit

The 2 files this component needs and nothing else, each fenced with the path it belongs at, followed by what the library's own verification covered and what it did not. No instructions attached — for placing it yourself, or handing it to something that has its own.

Read it first
Install kit: "Tag title banner"
Library page: https://astro.baysixmedia.com/components/tag-title-banner/
Files: 2 required, 1 supporting

Write each block below to the path named in its header, relative to the project root. A block marked (required) is one the component does not work without; (supporting) is documentation. Nothing here needs downloading except a block that says so in as many words.

===== FILE (required): src/components/TagTitleBanner.astro =====
---
/**
 * TagTitleBanner
 *
 * An inner-page banner built as a split: the breadcrumb and a heavy
 * uppercase title with a stamped tag on a navy field, and — when a photo is
 * given — a full-height photo panel meeting it at an accent seam. Below
 * 700px of its own width the photo becomes a strip that closes the banner.
 * Leaves room at the top for a fixed pill header.
 *
 * Sizes follow the component's own width (container queries), so it holds
 * the same composition in a sidebar layout or a narrow column. The title
 * rises in on load; the breadcrumb follows. Both end at rest and are off
 * under reduced motion.
 *
 * Reads the --tw-* tokens from any ancestor, with fallbacks.
 */

export interface TagTitleCrumb {
	label: string;
	/** Omit on the last crumb, the current page. */
	href?: string;
}

export interface TagTitleBannerProps {
	title?: string;
	/** The orange box after the title. `""` drops it. */
	tag?: string;
	breadcrumbs?: TagTitleCrumb[];
	/** Background photo. `src: ""` renders the navy band alone. */
	background?: { src?: string };
	animate?: boolean;
	fontStylesheet?: string;
	class?: string;
	id?: string;
}

interface Props extends TagTitleBannerProps {}

const {
	title = "",
	tag = "",
	breadcrumbs: rawCrumbs = [],
	background: bgProp,
	animate = true,
	fontStylesheet = "https://fonts.googleapis.com/css2?family=Outfit:wght@500;600;700;800;900&family=Noto+Sans:wght@400;500;600;700&family=Inter:wght@500;600;700&display=swap",
	class: className,
	id,
} = Astro.props;

/* No photo by default: the navy band renders alone. No title, no banner. */
const background = { src: "", ...(bgProp ?? {}) };
const breadcrumbs = rawCrumbs.filter((c) => c?.label);
const SAFE = /^(?:https?:|mailto:|tel:|[#/.?])/i;
const safeHref = (href: string) => (SAFE.test(href.trim()) ? href.trim() : "#");
---

{title && (
<>
{fontStylesheet && <link rel="stylesheet" href={fontStylesheet} />}
<section class:list={["ttb", className]} id={id} data-animate={animate ? "" : undefined} data-media={background.src ? "" : undefined}>
	<div class="ttb-grid">
	<div class="ttb-inner">
		{
			breadcrumbs.length > 0 && (
				<nav class="ttb-crumbs" aria-label="Breadcrumb">
					<ol>
						{breadcrumbs.map((c, i) => (
							<li>
								{c.href && i < breadcrumbs.length - 1 ? (
									<a href={safeHref(c.href)}>{c.label}</a>
								) : (
									<span aria-current={i === breadcrumbs.length - 1 ? "page" : undefined}>{c.label}</span>
								)}
							</li>
						))}
					</ol>
				</nav>
			)
		}
		<h1 class="ttb-title">
			<span class="ttb-word">{title}</span>
			{tag && <span class="ttb-tag">{tag}</span>}
		</h1>
	</div>
	{
		background.src && (
			<div class="ttb-media" aria-hidden="true">
				<img src={background.src} alt="" width="1920" height="600" fetchpriority="high" decoding="async" />
			</div>
		)
	}
	</div>
</section>
</>
)}

<style>
	.ttb {
		--ttb-navy: var(--tw-navy, #0b4654);
		--ttb-accent: var(--tw-accent, #ff6d45);
		--ttb-display: var(--tw-display, Outfit, ui-sans-serif, system-ui, sans-serif);
		--ttb-body: var(--tw-body, "Noto Sans", ui-sans-serif, system-ui, sans-serif);
		--ttb-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
		--ttb-seam: 6px;

		container-type: inline-size;
		position: relative;
		isolation: isolate;
		overflow: hidden;
		background: var(--ttb-navy);
		color: #fff;
		font-family: var(--ttb-body);
		/* The closing edge: the banner ends on a line, never on open colour. */
		border-bottom: var(--ttb-seam) solid var(--ttb-accent);
	}

	.ttb *,
	.ttb *::before,
	.ttb *::after {
		box-sizing: border-box;
	}

	.ttb-grid {
		display: grid;
	}

	/* Step 39.2: --tw-grid-max / --tw-grid-gutter put the title on a site grid; the fallbacks are the original 1440 / 64. */
	.ttb-inner {
		--ttb-max: var(--tw-grid-max, 1440px);
		--ttb-gutter: var(--tw-grid-gutter, 64px);
	}

	.ttb-inner {
		display: flex;
		flex-direction: column;
		justify-content: flex-end;
		gap: 18px;
		min-width: 0;
		padding: 124px 20px 40px;
	}

	/* ---- breadcrumb: wayfinding first, above the title ---- */

	.ttb-crumbs ol {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 0 2px;
		margin: 0;
		padding: 0;
		list-style: none;
		font: 500 15px/1.4 var(--ttb-body);
	}

	.ttb-crumbs li {
		display: flex;
		align-items: center;
		min-width: 0;
	}

	.ttb-crumbs li + li::before {
		content: "/";
		margin: 0 8px 0 6px;
		color: rgb(255 255 255 / 0.4);
	}

	.ttb-crumbs a,
	.ttb-crumbs span {
		display: inline-block;
		padding: 5px 0;
		overflow-wrap: anywhere;
	}

	.ttb-crumbs a {
		color: rgb(255 255 255 / 0.74);
		text-decoration: underline;
		text-decoration-color: rgb(255 255 255 / 0);
		text-underline-offset: 4px;
		transition: color 0.2s var(--ttb-ease), text-decoration-color 0.2s var(--ttb-ease);
	}

	.ttb-crumbs a:hover {
		color: #fff;
		text-decoration-color: rgb(255 255 255 / 0.6);
	}

	.ttb-crumbs a:focus-visible {
		outline: 2px solid #fff;
		outline-offset: 2px;
		border-radius: 2px;
	}

	.ttb-crumbs [aria-current] {
		color: #fff;
		font-weight: 600;
	}

	/* ---- title: one lockup, the tag stamped onto the end of it ---- */

	.ttb-title {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 0.14em 0.2em;
		margin: 0;
		max-width: 16ch;
		font: 700 clamp(40px, 11.5cqi, 60px) / 0.98 var(--ttb-display);
		letter-spacing: -0.035em;
		text-transform: uppercase;
		text-wrap: balance;
		overflow-wrap: anywhere;
	}

	.ttb-tag {
		display: inline-block;
		padding: 0.1em 0.26em 0.06em;
		border: 2px solid transparent;
		border-radius: 4px;
		background: var(--ttb-accent);
		color: var(--ttb-navy);
		font-size: 0.62em;
		line-height: 1;
		letter-spacing: -0.02em;
		white-space: nowrap;
	}

	/* ---- photo ---- */

	.ttb-media {
		position: relative;
		min-height: 168px;
		border-top: var(--ttb-seam) solid var(--ttb-accent);
	}

	.ttb-media img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		object-position: 70% center;
	}

	/* A light navy grade so a busy photo sits in the palette instead of fighting it. */
	.ttb-media::after {
		content: "";
		position: absolute;
		inset: 0;
		background: linear-gradient(90deg, rgb(11 70 84 / 0.45), rgb(11 70 84 / 0.12) 55%, rgb(11 70 84 / 0.05));
	}

	/* ---- tablet and up: side by side, the seam runs top to bottom ---- */

	@container (min-width: 700px) {
		.ttb[data-media] .ttb-grid {
			grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr);
		}

		.ttb-inner {
			gap: 22px;
			padding: 150px 40px 56px;
		}

		.ttb-title {
			max-width: 14ch;
			font-size: clamp(52px, 8.4cqi, 104px);
		}

		.ttb:not([data-media]) .ttb-title {
			max-width: 20ch;
		}

		.ttb-media {
			min-height: 0;
			border-top: 0;
			border-left: var(--ttb-seam) solid var(--ttb-accent);
		}
	}

	@container (min-width: 1100px) {
		.ttb-inner {
			padding: 196px max(var(--ttb-gutter), calc((100cqi - var(--ttb-max)) / 2 + var(--ttb-gutter))) 72px;
		}

		.ttb[data-media] .ttb-grid {
			grid-template-columns: minmax(0, 1fr) minmax(0, 0.78fr);
		}
	}

	/* ---- motion: rises in, ends at rest ---- */

	@keyframes ttb-rise {
		from {
			opacity: 0;
			transform: translateY(var(--ttb-from, 18px));
		}
	}

	.ttb[data-animate] .ttb-title {
		animation: ttb-rise 0.7s var(--ttb-ease) both;
	}

	.ttb[data-animate] .ttb-crumbs {
		--ttb-from: 10px;
		animation: ttb-rise 0.6s var(--ttb-ease) 0.12s both;
	}

	@media (prefers-reduced-motion: reduce) {
		.ttb[data-animate] .ttb-title,
		.ttb[data-animate] .ttb-crumbs {
			animation: none;
		}

		.ttb-crumbs a {
			transition: none;
		}
	}

	@media (forced-colors: active) {
		.ttb {
			border-bottom-color: CanvasText;
		}

		.ttb-media,
		.ttb-tag {
			border-color: CanvasText;
		}
	}
</style>

===== END src/components/TagTitleBanner.astro =====

===== FILE (supporting): src/components/TagTitleBanner.md =====
# Tag title banner

An inner-page banner built as a split: the breadcrumb and a heavy uppercase
title with a stamped tag on a navy field, and — when a photo is given — a
full-height photo panel meeting it at an orange seam. Below 700px of its own
width the photo becomes a strip that closes the banner. An orange rule always
closes the bottom edge.
The same component serves every inner page — change `title`, `tag` and
`breadcrumbs`.

Catalog page: `/components/tag-title-banner`

## Files required

- **`TagTitleBanner.astro`** — the whole component. No script.
- `public/tag-title-banner/port.webp` — optional; the catalog demo passes it
  as `background`.
- `TagTitleBanner.md` — this file.

## Props

| Prop | Type | Default | What it does |
| :--- | :--- | :--- | :--- |
| `title` | `string?` | `""` | Required in practice: with no title the banner renders nothing. |
| `tag` | `string?` | `""` | The stamped orange tag after the title (navy text). Empty drops it. |
| `breadcrumbs` | `{ label, href? }[]` | `[]` | Last crumb is the current page. Empty drops the trail; a crumb without `label` is dropped. |
| `background` | `{ src? }?` | none | The photo panel. No `src` → the navy field alone, one column. |
| `animate` | `boolean?` | `true` | |
| `fontStylesheet`, `class`, `id` | | | |

## Behaviour (measured)

- Layout follows the banner's own width (container queries): split from
  700px, photo strip below it.
- Breadcrumb above the title, sentence case, "/" separators; links 74% white
  → white with an underline on hover, each at least 24px tall. The current
  crumb is white and bold (orange on navy failed contrast).
- Title rises 18px and fades in on load; the breadcrumb follows 0.12s later.
  CSS animations; off under reduced motion.
- Forced colours: the seam, closing rule and tag keep a visible border.

## Images and credits

| File | Size | Credit |
| :--- | :--- | :--- |
| `port.webp` | 1920 × 600 | Unsplash QzqpPPpWP6I, Unsplash License |

## Approximations

The reference banner photo carries the reference company's name on a
container; the stock port photo replaces it.

===== END src/components/TagTitleBanner.md =====

===== FILE (required): public/tag-title-banner/port.webp =====
[binary asset — download https://astro.baysixmedia.com/tag-title-banner/port.webp and save it to public/tag-title-banner/port.webp]

--- VERIFIED IN THE COMPONENT LIBRARY ---
Enrolled for verification but never run.
No verification run has been recorded.
No checks have passed yet.
No usable source fingerprint, so these results cannot be tied to the files below.

--- NOT PROVEN ---
- ClientRouter: not applicable — this component ships no script.

--- WHAT THIS DOES NOT CERTIFY ---
Verification was performed on the unmodified component, in an isolated fixture, in the
library. It says nothing about this project's CSS, routes, layout or data, and nothing
about the component once you adapt it. A verified component is a good starting point,
not a guarantee about the installation you are about to build.

--- TEST IN THIS PROJECT AFTER INSTALLING OR CUSTOMISING ---
- Horizontal overflow at 1440, 1280, 1024, 834, 390 and 320px.
- Keyboard operation end to end, including visible focus.
- The no-JavaScript render.
- prefers-reduced-motion: reduce.
- Two instances on one page, if this project renders more than one.
- If this project uses <ClientRouter />: teardown and reinitialisation across a real navigation.

Component reference

A fragment for a request you write yourself, e.g. “I want to add [paste] to Section 3 of my homepage.” It names the component, links its page, and fixes what must not change — the design build and its effects — while leaving branding and content open. It does not carry the code.

Read it first
“Tag title banner” from my Astro Component Library:
https://astro.baysixmedia.com/components/tag-title-banner/

Use the existing library component as the implementation source. Preserve its design structure, layout, proportions, spacing system, responsive behavior, visual effects, animations, transitions, hover states, interactions, and accessibility.

The copy, colors, typography, images, and other content may be adapted to match the destination website. Do not redesign, simplify, or reinterpret the component’s underlying design build or effects.

Component readiness

Judged on recorded evidence, not on how it looks in the frame above. A description of a component is not a result.

Interactivity
Static
Profile
core only
Installation files
2 required + 1 supporting
Verified
Never
Client navigation
Not applicable — ships no script
Source fingerprint
No fingerprint recorded
Production ready
Not yet

Not yet verified

Enrolled for verification, but never run. Silence is reported as silence rather than assumed to be fine.

Open the verification fixture

src/components/library/TagTitleBanner.astro

This component is not one file on its own

  • assetsCopy these across too — they are referenced by URL, so nothing in the source above points at them: public/tag-title-banner/port.webp. Leave them behind and those URLs resolve to nothing on the other end. What each component does without them is in its README.
---
/**
 * TagTitleBanner
 *
 * An inner-page banner built as a split: the breadcrumb and a heavy
 * uppercase title with a stamped tag on a navy field, and — when a photo is
 * given — a full-height photo panel meeting it at an accent seam. Below
 * 700px of its own width the photo becomes a strip that closes the banner.
 * Leaves room at the top for a fixed pill header.
 *
 * Sizes follow the component's own width (container queries), so it holds
 * the same composition in a sidebar layout or a narrow column. The title
 * rises in on load; the breadcrumb follows. Both end at rest and are off
 * under reduced motion.
 *
 * Reads the --tw-* tokens from any ancestor, with fallbacks.
 */

export interface TagTitleCrumb {
	label: string;
	/** Omit on the last crumb, the current page. */
	href?: string;
}

export interface TagTitleBannerProps {
	title?: string;
	/** The orange box after the title. `""` drops it. */
	tag?: string;
	breadcrumbs?: TagTitleCrumb[];
	/** Background photo. `src: ""` renders the navy band alone. */
	background?: { src?: string };
	animate?: boolean;
	fontStylesheet?: string;
	class?: string;
	id?: string;
}

interface Props extends TagTitleBannerProps {}

const {
	title = "",
	tag = "",
	breadcrumbs: rawCrumbs = [],
	background: bgProp,
	animate = true,
	fontStylesheet = "https://fonts.googleapis.com/css2?family=Outfit:wght@500;600;700;800;900&family=Noto+Sans:wght@400;500;600;700&family=Inter:wght@500;600;700&display=swap",
	class: className,
	id,
} = Astro.props;

/* No photo by default: the navy band renders alone. No title, no banner. */
const background = { src: "", ...(bgProp ?? {}) };
const breadcrumbs = rawCrumbs.filter((c) => c?.label);
const SAFE = /^(?:https?:|mailto:|tel:|[#/.?])/i;
const safeHref = (href: string) => (SAFE.test(href.trim()) ? href.trim() : "#");
---

{title && (
<>
{fontStylesheet && <link rel="stylesheet" href={fontStylesheet} />}
<section class:list={["ttb", className]} id={id} data-animate={animate ? "" : undefined} data-media={background.src ? "" : undefined}>
	<div class="ttb-grid">
	<div class="ttb-inner">
		{
			breadcrumbs.length > 0 && (
				<nav class="ttb-crumbs" aria-label="Breadcrumb">
					<ol>
						{breadcrumbs.map((c, i) => (
							<li>
								{c.href && i < breadcrumbs.length - 1 ? (
									<a href={safeHref(c.href)}>{c.label}</a>
								) : (
									<span aria-current={i === breadcrumbs.length - 1 ? "page" : undefined}>{c.label}</span>
								)}
							</li>
						))}
					</ol>
				</nav>
			)
		}
		<h1 class="ttb-title">
			<span class="ttb-word">{title}</span>
			{tag && <span class="ttb-tag">{tag}</span>}
		</h1>
	</div>
	{
		background.src && (
			<div class="ttb-media" aria-hidden="true">
				<img src={background.src} alt="" width="1920" height="600" fetchpriority="high" decoding="async" />
			</div>
		)
	}
	</div>
</section>
</>
)}

<style>
	.ttb {
		--ttb-navy: var(--tw-navy, #0b4654);
		--ttb-accent: var(--tw-accent, #ff6d45);
		--ttb-display: var(--tw-display, Outfit, ui-sans-serif, system-ui, sans-serif);
		--ttb-body: var(--tw-body, "Noto Sans", ui-sans-serif, system-ui, sans-serif);
		--ttb-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
		--ttb-seam: 6px;

		container-type: inline-size;
		position: relative;
		isolation: isolate;
		overflow: hidden;
		background: var(--ttb-navy);
		color: #fff;
		font-family: var(--ttb-body);
		/* The closing edge: the banner ends on a line, never on open colour. */
		border-bottom: var(--ttb-seam) solid var(--ttb-accent);
	}

	.ttb *,
	.ttb *::before,
	.ttb *::after {
		box-sizing: border-box;
	}

	.ttb-grid {
		display: grid;
	}

	/* Step 39.2: --tw-grid-max / --tw-grid-gutter put the title on a site grid; the fallbacks are the original 1440 / 64. */
	.ttb-inner {
		--ttb-max: var(--tw-grid-max, 1440px);
		--ttb-gutter: var(--tw-grid-gutter, 64px);
	}

	.ttb-inner {
		display: flex;
		flex-direction: column;
		justify-content: flex-end;
		gap: 18px;
		min-width: 0;
		padding: 124px 20px 40px;
	}

	/* ---- breadcrumb: wayfinding first, above the title ---- */

	.ttb-crumbs ol {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 0 2px;
		margin: 0;
		padding: 0;
		list-style: none;
		font: 500 15px/1.4 var(--ttb-body);
	}

	.ttb-crumbs li {
		display: flex;
		align-items: center;
		min-width: 0;
	}

	.ttb-crumbs li + li::before {
		content: "/";
		margin: 0 8px 0 6px;
		color: rgb(255 255 255 / 0.4);
	}

	.ttb-crumbs a,
	.ttb-crumbs span {
		display: inline-block;
		padding: 5px 0;
		overflow-wrap: anywhere;
	}

	.ttb-crumbs a {
		color: rgb(255 255 255 / 0.74);
		text-decoration: underline;
		text-decoration-color: rgb(255 255 255 / 0);
		text-underline-offset: 4px;
		transition: color 0.2s var(--ttb-ease), text-decoration-color 0.2s var(--ttb-ease);
	}

	.ttb-crumbs a:hover {
		color: #fff;
		text-decoration-color: rgb(255 255 255 / 0.6);
	}

	.ttb-crumbs a:focus-visible {
		outline: 2px solid #fff;
		outline-offset: 2px;
		border-radius: 2px;
	}

	.ttb-crumbs [aria-current] {
		color: #fff;
		font-weight: 600;
	}

	/* ---- title: one lockup, the tag stamped onto the end of it ---- */

	.ttb-title {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 0.14em 0.2em;
		margin: 0;
		max-width: 16ch;
		font: 700 clamp(40px, 11.5cqi, 60px) / 0.98 var(--ttb-display);
		letter-spacing: -0.035em;
		text-transform: uppercase;
		text-wrap: balance;
		overflow-wrap: anywhere;
	}

	.ttb-tag {
		display: inline-block;
		padding: 0.1em 0.26em 0.06em;
		border: 2px solid transparent;
		border-radius: 4px;
		background: var(--ttb-accent);
		color: var(--ttb-navy);
		font-size: 0.62em;
		line-height: 1;
		letter-spacing: -0.02em;
		white-space: nowrap;
	}

	/* ---- photo ---- */

	.ttb-media {
		position: relative;
		min-height: 168px;
		border-top: var(--ttb-seam) solid var(--ttb-accent);
	}

	.ttb-media img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		object-position: 70% center;
	}

	/* A light navy grade so a busy photo sits in the palette instead of fighting it. */
	.ttb-media::after {
		content: "";
		position: absolute;
		inset: 0;
		background: linear-gradient(90deg, rgb(11 70 84 / 0.45), rgb(11 70 84 / 0.12) 55%, rgb(11 70 84 / 0.05));
	}

	/* ---- tablet and up: side by side, the seam runs top to bottom ---- */

	@container (min-width: 700px) {
		.ttb[data-media] .ttb-grid {
			grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr);
		}

		.ttb-inner {
			gap: 22px;
			padding: 150px 40px 56px;
		}

		.ttb-title {
			max-width: 14ch;
			font-size: clamp(52px, 8.4cqi, 104px);
		}

		.ttb:not([data-media]) .ttb-title {
			max-width: 20ch;
		}

		.ttb-media {
			min-height: 0;
			border-top: 0;
			border-left: var(--ttb-seam) solid var(--ttb-accent);
		}
	}

	@container (min-width: 1100px) {
		.ttb-inner {
			padding: 196px max(var(--ttb-gutter), calc((100cqi - var(--ttb-max)) / 2 + var(--ttb-gutter))) 72px;
		}

		.ttb[data-media] .ttb-grid {
			grid-template-columns: minmax(0, 1fr) minmax(0, 0.78fr);
		}
	}

	/* ---- motion: rises in, ends at rest ---- */

	@keyframes ttb-rise {
		from {
			opacity: 0;
			transform: translateY(var(--ttb-from, 18px));
		}
	}

	.ttb[data-animate] .ttb-title {
		animation: ttb-rise 0.7s var(--ttb-ease) both;
	}

	.ttb[data-animate] .ttb-crumbs {
		--ttb-from: 10px;
		animation: ttb-rise 0.6s var(--ttb-ease) 0.12s both;
	}

	@media (prefers-reduced-motion: reduce) {
		.ttb[data-animate] .ttb-title,
		.ttb[data-animate] .ttb-crumbs {
			animation: none;
		}

		.ttb-crumbs a {
			transition: none;
		}
	}

	@media (forced-colors: active) {
		.ttb {
			border-bottom-color: CanvasText;
		}

		.ttb-media,
		.ttb-tag {
			border-color: CanvasText;
		}
	}
</style>