/* ===========================================================================
   TURBO (DAC) — stylesheet
   ===========================================================================

   Ported from the SvelteKit build (github.com/anshb-afk/dac-instant-search).
   That version leaned on Tailwind v4 for layout utilities and on Svelte's
   scoped styles; neither exists here, so every rule below is written out in
   full and every class is namespaced `tb-`. There is no build step: this file
   is what the browser gets.

   The TOKENS block is the exception. It is GENERATED, captured from the live
   MetaSearch stylesheet so the two products cannot drift apart, and is copied
   across verbatim apart from the `@theme` wrapper, which was a Tailwind
   directive and is a plain `:root` here. To change a colour, change it in
   MetaSearch and re-capture — do not edit it here.
   =========================================================================== */


/* ---------------------------------------------------------------------------
   TOKENS — generated from the computed :root of metasearch.namify.tech.
   Dark is the default palette, matching MetaSearch.
   --------------------------------------------------------------------------- */

:root {
	--font-sans: "Inter", "Inter Fallback", -apple-system, sans-serif;
	--font-mono: "JetBrains Mono", "JetBrains Mono Fallback", monospace;
	--font-weight-light: 300;
	--font-weight-normal: 400;
	--font-weight-medium: 500;
	--font-weight-semibold: 600;
	--font-weight-bold: 700;
	--tracking-tight: -0.025em;
	--tracking-wide: 0.025em;
	--leading-relaxed: 1.625;
	--radius-sm: 4px;
	--radius-md: 6px;
	--radius-cta: 10px;
	--radius-lg: 12px;
	--radius-unit: 20px;
	--ease-out: cubic-bezier(0, 0, .2, 1);

	/* Dark is the default palette, matching MetaSearch. */
	--btn-face: #353940;
	--btn-face-hover: #454b54;
	--card-shadow: inset 0 0 50px rgba(255,255,255,.02), 0 8px 24px -6px rgba(0,0,0,.7), 0 2px 6px -2px rgba(0,0,0,.5);
	--color-accent-blue: #83b9f7;
	--color-accent-blue-edge: #83b9f74d;
	--color-accent-blue-graphic: #83b9f7;
	--color-accent-blue-ink: #83b9f7;
	--color-accent-blue-tint: #83b9f71a;
	--color-accent-coral: #f79e83;
	--color-accent-coral-graphic: #f79e83;
	--color-accent-coral-ink: #f79e83;
	--color-accent-coral-tint: #f79e831a;
	--color-accent-green: #83f891;
	--color-accent-green-900: #83f8911a;
	--color-accent-green-edge: #83f8914d;
	--color-accent-green-graphic: #83f891;
	--color-accent-green-ink: #83f891;
	--color-accent-green-strong: #83f891;
	--color-accent-green-tint: #83f8911a;
	--color-accent-green-tint-hover: #83f89133;
	--color-accent-purple: #d383f7;
	--color-accent-purple-edge: #d383f74d;
	--color-accent-purple-graphic: #d383f7;
	--color-accent-purple-ink: #d383f7;
	--color-accent-purple-strong: #d383f7;
	--color-accent-purple-tint: #d383f714;
	--color-accent-purple-tint-hover: #d383f72e;
	--color-card: #0a0a0a;
	--color-code-key: #83b9f7;
	--color-code-literal: #f9fafb;
	--color-code-punct: #898e8e;
	--color-code-string: #83f891;
	--color-elevated: #1a1a1a;
	--color-emphasis: #83f891;
	--color-name-muted: #737373;
	--color-on-accent: #080808;
	--color-page: #080808;
	--color-pane: #1d1d1d;
	--color-placeholder: #414141;
	--color-scrim: #080808b3;
	--color-stroke-default: #232528;
	--color-stroke-strong: #353940;
	--color-stroke-subtle: #171717;
	--color-text-primary: #f9fafb;
	--color-text-secondary: #737373;
	--color-text-tertiary: #4d4d4d;
	--cta-hover: #f9fafb;
	--cta-hover-ink: #080808;
	--elevation-float: 0 8px 24px -6px #000000b3, 0 2px 6px -2px #00000080;
	--elevation-pop: 0 12px 32px -8px #000c, 0 3px 8px -3px #0009;
	--hero-edge: #83f89147;
	--pane-divider: #232528;
	--pane-inner: #ffffff05;
	--pane-ring: #2c2f3685;
	--pane-ring-active: rgb(from color-mix(in srgb, #83f891 55%, #f9fafb) r g b / .28);
	--track-face: #080808;
	--track-hover: #1a1a1a;

	/* Aliases so Tailwind can emit bg-/border- utilities. NAMES are DAC-local;
	VALUES are MetaSearch's, by reference, so they follow the theme. */
	--color-surface: var(--pane-inner);
	--color-surface-ring: var(--pane-ring);

	/* DAC-only: fixed-height result slots so results stream in without shifting. */
	--radius-pill: 999px;
	--spacing-row: 44px;
	--spacing-pick: 92px;

	/*
	 * Dark is the default, so say so to the browser as well as to the page:
	 * this is what paints the scrollbar, the text caret and any native control
	 * dark. Without it they stay light on an otherwise black page.
	 */
	color-scheme: dark;
}


/*
 * Light. Applied either because the OS asks for it and nothing has been pinned,
 * or because the toggle pinned it. The two selectors carry the same values, so
 * they are written once.
 */
/*
 * DARK IS THE DEFAULT, and it does not follow the OS.
 *
 * There used to be a `@media (prefers-color-scheme: light)` block here that
 * handed the page to a light-mode machine whenever nothing had been pinned.
 * It is gone on purpose: the demo opens dark for everyone, and light is now
 * reachable only by choosing it with the toggle, which pins `[data-theme]`.
 *
 * The explicit `:root[data-theme='light']` rules below are what light mode is
 * now made of. They carried the same declarations as the media block did, so
 * nothing was lost with it — only the OS's say in the matter.
 */
:root[data-theme='light'] {
	--btn-face: #e7e8e9;
	--btn-face-hover: #d9dde0;
	--card-shadow: inset 0 0 50px rgba(8,8,8,.03), 0 1px 2px rgba(8,8,8,.05), 0 2px 8px -4px rgba(8,8,8,.08);
	--color-accent-blue: #83b9f7;
	--color-accent-blue-edge: #83b9f7d9;
	--color-accent-blue-graphic: #0c5dba;
	--color-accent-blue-ink: #080808;
	--color-accent-blue-tint: #83b9f766;
	--color-accent-coral: #f79e83;
	--color-accent-coral-graphic: #a3390a;
	--color-accent-coral-ink: #080808;
	--color-accent-coral-tint: #f79e8366;
	--color-accent-green: #83f891;
	--color-accent-green-900: #83f8912e;
	--color-accent-green-edge: #83f891e6;
	--color-accent-green-graphic: #83f891;
	--color-accent-green-ink: #080808;
	--color-accent-green-strong: #0c1f0e;
	--color-accent-green-tint: #83f89133;
	--color-accent-green-tint-hover: #83f89159;
	--color-accent-purple: #d383f7;
	--color-accent-purple-edge: #d383f7bf;
	--color-accent-purple-graphic: #d383f7;
	--color-accent-purple-ink: #080808;
	--color-accent-purple-strong: #1f0f26;
	--color-accent-purple-tint: #d383f733;
	--color-accent-purple-tint-hover: #d383f759;
	--color-card: #fff;
	--color-code-key: #1a56db;
	--color-code-literal: #080808;
	--color-code-punct: #5f6464;
	--color-code-string: #096e35;
	--color-elevated: #e7e8e9;
	--color-emphasis: #83f891;
	--color-name-muted: #6b6b6b;
	--color-on-accent: #080808;
	--color-page: #f7f8f9;
	--color-pane: #fff;
	--color-placeholder: #b0b0b0;
	--color-scrim: #080808b3;
	--color-stroke-default: #d9dde0;
	--color-stroke-strong: #c1c9ce;
	--color-stroke-subtle: #eaebec;
	--color-text-primary: #1a1a1a;
	--color-text-secondary: #1a1a1a;
	--color-text-tertiary: #353535;
	--cta-hover: #080808;
	--cta-hover-ink: #f7f8f9;
	--elevation-float: 0 1px 2px 0 #0808080d, 0 2px 8px -4px #08080814;
	--elevation-pop: 0 2px 6px -3px #08080814, 0 12px 30px -12px #08080829;
	--hero-edge: #0a7c3d47;
	--pane-divider: #ecedee;
	--pane-inner: #08080808;
	--pane-ring: #d9dde0e6;
	--pane-ring-active: rgb(from color-mix(in srgb, #83f891 55%, #080808) r g b / .28);
	--track-face: #e7e8e9;
	--track-hover: #fff;
	color-scheme: light;
}

:root[data-theme='dark'] {
	color-scheme: dark;
}


/* ---------------------------------------------------------------------------
   PAGE
   --------------------------------------------------------------------------- */

:root {
	/*
	 * The page gutter, and every cell's horizontal padding.
	 *
	 * It has to be ONE value. When the page used a wide gutter and the cells a
	 * narrow one, the only way to line the wall's text up with the name above it
	 * was to pad the edge cells and not the rest — which meant no two cells had
	 * the same internal proportions, and the grid stopped reading as a grid. With
	 * a single value the wall still bleeds to the window, every cell is identical,
	 * and the first column lands on the page's line for free.
	 */
	--tb-gutter: clamp(16px, 2.2vw, 40px);

	/*
	 * Everything stops here and the rest of the window is left as space either
	 * side. Without it an ultra-wide monitor simply stretched the boxes: the
	 * layout did not break, it just got emptier the wider the screen went.
	 */
	--tb-max-w: 1600px;
}

html.tb {
	background: var(--color-page);
}

html.tb body {
	margin: 0;
	background: var(--color-page);
	color: var(--color-text-primary);
	font-family: var(--font-sans);
	min-height: 100vh;
	-webkit-font-smoothing: antialiased;
	transition:
		background-color 0.16s ease,
		color 0.16s ease;
}

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

/*
 * `hidden` has to win. The browser's own `[hidden] { display: none }` is a
 * low-specificity UA rule, so any class here that sets `display` — and most of
 * the layout ones do — silently outranks it and the element stays on screen.
 * Every show/hide in app.js goes through the property, so this is load-bearing.
 */
html.tb [hidden] {
	display: none !important;
}

/* Buttons inherit nothing useful by default and every control here is one. */
html.tb button {
	font: inherit;
	color: inherit;
	margin: 0;
}

.tb-page {
	/* Full-bleed on purpose: the wall runs edge to edge. */
	padding-bottom: 64px;
}

/*
 * The idle screen is exactly one viewport and never scrolls. It is a flex
 * column so the field simply takes whatever height is left after the line
 * above it, rather than the field subtracting a guessed constant — that
 * constant is wrong the moment the line wraps to two. 65px, not 64: the
 * header's hairline bottom rule counts.
 */
.tb-page.is-idle {
	min-height: calc(100vh - 65px);
	display: flex;
	flex-direction: column;
	padding-bottom: 0;
}

.tb-type {
	max-width: var(--tb-max-w);
	margin-inline: auto;
	padding: 40px var(--tb-gutter) 28px;
}

/* Idle centres the name block in what is left of the viewport. */
.tb-page.is-idle .tb-type {
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding-bottom: 96px;
}

/*
 * Anchored under the nav with air above it, rather than riding up and down with
 * the vertically centred field. It opens with the instruction: naming the count
 * first described the demo without saying what to do with it. One quiet line
 * only, so it never becomes a lede that delays the field.
 */
.tb-hint {
	/* Left-aligned on the page's own line, not centred: it is a caption to the
	   field below it, and the field starts at the gutter. */
	margin: 0;
	padding: 56px var(--tb-gutter) 0;
	max-width: 62ch;
	font-size: 13.5px;
	line-height: 1.5;
	color: var(--color-text-tertiary);
}

.tb-chips {
	margin-top: 24px;
	display: flex;
}

/* The meta strip sits between the name and the wall. */
.tb-bar {
	max-width: var(--tb-max-w);
	margin-inline: auto;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 12px 20px;
	padding: 0 var(--tb-gutter) 20px;
}

.tb-inset {
	max-width: var(--tb-max-w);
	margin-inline: auto;
	padding: 0 var(--tb-gutter);
}

/*
 * Phones do not get the centred treatment. Centring the field leaves the line
 * stranded at the top with a void between them, and the two read as unrelated
 * fragments; stacked from the top they read as one thought.
 */
@media (max-width: 760px) {
	/*
	 * The line and the field are centred TOGETHER as one block. Pinning the line
	 * to the top and centring the field left a void between them; stacking both
	 * at the top left the void underneath instead.
	 */
	.tb-page.is-idle {
		justify-content: center;
	}
	.tb-hint {
		padding: 0 var(--tb-gutter);
	}
	/* The tagline always lands on its own line rather than wherever the sentence
	   happens to break at this width. */
	.tb-hint .tb-tagline {
		display: block;
	}
	/* Room to breathe between the line and the field, which sat too close once
	   the two were centred together. */
	.tb-page.is-idle .tb-type {
		flex: none;
		padding: 40px var(--tb-gutter) 0;
	}
	/* Filters on their own row, the readout and the button stacked in the corner
	   beneath them. */
	.tb-bar {
		flex-direction: column;
		align-items: stretch;
		padding: 0 var(--tb-gutter) 16px;
	}
}


/* ---------------------------------------------------------------------------
   HEADER + BRAND
   --------------------------------------------------------------------------- */

/*
 * 65px tall with a hairline bottom rule. Full-bleed rather than a centred
 * container, so its gutter lines up with the edge-to-edge wall below.
 *
 * No concept switcher: each prototype is its own URL, opened cold. A tab bar
 * would frame them as views of one product, and they are meant to be judged
 * separately.
 */
.tb-header {
	position: sticky;
	top: 0;
	z-index: 30;
	border-bottom: 1px solid var(--color-stroke-subtle);
	background: var(--color-page);
}

.tb-head {
	max-width: var(--tb-max-w);
	margin-inline: auto;
	padding-inline: var(--tb-gutter);
	display: flex;
	height: 64px;
	align-items: center;
	gap: 12px;
}

.tb-head-right {
	margin-left: auto;
	display: flex;
	flex-shrink: 0;
	align-items: center;
	gap: 12px;
}

/* Header lockup, matching MetaSearch exactly: the Namify API mark, a 1px
   divider, then the product label. */
.tb-brand {
	display: flex;
	flex-shrink: 0;
	align-items: center;
	gap: 12px;
	text-decoration: none;
}

/* MetaSearch renders the mark at 130x25. */
.tb-logo {
	flex-shrink: 0;
	width: 130px;
	height: 25px;
	display: block;
}

.tb-brand-divider {
	height: 18px;
	width: 1px;
	flex-shrink: 0;
	background: var(--color-stroke-default);
}

/* Dark is the default theme, so the light mark is hidden unless light wins. */
.tb-logo--light {
	display: none;
}

:root[data-theme='light'] .tb-logo--dark {
	display: none;
}
:root[data-theme='light'] .tb-logo--light {
	display: block;
}

:root[data-theme='dark'] .tb-logo--dark {
	display: block;
}
:root[data-theme='dark'] .tb-logo--light {
	display: none;
}


/* ---------------------------------------------------------------------------
   TURBO MARK — a circular gauge badge, then the wordmark.

   Square, not a wide rect: a 270-degree ring is a circular form, and a circle
   in a wide box leaves dead space at both ends. Sized to the API badge's HEIGHT
   so the two line up as a pair, with the same radius, gradient and rim so it
   reads as the same family rather than a different sticker.

   The needle sweeps and the ring fills whenever the search counter changes, so
   the gauge answers each search rather than looping.
   --------------------------------------------------------------------------- */

.tb-mark {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	line-height: 1;
}

/*
 * 22.25px, which is what the API badge beside it actually measures: its path is
 * 17.8 units tall in a 104x20 viewBox rendered at 130px, so 1.25x. It had been
 * set to 20 by eye and sat visibly short.
 */
.tb-gauge {
	width: 22.25px;
	height: 22.25px;
	display: block;
	flex: none;
}

/*
 * The ring fills by dash offset as the needle travels, so the colour arrives
 * with the movement instead of being there from the start. 23.6 is the length
 * of a 270-degree arc at r=5.
 */
.tb-sweep {
	stroke-dasharray: 23.6;
	stroke-dashoffset: 23.6;
	animation: tb-fill 1.15s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}

/*
 * The dial runs from bottom-left to bottom-right the long way round, so empty
 * is -135deg from vertical and full is +135deg.
 */
.tb-needle {
	transform-origin: 10px 10px;
	animation: tb-sweep 1.15s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes tb-sweep {
	0% {
		transform: rotate(-135deg);
	}
	58% {
		transform: rotate(96deg);
	}
	78% {
		transform: rotate(66deg);
	}
	100% {
		transform: rotate(78deg);
	}
}
@keyframes tb-fill {
	0% {
		stroke-dashoffset: 23.6;
	}
	100% {
		stroke-dashoffset: 6;
	}
}

/*
 * A second name for the same movement: a browser replays an animation when its
 * name changes, but not when the same one is reapplied. The JS swaps between
 * the two names to re-run the sweep on each search; hover uses the same trick.
 */
.tb-mark:hover .tb-needle,
.tb-needle.is-alt {
	animation: tb-sweep-again 1.15s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.tb-mark:hover .tb-sweep,
.tb-sweep.is-alt {
	animation: tb-fill-again 1.15s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
@keyframes tb-sweep-again {
	0% {
		transform: rotate(-135deg);
	}
	58% {
		transform: rotate(96deg);
	}
	78% {
		transform: rotate(66deg);
	}
	100% {
		transform: rotate(78deg);
	}
}
@keyframes tb-fill-again {
	0% {
		stroke-dashoffset: 23.6;
	}
	100% {
		stroke-dashoffset: 6;
	}
}

/* Caps and tracking, so it carries beside the badge at a small size. */
.tb-word {
	font-family: var(--font-sans);
	font-size: 11.5px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.11em;
	color: var(--color-text-primary);
}

@media (prefers-reduced-motion: reduce) {
	.tb-needle,
	.tb-sweep,
	.tb-mark:hover .tb-needle,
	.tb-mark:hover .tb-sweep {
		animation: none;
	}
	.tb-needle {
		transform: rotate(78deg);
	}
	.tb-sweep {
		stroke-dashoffset: 6;
	}
}


/* ---------------------------------------------------------------------------
   THEME TOGGLE — MetaSearch's `.theme-swap` rules verbatim. Both icons occupy
   the same grid cell and cross-fade with a scale+rotate, rather than one
   swapping out for the other.
   --------------------------------------------------------------------------- */

.tb-theme-swap {
	display: grid;
	place-items: center;
	width: 32px;
	height: 32px;
	flex-shrink: 0;
	border: 0;
	border-radius: 9999px;
	padding: 0;
	cursor: pointer;
	background-color: var(--color-elevated);
	color: var(--color-text-secondary);
	transition:
		background-color 0.16s,
		color 0.16s;
}

.tb-theme-swap:hover {
	color: var(--color-text-primary);
}

.tb-theme-icon {
	grid-area: 1 / 1;
	width: 16px;
	height: 16px;
	transform-origin: center;
	transition:
		opacity 0.5s,
		transform 0.5s;
}

/* Default (dark): moon visible, sun tucked away. */
.tb-theme-icon--light {
	opacity: 0;
	transform: scale(0.85) rotate(30deg);
}
.tb-theme-icon--dark {
	opacity: 1;
	transform: none;
}

:root[data-theme='light'] .tb-theme-icon--light {
	opacity: 1;
	transform: none;
}
:root[data-theme='light'] .tb-theme-icon--dark {
	opacity: 0;
	transform: scale(0.85) rotate(30deg);
}

@media (prefers-reduced-motion: reduce) {
	.tb-theme-icon {
		transition: none;
	}
}


/* ---------------------------------------------------------------------------
   TYPEWALL — the name you type IS the interface.

   A real <input> styled at display scale with no box, so it keeps the mobile
   keyboard, selection and a11y while looking like nothing but type. Typing
   anywhere on the page routes here, so the missing box never leaves you
   wondering where to start.
   --------------------------------------------------------------------------- */

.tb-tw {
	width: 100%;
}

.tb-stack {
	position: relative;
}

.tb-input,
.tb-ghost {
	font-family: var(--font-sans);
	font-weight: 700;
	letter-spacing: -0.045em;
	/* Leading and padding together stop descenders clipping at display scale. */
	line-height: 1.16;
	padding-block: 0.04em;
	font-size: clamp(52px, 13vw, 176px);
}

.tb-input {
	width: 100%;
	display: block;
	background: none;
	border: 0;
	padding-inline: 0;
	outline: none;
	height: auto;
	color: var(--color-text-primary);
	caret-color: var(--color-emphasis);
	transition: font-size 0.42s cubic-bezier(0.22, 1, 0.36, 1);
}

/*
 * While the ghost is typing there were two carets: the browser's own thin one
 * sitting in the empty field, and the ghost's block caret after the suggested
 * text. The real one is hidden until there is something to type a caret against.
 */
.tb-tw.is-ghosting .tb-input {
	caret-color: transparent;
}

/* Once results are up the name yields height to the wall below it. */
.tb-tw.is-compact .tb-input,
.tb-tw.is-compact .tb-ghost {
	font-size: clamp(40px, 7.5vw, 104px);
}

.tb-ghost {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	pointer-events: none;
	/* Brand placeholder grey, the same token MetaSearch's search field uses. */
	color: var(--color-placeholder);
	white-space: nowrap;
	overflow: hidden;
}

/* A block caret rather than the hairline default, so the empty state reads as
   something alive rather than an unlabelled gap. */
.tb-caret {
	display: inline-block;
	width: 0.07em;
	min-width: 4px;
	height: 0.74em;
	margin-left: 0.04em;
	background: var(--color-emphasis);
	animation: tb-blink 1.05s steps(1, end) infinite;
}

@keyframes tb-blink {
	50% {
		opacity: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.tb-input {
		transition: none;
	}
	.tb-caret {
		animation: none;
	}
}


/* ---------------------------------------------------------------------------
   EXAMPLE CHIPS — a hint, not furniture.

   Five chips sitting permanently under the field competed with the one thing
   the empty state is asking you to do, so they start collapsed behind a single
   line and open on hover — or on click and keyboard focus, which is what makes
   them reachable without a pointer.
   --------------------------------------------------------------------------- */

.tb-examples {
	display: flex;
	align-items: center;
	gap: 10px;
	min-height: 34px;
}

.tb-trigger {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	flex: none;
	padding: 0;
	background: none;
	border: 0;
	font-size: 13px;
	color: var(--color-text-tertiary);
	cursor: pointer;
	transition: color 0.16s ease;
}
.tb-examples.is-open .tb-trigger,
.tb-trigger:hover {
	color: var(--color-text-primary);
}

.tb-dot {
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--color-emphasis);
	transition: transform 0.24s cubic-bezier(0.22, 1, 0.36, 1);
}
.tb-examples.is-open .tb-dot {
	transform: scale(1.8);
}

.tb-chip-row {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.2s ease;
}
.tb-examples.is-open .tb-chip-row {
	opacity: 1;
	pointer-events: auto;
}

/* Each chip arrives just after the one before it, so opening reads as a single
   gesture rather than five things appearing at once. */
.tb-example-chip {
	height: 30px;
	padding: 0 10px;
	border-radius: var(--radius-md);
	border: 1px solid var(--color-stroke-default);
	background: none;
	font-size: 13px;
	color: var(--color-text-primary);
	cursor: pointer;
	transform: translateX(-6px);
	transition:
		transform 0.28s cubic-bezier(0.22, 1, 0.36, 1),
		border-color 0.16s ease;
	transition-delay: calc(var(--tb-i) * 34ms);
}
.tb-examples.is-open .tb-example-chip {
	transform: none;
}
.tb-example-chip:hover {
	border-color: var(--color-stroke-strong);
}

@media (prefers-reduced-motion: reduce) {
	.tb-example-chip,
	.tb-dot {
		transition: none;
		transform: none;
	}
}


/* ---------------------------------------------------------------------------
   FILTER CHIPS — the counts ARE the filters. A status count you can't act on
   is chrome.

   Chips toggle: clicking a selected chip clears it, so "Show all" is only
   rendered while a filter is actually active. That keeps the resting state at
   three controls instead of four, and makes the escape hatch appear exactly
   when it means something.
   --------------------------------------------------------------------------- */

.tb-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
}

.tb-chip {
	display: flex;
	height: 32px;
	align-items: center;
	gap: 6px;
	border-radius: var(--radius-md);
	border: 1px solid var(--color-stroke-default);
	background: none;
	padding: 0 8px;
	font-size: 12px;
	color: var(--color-text-secondary);
	cursor: pointer;
	white-space: nowrap;
	transition:
		background-color 0.14s,
		border-color 0.14s,
		color 0.14s;
}
.tb-chip:hover:not(:disabled) {
	border-color: var(--color-stroke-strong);
	color: var(--color-text-primary);
}
.tb-chip.is-on {
	background: var(--color-elevated);
	border-color: var(--color-stroke-strong);
	color: var(--color-text-primary);
}
.tb-chip:disabled {
	opacity: 0.4;
	cursor: default;
}

.tb-chip-count {
	color: var(--color-text-primary);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.tb-chip-dot {
	width: 6px;
	height: 6px;
	border-radius: 9999px;
	background: var(--color-text-tertiary);
}
.tb-chip-dot.is-available {
	background: var(--color-accent-green-graphic);
}
.tb-chip-dot.is-premium {
	background: var(--color-accent-purple-graphic);
}
.tb-chip-dot.is-uncertain {
	background: transparent;
	box-shadow: inset 0 0 0 1.5px var(--color-text-tertiary);
}

.tb-showall {
	height: 32px;
	border: 0;
	border-radius: var(--radius-md);
	background: none;
	padding: 0 8px;
	font-size: 12px;
	color: var(--color-text-secondary);
	cursor: pointer;
	text-underline-offset: 2px;
}
.tb-showall:hover {
	text-decoration: underline;
}


/* ---------------------------------------------------------------------------
   RESULTS META — the timing readout, beside the results, with a Raw API
   response toggle alongside. This is a developer-facing demo, so showing the
   actual traffic is part of the point.
   --------------------------------------------------------------------------- */

.tb-meta-row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 8px 16px;
}

.tb-readout {
	margin: 0;
	color: var(--color-text-secondary);
	font-family: var(--font-mono);
	font-size: 11px;
	font-variant-numeric: tabular-nums;
}
.tb-readout b {
	color: var(--color-text-primary);
	font-weight: 600;
}
.tb-readout .tb-quiet {
	opacity: 0.7;
}

.tb-raw-btn {
	display: flex;
	height: 32px;
	align-items: center;
	gap: 8px;
	border-radius: var(--radius-md);
	border: 1px solid var(--color-stroke-default);
	background: none;
	padding: 0 10px;
	font-size: 12px;
	color: var(--color-text-secondary);
	cursor: pointer;
	white-space: nowrap;
	transition:
		border-color 0.14s,
		color 0.14s;
}
.tb-raw-btn:hover {
	border-color: var(--color-stroke-strong);
	color: var(--color-text-primary);
}
.tb-raw-btn svg {
	width: 14px;
	height: 14px;
}

/*
 * Phones keep the full readout and the full button label. Neither fits beside
 * the filters at 375px — the readout alone wants 252px of the 343 available —
 * so they stack under them on the page's left edge, in the order they read:
 * what happened, then the way to inspect it.
 */
@media (max-width: 760px) {
	.tb-meta-row {
		flex-direction: column;
		align-items: flex-start;
		gap: 10px;
	}
}


/* ---------------------------------------------------------------------------
   RAW RESPONSE — the real request/response pairs for the current search,
   coloured with the palette's own --color-code-* tokens, the same ones
   MetaSearch uses for its raw-response panel.
   --------------------------------------------------------------------------- */

.tb-scrim {
	position: fixed;
	inset: 0;
	z-index: 50;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 16px;
	background: var(--color-scrim);
}

.tb-dialog {
	display: flex;
	max-height: 85vh;
	width: 100%;
	max-width: 720px;
	flex-direction: column;
	border-radius: var(--radius-unit);
	background: var(--color-pane);
	border: 1px solid var(--color-stroke-default);
	box-shadow: var(--elevation-pop);
}

.tb-dialog-head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 16px;
	padding: 20px 20px 12px;
}

.tb-dialog-head h2 {
	margin: 0;
	color: var(--color-text-primary);
	font-size: 14px;
	line-height: 20px;
	font-weight: 600;
}

.tb-dialog-head p {
	margin: 4px 0 0;
	color: var(--color-text-tertiary);
	font-size: 13px;
	line-height: 1.625;
}

.tb-close {
	flex-shrink: 0;
	border: 0;
	border-radius: var(--radius-md);
	background: none;
	padding: 4px;
	color: var(--color-text-tertiary);
	cursor: pointer;
	display: grid;
	place-items: center;
}
.tb-close svg {
	width: 16px;
	height: 16px;
}
.tb-close:hover {
	color: var(--color-text-primary);
	background: var(--color-elevated);
}

.tb-dialog-body {
	min-height: 0;
	flex: 1;
	overflow-y: auto;
	padding: 0 20px 20px;
}

.tb-raw-block + .tb-raw-block {
	margin-top: 20px;
	padding-top: 20px;
	border-top: 1px solid var(--color-stroke-subtle);
}

.tb-raw-head {
	margin-bottom: 8px;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
}

.tb-raw-label {
	color: var(--color-text-secondary);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.tb-copy {
	border-radius: var(--radius-sm);
	padding: 2px 8px;
	font-size: 11px;
	background: none;
	color: var(--color-text-tertiary);
	border: 1px solid var(--color-stroke-default);
	cursor: pointer;
}
.tb-copy:hover {
	color: var(--color-text-primary);
}

.tb-req {
	margin-bottom: 8px;
	display: block;
	font-family: var(--font-mono);
	font-size: 12px;
	line-height: 16px;
	word-break: break-all;
	color: var(--color-code-string);
}

.tb-json {
	overflow-x: auto;
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--color-code-literal);
	line-height: 1.55;
	margin: 0;
}
.tb-json .k {
	color: var(--color-code-key);
}
.tb-json .s {
	color: var(--color-code-string);
}
.tb-json .l,
.tb-json .n {
	color: var(--color-code-punct);
}


/* ---------------------------------------------------------------------------
   MOSAIC — every extension as a cell in one full-bleed wall. No container, no
   cards, no scrolling past a fold: all 27 answers are on screen at once and the
   whole wall repaints as results stream in.
   --------------------------------------------------------------------------- */

/*
 * The rules come from each cell's own outline, drawn outward into the 1px gap.
 * Painting the CONTAINER in the rule colour was simpler but left the unfilled
 * part of the last row as a solid grey block hanging off the end of the wall —
 * the grid ends where the answers end now.
 */
.tb-wall {
	display: grid;
	gap: 1px;
	max-width: var(--tb-max-w);
	margin-inline: auto;
}

/* Cell min-height plus the 1px rule, so the cap lands on a whole row. */
.tb-wall.is-scrolling {
	max-height: calc(8 * 97px);
	overflow-y: auto;
}

/*
 * The hero runs the full height of the wall rather than a 2x2 block in the
 * corner. The block left six cells stranded under it and five empty ones at the
 * bottom right; at full height the other extensions flow past it in one column
 * order and the grid closes out exactly, with nothing left over.
 *
 * Row span is set inline: it depends on how many extensions there are and how
 * many columns they get, neither of which CSS can count.
 */
.tb-feature {
	display: grid;
}

.tb-empty {
	padding: 32px 24px;
	font-size: 14px;
	color: var(--color-text-tertiary);
}


/* ---------------------------------------------------------------------------
   MOSAIC CELL
   --------------------------------------------------------------------------- */

.tb-cell {
	outline: 1px solid var(--color-stroke-default);
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 6px;
	min-height: 96px;
	/* Square padding: the same 12px on all four sides, so the gap before the
	   name matches the gap under the timing row. Tying it to the page gutter
	   instead made the inset far heavier at the sides than at the bottom. */
	padding: 12px;
	background: var(--color-card);
	/* The wave: each cell repaints the moment its answer lands. */
	transition:
		background-color 0.35s ease,
		color 0.35s ease;
}

/* The name is the point of the cell, and it is the WHOLE name: showing the
   extension alone made you reconstruct each domain in your head. It is set
   smaller to fit, and wraps rather than clipping, because a name cut off
   mid-word is worse than a name on two lines. Full contrast whatever the
   status — that is carried by the pill and the cell fill, not by dimming the
   name. */
.tb-tld {
	font-size: clamp(12px, 1.05vw, 15px);
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: -0.01em;
	overflow-wrap: anywhere;
	color: var(--color-text-primary);
}

/*
 * The dot and the extension are one unit and never split. The name may wrap
 * anywhere inside the typed part, but ".store" moves to the next line whole
 * rather than leaving ".sto" hanging at the end of a line.
 */
.tb-ext {
	white-space: nowrap;
}

/* The stem repeats in all 27 cells, so it recedes and the extension leads. */
.tb-stem {
	color: var(--color-text-tertiary);
	font-weight: 500;
}

/* Transparent in a normal cell — it exists so the hero can move the status and
   the timing together as one unit. */
.tb-foot {
	display: contents;
}

.tb-meta {
	display: flex;
	align-items: baseline;
	gap: 8px;
	flex-wrap: wrap;
	min-height: 16px;
}

/* Deliberately small: the status is a footnote to the name, not a badge. Small
   type needs more contrast, so the taken label sits on secondary rather than
   the faintest grey. */
.tb-pill {
	display: inline-block;
	padding: 1px 5px;
	border-radius: var(--radius-sm);
	font-size: 9.5px;
	font-weight: 600;
	letter-spacing: 0.02em;
	white-space: nowrap;
	background: var(--color-elevated);
	/* The chip needs its label a step up from the recessive grey to stay legible
	   against the fill. */
	color: var(--color-text-secondary);
}

.tb-price {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--color-text-secondary);
	font-variant-numeric: tabular-nums;
}

.tb-price.is-quiet {
	font-family: var(--font-sans);
	font-weight: 500;
	color: var(--color-text-tertiary);
}

.tb-yr {
	font-size: 0.8em;
	color: var(--color-text-tertiary);
	font-weight: 500;
}

/* The premium suffix reads as "$12,500/yr" and abuts the figure; the standard
   note is a separate qualifier and needs the space. */
.tb-yr.is-note {
	margin-left: 0.35em;
}

/* Gettable: the cell takes the colour, so the wall reads at a glance. */
.tb-cell.is-available {
	background:
		linear-gradient(var(--color-accent-green-tint), var(--color-accent-green-tint)),
		var(--color-card);
}
.tb-cell.is-available .tb-pill {
	background: var(--color-accent-green);
	color: var(--color-on-accent);
}

.tb-cell.is-premium {
	background:
		linear-gradient(var(--color-accent-purple-tint), var(--color-accent-purple-tint)),
		var(--color-card);
}
.tb-cell.is-premium .tb-pill {
	background: var(--color-accent-purple);
	color: var(--color-on-accent);
}
.tb-cell.is-premium .tb-price {
	color: var(--color-text-secondary);
}

.tb-cell.is-uncertain {
	background: var(--color-card);
	box-shadow: inset 0 0 0 1px var(--color-stroke-default);
}

/* Taken stays quiet — it is the answer you skip past. */
.tb-cell.is-taken {
	background: var(--color-card);
}

/*
 * The feature cell. The name and its status are ONE group, separated by a gap
 * set against the name's own size rather than against the block's height.
 *
 * Centred, not top-aligned. The hero runs the full height of the wall, so
 * anchoring its content to the top left five hundred pixels of empty panel
 * below it, which read as a rendering fault rather than as space. Centred, the
 * height reads as deliberate.
 */
.tb-cell.is-feature {
	position: relative;
	min-height: 100%;
	padding: 12px 12px 12px var(--tb-gutter);
	display: flex;
	flex-direction: column;
	align-items: stretch;
	justify-content: center;
	gap: clamp(10px, 1.4vw, 22px);
}

/*
 * Says what the big cell IS, so it does not read as a stray large tile.
 *
 * Sits in the top-right corner, out of the name's way, and takes the same
 * filled-chip shape as the status pills — in MetaSearch's blue, so it reads as
 * a different KIND of label rather than another status.
 */
.tb-hero-badge {
	position: absolute;
	top: 12px;
	right: 12px;
	padding: 2px 7px;
	border-radius: var(--radius-sm);
	background: var(--color-accent-blue);
	font-size: 9.5px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-on-accent);
}

.tb-cell.is-feature .tb-full {
	flex: none;
	order: -1;
	/* A third of the wall's width and all of its height, so the name is set to
	   match rather than sitting small inside it. */
	font-size: clamp(24px, 4.4vw, 76px);
	font-weight: 700;
	letter-spacing: -0.03em;
	line-height: 1.05;
	overflow-wrap: anywhere;
	color: var(--color-text-primary);
}
.tb-cell.is-feature .tb-foot {
	display: flex;
	flex-direction: column;
	gap: 10px;
	flex: none;
}
.tb-cell.is-feature .tb-tld {
	display: none;
}
.tb-cell.is-feature .tb-price {
	font-size: 12px;
}
.tb-cell.is-feature .tb-pill {
	font-size: 10.5px;
	padding: 2px 6px;
}

/* Taken reads grey rather than full-strength black — it is the answer you skip
   past, and on light the body colour made it as loud as the rest. */
.tb-cell.is-taken .tb-tld,
.tb-cell.is-taken .tb-stem {
	color: var(--color-name-muted);
}

/* A name you can actually buy reads at full strength, stem included. The stem
   only recedes on rows you are scrolling past. */
.tb-cell.is-available .tb-stem,
.tb-cell.is-premium .tb-stem {
	color: var(--color-text-primary);
}

/* Rows lift to the elevated grey on hover. The tinted states set their colour
   through the background shorthand, whose final layer IS the base colour, so
   overriding background-color alone keeps the tint on top. */
.tb-cell:hover {
	background-color: var(--color-elevated);
}
.tb-cell.is-available:hover {
	background-color: var(--color-card);
	background-image: linear-gradient(
		var(--color-accent-green-tint-hover),
		var(--color-accent-green-tint-hover)
	);
}
.tb-cell.is-premium:hover {
	background-color: var(--color-card);
	background-image: linear-gradient(
		var(--color-accent-purple-tint-hover),
		var(--color-accent-purple-tint-hover)
	);
}

/* Full-strength ink on a coloured tile. The supporting greys were chosen
   against the page, and on green they lost too much contrast to read. */
.tb-cell.is-available .tb-price,
.tb-cell.is-available .tb-yr,
.tb-cell.is-premium .tb-price,
.tb-cell.is-premium .tb-yr {
	color: var(--color-text-primary);
}

/* Outer edges only. Inner boundaries keep the cells' own 12px. */
.tb-cell.is-edge-left {
	padding-left: var(--tb-gutter);
}
.tb-cell.is-edge-right {
	padding-right: var(--tb-gutter);
}

@media (max-width: 639px) {
	.tb-cell.is-feature {
		padding-right: var(--tb-gutter);
	}
}


/* ---------------------------------------------------------------------------
   SKELETON — the shimmer standing in for an answer that has not landed.
   --------------------------------------------------------------------------- */

@keyframes tb-shimmer {
	0% {
		background-position: 100% 0;
	}
	100% {
		background-position: 0 0;
	}
}

.tb-skeleton {
	display: inline-block;
	vertical-align: middle;
	height: 8px;
	background: linear-gradient(
		90deg,
		var(--color-elevated) 25%,
		var(--color-stroke-default) 37%,
		var(--color-elevated) 63%
	);
	background-size: 400% 100%;
	animation: tb-shimmer 1.1s infinite linear;
	border-radius: var(--radius-sm);
}

.tb-skeleton.is-status {
	width: 40px;
}
.tb-skeleton.is-price {
	width: 48px;
}

@media (prefers-reduced-motion: reduce) {
	.tb-skeleton {
		animation: none;
	}
}


/* ---------------------------------------------------------------------------
   NOTICES
   --------------------------------------------------------------------------- */

/* Inline failure surface. The API rejects bad labels with a 400 and an
   explanatory message; we show its wording rather than failing silently or
   leaving 27 skeletons spinning forever. */
.tb-notice {
	margin: 40px auto 0;
	display: flex;
	max-width: 520px;
	align-items: flex-start;
	gap: 12px;
	border-radius: var(--radius-cta);
	padding: 16px;
	font-size: 14px;
	line-height: 20px;
	background: var(--color-pane);
	border: 1px solid var(--color-accent-coral-tint);
	box-shadow: var(--elevation-float);
}

.tb-notice-dot {
	margin-top: 6px;
	width: 6px;
	height: 6px;
	flex-shrink: 0;
	border-radius: 9999px;
	background: var(--color-accent-coral-graphic);
}

.tb-notice-title {
	margin: 0;
	color: var(--color-text-primary);
	font-weight: 500;
}

.tb-notice-body {
	margin: 4px 0 0;
	color: var(--color-text-tertiary);
	line-height: 1.625;
}

/*
 * Shown when the OFFLINE build is asked for a name it has no capture for.
 *
 * The alternative was 27 rows of "Unknown", which is technically honest but
 * reads as a broken search. This says the same thing in one sentence and hands
 * the visitor names that do work.
 */
.tb-offline {
	margin: 40px auto 0;
	max-width: 560px;
	border-radius: var(--radius-cta);
	padding: 24px;
	text-align: center;
	background: var(--color-pane);
	border: 1px solid var(--pane-ring);
}

.tb-offline-title {
	margin: 0;
	color: var(--color-text-primary);
	font-size: 14px;
	font-weight: 500;
}
.tb-offline-title .tb-term {
	font-family: var(--font-mono);
}

.tb-offline-body {
	margin: 8px 0 0;
	color: var(--color-text-tertiary);
	font-size: 13px;
	line-height: 1.625;
}

.tb-offline-chips {
	margin-top: 16px;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 6px;
}

.tb-offline-chip {
	height: 32px;
	border-radius: var(--radius-md);
	border: 1px solid var(--color-stroke-default);
	background: none;
	padding: 0 10px;
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--color-text-secondary);
	cursor: pointer;
	transition:
		border-color 0.14s,
		color 0.14s;
}
.tb-offline-chip:hover {
	border-color: var(--color-stroke-strong);
	color: var(--color-text-primary);
}
