# desktop-mode/1.1.1/assets/css/announce.css

OpenStation: Desktop Windows, Dock &amp; Virtual Desktops for WP Admin, version 1.1.1. 384 lines.

- Page: https://pluginprobe.com/plugins/desktop-mode/1.1.1/code/assets/css/announce.css
- Raw: https://pluginprobe.com/plugins/desktop-mode/1.1.1/raw/assets/css/announce.css
- Modified: 2026-08-07T20:39:04+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/desktop-mode/1.1.1/code/assets/css/announce.css#L10-L20`.

```css
/*
 * Announcement dialog — the shell's full-stop moment.
 *
 * The look is the first-run welcome dialog's: a blurred Void scrim with
 * Nebula and mint glows, a near-white card with a holographic hairline,
 * and a dark shimmering hero at the top of it. That dialog is the one
 * piece of UI in the product that gets to be loud, and an announcement
 * that has to explain a rename is the only other thing that earns it.
 *
 * Built as plain classed DOM rather than out of `<os-*>` components, on
 * purpose and for the same reason the welcome dialog is: this is a
 * poster, not a control panel. `<os-modal>` gives a dialog chrome and a
 * focus trap, and would then have to be fought for every one of the
 * gradients below.
 *
 * ---------------------------------------------------------------
 * KNOWN DUPLICATION. `includes/welcome-dialog.php` inlines its own copy
 * of this design. It has to be self-contained — it renders in *classic*
 * wp-admin, on `admin_footer`, where none of the shell's stylesheets
 * are enqueued — so the two cannot share a file without that dialog
 * taking on a dependency it was deliberately built without. Restyle one
 * and the other will drift. If they should converge, the move is to
 * enqueue THIS file in classic admin too and delete the inline block,
 * not to copy edits between them.
 * ---------------------------------------------------------------
 *
 * ---------------------------------------------------------------
 * THIS FILE OPTS OUT OF THE PALETTE, AND THAT IS A DEPARTURE.
 *
 * Every colour below is a literal. Not one reads a `--os-*` token, so
 * nothing here answers to `variables.css` or to a desktop theme, which
 * is exactly what AGENTS.md's "one declaration, one owner" rule tells
 * you not to do. Read this as a one-off, NOT as the house pattern: a
 * feature stylesheet that hardcodes its colours is a bug.
 *
 * The trade, deliberately made: the card is the product introducing
 * itself by name, and a theme recolouring that would be the theme
 * speaking in the product's voice. `<os-modal>` makes the same call for
 * its own surface. The difference is that `<os-modal>` still routes
 * through `--os-ui-modal-*` names, so a theme that really wants the
 * surface can reach it; this file gives a theme nothing, and it is only
 * defensible because the dialog exists for one release cycle and then
 * stops firing forever.
 *
 * If it outlives that, tokenize it. Note that nothing will tell you to:
 * `brand-palette.test.ts` only scans `variables.css`, so no test fails
 * while this drifts from the palette beside it.
 * ---------------------------------------------------------------
 */

.os-announce,
.os-announce * {
	box-sizing: border-box;
}

.os-announce {
	position: fixed;
	inset: 0;
	/*
	 * Above every window (z 100+), the dock, and the Mio layer (190).
	 * Matches the welcome dialog's own z-index so the two can never
	 * argue if a site somehow shows both.
	 */
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	background: radial-gradient(
			ellipse at 30% 20%,
			rgba(236, 155, 255, 0.32),
			transparent 60%
		),
		radial-gradient(
			ellipse at 70% 80%,
			rgba(147, 240, 198, 0.26),
			transparent 55%
		),
		rgba(12, 11, 15, 0.62);
	backdrop-filter: blur(14px) saturate(140%);
	-webkit-backdrop-filter: blur(14px) saturate(140%);
	animation: os-announce-fade 360ms cubic-bezier(0.22, 1, 0.36, 1);
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
		"Helvetica Neue", Arial, sans-serif;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

@keyframes os-announce-fade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

@keyframes os-announce-pop {
	0% {
		opacity: 0;
		transform: translateY(14px) scale(0.96);
	}
	100% {
		opacity: 1;
		transform: translateY(0) scale(1);
	}
}

@keyframes os-announce-shimmer {
	0% {
		background-position: 0% 50%;
	}
	100% {
		background-position: 100% 50%;
	}
}

.os-announce__card {
	position: relative;
	width: 100%;
	max-width: 620px;
	border-radius: 22px;
	overflow: hidden;
	background: linear-gradient(
		145deg,
		rgba(255, 255, 255, 0.98) 0%,
		rgba(255, 251, 255, 0.98) 100%
	);
	box-shadow: 0 1px 0 rgba(255, 255, 255, 0.85) inset,
		0 30px 60px -20px rgba(26, 23, 33, 0.55),
		0 18px 36px -18px rgba(242, 82, 252, 0.45);
	animation: os-announce-pop 460ms cubic-bezier(0.22, 1, 0.36, 1) both;
	animation-delay: 60ms;
}

/*
 * Holographic hairline. A padded pseudo-element masked with `xor` so
 * only the 1px ring paints — a plain border cannot carry a gradient.
 */
.os-announce__card::before {
	content: "";
	position: absolute;
	inset: -1px;
	border-radius: inherit;
	padding: 1px;
	background: linear-gradient(
		135deg,
		rgba(242, 82, 252, 0.65),
		rgba(236, 155, 255, 0.55),
		rgba(147, 240, 198, 0.55)
	);
	-webkit-mask: linear-gradient(#000 0 0) content-box,
		linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
	pointer-events: none;
}

.os-announce__hero {
	position: relative;
	padding: 32px 36px 26px;
	background: linear-gradient(135deg, #0c0b0f 0%, #2a2533 45%, #ec9bff 100%);
	background-size: 200% 200%;
	animation: os-announce-shimmer 14s ease infinite alternate;
	color: #fff;
	overflow: hidden;
}

/* Station grid + glows, faded out at the edges so it reads as depth. */
.os-announce__hero::after {
	content: "";
	position: absolute;
	inset: 0;
	background: radial-gradient(
			circle at 85% 15%,
			rgba(236, 155, 255, 0.35),
			transparent 45%
		),
		radial-gradient(
			circle at 15% 90%,
			rgba(147, 240, 198, 0.22),
			transparent 50%
		),
		linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px) 0 0 /
			28px 28px,
		linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px) 0
			0 / 28px 28px;
	pointer-events: none;
	mask-image: radial-gradient(ellipse at 50% 40%, #000 35%, transparent 80%);
	-webkit-mask-image: radial-gradient(
		ellipse at 50% 40%,
		#000 35%,
		transparent 80%
	);
}

/*
 * The eyebrow pill, sitting above the hero's own overlay. Same chip the
 * welcome dialog wears for "New here", so the two dialogs read as the
 * same voice saying two different things.
 */
.os-announce__eyebrow {
	position: relative;
	z-index: 1;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 5px 12px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: #fff;
	background: rgba(255, 255, 255, 0.18);
	border: 1px solid rgba(255, 255, 255, 0.28);
	border-radius: 999px;
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
}

.os-announce__eyebrow-dot {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: #ec9bff;
	box-shadow: 0 0 0 4px rgba(236, 155, 255, 0.28);
}

.os-announce__title {
	position: relative;
	z-index: 1;
	margin: 14px 0 6px;
	font-size: 26px;
	line-height: 1.2;
	font-weight: 700;
	letter-spacing: -0.01em;
	color: #fff;
}

.os-announce__subtitle {
	position: relative;
	z-index: 1;
	margin: 0;
	font-size: 14px;
	line-height: 1.5;
	color: rgba(255, 255, 255, 0.85);
}

.os-announce__body {
	padding: 24px 36px 4px;
	font-size: 14.5px;
	line-height: 1.6;
	color: #33303a;
}

.os-announce__body p {
	margin: 0 0 12px;
}

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

/*
 * The reassurance line — quieter than the copy above it. It answers
 * "did my install change?" for the people who think to ask, without
 * competing with the explanation.
 */
.os-announce__fine {
	padding: 14px 16px;
	background: linear-gradient(
		135deg,
		rgba(242, 82, 252, 0.08),
		rgba(147, 240, 198, 0.08)
	);
	border: 1px solid rgba(242, 82, 252, 0.22);
	border-radius: 12px;
	font-size: 13px;
	color: #2a2533;
}

.os-announce__actions {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 10px;
	padding: 22px 36px 28px;
}

.os-announce__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	min-height: 38px;
	padding: 8px 18px;
	font-size: 14px;
	font-weight: 600;
	font-family: inherit;
	line-height: 1;
	border-radius: 10px;
	border: 1px solid transparent;
	cursor: pointer;
	text-decoration: none;
	transition: transform 120ms ease, box-shadow 120ms ease,
		background 120ms ease, color 120ms ease;
}

.os-announce__btn:focus-visible {
	outline: 2px solid #f252fc;
	outline-offset: 2px;
}

.os-announce__btn--primary,
.os-announce__btn--primary:hover,
.os-announce__btn--primary:focus {
	color: #fffbff;
}

.os-announce__btn--primary {
	/*
	 * Ends on Pulse, not Nebula. `background-position` slides this on
	 * hover, so every stop carries the label at some point, and Nebula
	 * is light enough that Starlight text on it falls to ~1.6:1.
	 */
	background: linear-gradient(135deg, #2a2533, #a12bb0 45%, #f252fc);
	background-size: 180% 180%;
	box-shadow: 0 10px 24px -10px rgba(242, 82, 252, 0.75),
		0 4px 10px -4px rgba(236, 155, 255, 0.55);
}

.os-announce__btn--primary:hover {
	transform: translateY(-1px);
	background-position: 100% 50%;
	box-shadow: 0 14px 30px -12px rgba(242, 82, 252, 0.85),
		0 6px 14px -4px rgba(236, 155, 255, 0.65);
}

.os-announce__btn--primary:active {
	transform: translateY(0);
}

@media (max-width: 600px) {
	.os-announce__hero {
		padding: 26px 24px 20px;
	}

	.os-announce__body,
	.os-announce__actions {
		padding-left: 24px;
		padding-right: 24px;
	}

	.os-announce__title {
		font-size: 22px;
	}

	.os-announce__actions {
		flex-direction: column-reverse;
		align-items: stretch;
	}

	.os-announce__btn {
		width: 100%;
	}
}

/*
 * Reduced motion stops the movement, never the paint. The shimmer, the
 * pop and the scrim fade are decoration; the gradients they animate are
 * the dialog's identity and stay put at their first frame.
 */
@media (prefers-reduced-motion: reduce) {
	.os-announce,
	.os-announce__card,
	.os-announce__hero {
		animation: none;
	}

	.os-announce__btn {
		transition: none;
	}
}

```
