/*
Theme Name: Lisboa Glow
Theme URI: https://lisbon-local.com/
Description: The Lisbon Local design system as a Twenty Twenty-Five child theme. A warm limestone ground, Tejo blue water, Carris yellow as an event rather than a background, and a night mode built as a live transit radar instead of an inverted day theme. Ships route-pill, ETA-chip and departure-board block styles plus LisboaClaro / LisboaNoite / LisboaPlay style variations.
Author: Lisbon Local
Author URI: https://lisbon-local.com/
Template: twentytwentyfive
Version: 1.1.2
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: lisboa-glow
Tags: one-column, custom-colors, custom-menu, custom-logo, editor-style, featured-images, full-site-editing, block-patterns, rtl-language-support, sticky-post, threaded-comments, translation-ready, wide-blocks, block-styles, style-variations, accessibility-ready
*/

/*
 * Lisboa Glow — component layer.
 *
 * Design tokens live in theme.json; this file only carries what block supports
 * cannot express (component recipes, glass surfaces, sticky chrome). Every value
 * below reads from a theme.json token — never hard-code a hex here.
 *
 * Contents:
 *   1. Foundations
 *   2. Route pills
 *   3. ETA chips
 *   4. Mode dots and legend
 *   5. Cards, glass and panels
 *   6. Departure rows
 *   7. Eyebrow, lede and highlight
 *   8. Search and controls
 *   9. Chrome — sticky header, footer
 *  10. Accessibility and motion
 */

/* ------------------------------------------------------------------------- *
 * 1. Foundations
 * ------------------------------------------------------------------------- */

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
}

/* Digits that line up: ETAs, times, route numbers, tables. */
.lg-tabular,
.wp-block-table td,
.wp-block-table th,
time {
	font-variant-numeric: tabular-nums;
}

/* Headings and long copy should never break awkwardly. */
:where(h1, h2, h3, h4, .lg-balance) {
	text-wrap: balance;
}

:where(p, li) {
	text-wrap: pretty;
}

/*
 * Keep prose inside a readable measure even in wide containers.
 *
 * The constrained layout centres any child that is narrower than the content
 * size, so the inline margins are pinned to keep measured text flush with the
 * headings above it rather than floating in the middle of the column.
 */
.lg-measure {
	margin-inline: 0 auto;
	max-width: var(--wp--custom--measure);
}

/* ------------------------------------------------------------------------- *
 * 2. Route pills — the strongest brand element
 *
 * Yellow is the scarcest resource in the system. A pill is a route identity,
 * never decoration.
 * ------------------------------------------------------------------------- */

.lg-pill,
.is-style-lg-pill {
	align-items: center;
	background-color: var(--wp--preset--color--carris);
	border-radius: var(--wp--custom--radius--sm);
	color: var(--wp--custom--text--on-accent);
	display: inline-flex;
	font-size: var(--wp--preset--font-size--route-number);
	font-variant-numeric: tabular-nums;
	font-weight: 800;
	gap: 0.4em;
	letter-spacing: 0.01em;
	line-height: 1.3;
	padding: 0.2em 0.5em;
	text-decoration: none;
}

/* A pill that is also a link keeps pill colours, not link colours. */
a.lg-pill,
a.lg-pill:hover,
a.lg-pill:focus {
	color: var(--wp--custom--text--on-accent);
	text-decoration: none;
}

.lg-pill--sm {
	font-size: var(--wp--preset--font-size--small);
	padding: 0.25em 0.6em;
}

.lg-pill--ghost {
	background-color: transparent;
	border: 1px solid var(--wp--custom--line--strong);
	color: var(--wp--custom--text--muted);
	font-weight: 700;
}

.lg-pill--cool {
	background-color: var(--wp--preset--color--tejo);
	color: #fff;
}

.lg-pill--danger {
	background-color: var(--wp--preset--color--danger);
	color: #fff;
}

.lg-pill--ok {
	background-color: var(--wp--preset--color--success);
	color: #fff;
}

/* Mode-coloured pills. */
.lg-pill--bus { background-color: var(--wp--custom--mode--bus); }
.lg-pill--tram { background-color: var(--wp--custom--mode--tram); color: #fff; }
.lg-pill--metro { background-color: var(--wp--custom--mode--metro); color: #fff; }
.lg-pill--light-rail { background-color: var(--wp--custom--mode--light-rail); color: #fff; }
.lg-pill--rail { background-color: var(--wp--custom--mode--rail); color: #fff; }
.lg-pill--ferry { background-color: var(--wp--custom--mode--ferry); color: #fff; }
.lg-pill--funicular { background-color: var(--wp--custom--mode--funicular); color: #fff; }

/* ------------------------------------------------------------------------- *
 * 3. ETA chips
 *
 * Human phrasing only — "2 min", "1 stop away", "Leave in 5 min".
 * ------------------------------------------------------------------------- */

.lg-eta,
.is-style-lg-eta {
	align-items: baseline;
	border-radius: var(--wp--custom--radius--full);
	display: inline-flex;
	font-size: var(--wp--preset--font-size--small);
	font-variant-numeric: tabular-nums;
	font-weight: 700;
	gap: 0.35rem;
	line-height: 1.35;
	padding: 0.3rem 0.75rem;
	white-space: nowrap;
}

.lg-eta--ontime {
	background-color: var(--wp--custom--status--success-soft);
	color: var(--wp--custom--status--success-dark);
}

.lg-eta--soon {
	background-color: var(--wp--preset--color--carris);
	color: var(--wp--custom--text--on-accent);
}

.lg-eta--late {
	background-color: var(--wp--custom--status--danger-soft);
	color: var(--wp--custom--status--danger-dark);
}

.lg-eta--info {
	background-color: var(--wp--custom--status--info-soft);
	color: var(--wp--custom--status--info-dark);
}

.lg-eta--warning {
	background-color: var(--wp--custom--status--warning-soft);
	color: var(--wp--custom--status--warning-dark);
}

/* Live pulse — only live things move. */
.lg-eta--live::before {
	animation: lg-pulse 2s ease-in-out infinite;
	background-color: currentColor;
	border-radius: var(--wp--custom--radius--full);
	content: "";
	flex: 0 0 auto;
	height: 0.5em;
	width: 0.5em;
}

@keyframes lg-pulse {
	0%, 100% { opacity: 1; transform: scale(1); }
	50% { opacity: 0.45; transform: scale(0.82); }
}

/* ------------------------------------------------------------------------- *
 * 4. Mode dots and legend
 * ------------------------------------------------------------------------- */

.lg-dot {
	border-radius: var(--wp--custom--radius--full);
	box-shadow: inset 0 0 0 1px var(--wp--custom--swatch-ring);
	display: inline-block;
	height: 0.7em;
	margin-inline-end: 0.45em;
	vertical-align: baseline;
	width: 0.7em;
}

.lg-dot--bus { background-color: var(--wp--custom--mode--bus); }
.lg-dot--tram { background-color: var(--wp--custom--mode--tram); }
.lg-dot--metro { background-color: var(--wp--custom--mode--metro); }
.lg-dot--light-rail { background-color: var(--wp--custom--mode--light-rail); }
.lg-dot--rail { background-color: var(--wp--custom--mode--rail); }
.lg-dot--ferry { background-color: var(--wp--custom--mode--ferry); }
.lg-dot--funicular { background-color: var(--wp--custom--mode--funicular); }

.lg-legend {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.25rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.lg-legend li {
	align-items: center;
	color: var(--wp--custom--text--soft);
	display: flex;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 550;
}

/* ------------------------------------------------------------------------- *
 * 5. Cards, glass and panels
 * ------------------------------------------------------------------------- */

/* Soft, generous radii and floating panels — never sterile white. */
.is-style-lg-card {
	background-color: var(--wp--custom--surface--card);
	border: 1px solid var(--wp--custom--line--hairline);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: var(--wp--preset--shadow--sm);
}

.is-style-lg-panel {
	background-color: var(--wp--custom--surface--raised);
	border: 1px solid var(--wp--custom--line--hairline);
	border-radius: var(--wp--custom--radius--xl);
	box-shadow: var(--wp--preset--shadow--lg);
}

/* Glass over a map. Falls back to the warm card colour without backdrop-filter. */
.is-style-lg-glass {
	background-color: var(--wp--custom--surface--glass-fallback);
	border: 1px solid var(--wp--custom--surface--glass-border);
	border-radius: var(--wp--custom--radius--xl);
	box-shadow: var(--wp--preset--shadow--md);
}

@supports (backdrop-filter: blur(12px)) or (-webkit-backdrop-filter: blur(12px)) {
	.is-style-lg-glass {
		-webkit-backdrop-filter: blur(12px);
		backdrop-filter: blur(12px);
		background-color: var(--wp--custom--surface--glass);
	}
}

/* Hairline-separated stack — used for spec tables and feature lists. */
.lg-rows > * + * {
	border-top: 1px solid var(--wp--custom--line--hairline);
	margin-top: 0;
	padding-top: 0.9rem;
}

.lg-rows > * {
	padding-bottom: 0.9rem;
}

.lg-rows > *:last-child {
	padding-bottom: 0;
}

/* ------------------------------------------------------------------------- *
 * 6. Departure rows
 * ------------------------------------------------------------------------- */

.lg-departure {
	align-items: center;
	border-bottom: 1px solid var(--wp--custom--line--hairline);
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 0.85rem;
	min-height: 62px;
	padding: 0.6rem 0;
}

.lg-departure:last-child {
	border-bottom: 0;
}

.lg-departure__dest {
	flex: 1 1 8rem;
	font-weight: 550;
	margin: 0;
}

.lg-departure__sched {
	color: var(--wp--custom--text--muted);
	font-size: var(--wp--preset--font-size--small);
	font-variant-numeric: tabular-nums;
	margin: 0;
}

/* ------------------------------------------------------------------------- *
 * 7. Eyebrow, lede and highlight
 * ------------------------------------------------------------------------- */

.is-style-lg-eyebrow {
	color: var(--wp--custom--text--muted);
	font-size: var(--wp--preset--font-size--caption);
	font-weight: 700;
	letter-spacing: 0.16em;
	line-height: 1.4;
	text-transform: uppercase;
}

.is-style-lg-lede {
	color: var(--wp--custom--text--soft);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 550;
	line-height: 1.45;
	margin-inline: 0 auto;
	max-width: 46ch;
}

/* The Carris highlight: a sweep behind the words, not a background. */
.lg-mark {
	box-shadow: inset 0 -0.42em 0 var(--wp--preset--color--carris-soft);
	font-style: normal;
	padding: 0 0.06em;
}

/* ------------------------------------------------------------------------- *
 * 8. Search and controls
 * ------------------------------------------------------------------------- */

.wp-block-search__input {
	background-color: var(--wp--custom--surface--raised);
	border: 1px solid var(--wp--custom--line--hairline);
	border-radius: var(--wp--custom--radius--xl);
	box-shadow: var(--wp--preset--shadow--md);
	color: var(--wp--preset--color--contrast);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	min-height: var(--wp--custom--control--search-height);
	padding-inline: 1.15rem;
}

.wp-block-search__input::placeholder {
	color: var(--wp--custom--text--light);
}

.wp-block-search__input:focus {
	border-color: var(--wp--preset--color--tejo);
	outline: 2px solid var(--wp--preset--color--tejo);
	outline-offset: 2px;
}

.wp-block-search__button {
	border-radius: var(--wp--custom--radius--xl);
	min-height: var(--wp--custom--control--height);
}

/*
 * Button-inside search: the wrapper is the pill, so the input must not draw a
 * second border inside it. Focus moves to the wrapper to stay visible.
 */
.wp-block-search__button-inside .wp-block-search__inside-wrapper {
	background-color: var(--wp--custom--surface--raised);
	border: 1px solid var(--wp--custom--line--hairline);
	border-radius: var(--wp--custom--radius--xl);
	box-shadow: var(--wp--preset--shadow--md);
	padding: 6px 6px 6px 10px;
}

.wp-block-search__button-inside .wp-block-search__inside-wrapper:focus-within {
	border-color: var(--wp--preset--color--tejo);
	outline: 2px solid var(--wp--preset--color--tejo);
	outline-offset: 2px;
}

.wp-block-search__button-inside .wp-block-search__input {
	background-color: transparent;
	border: 0;
	box-shadow: none;
	min-height: auto;
	padding-inline: 0.35rem;
}

.wp-block-search__button-inside .wp-block-search__input:focus {
	outline: 0;
}

/* Comment and contact fields share the search bar's material. */
.wp-block-post-comments-form input[type="text"],
.wp-block-post-comments-form input[type="email"],
.wp-block-post-comments-form input[type="url"],
.wp-block-post-comments-form textarea,
.wp-block-comments input[type="text"],
.wp-block-comments input[type="email"],
.wp-block-comments input[type="url"],
.wp-block-comments textarea {
	background-color: var(--wp--custom--surface--card);
	border: 1px solid var(--wp--custom--line--strong);
	border-radius: var(--wp--custom--radius--md);
	color: var(--wp--preset--color--contrast);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	padding: 0.75rem 0.9rem;
}

.wp-block-post-comments-form input[type="text"]:focus,
.wp-block-post-comments-form input[type="email"]:focus,
.wp-block-post-comments-form input[type="url"]:focus,
.wp-block-post-comments-form textarea:focus,
.wp-block-comments input[type="text"]:focus,
.wp-block-comments input[type="email"]:focus,
.wp-block-comments input[type="url"]:focus,
.wp-block-comments textarea:focus {
	border-color: var(--wp--preset--color--tejo);
	outline: 2px solid var(--wp--preset--color--tejo);
	outline-offset: 1px;
}

.wp-block-post-comments-form label,
.wp-block-comments label {
	color: var(--wp--custom--text--soft);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 550;
}

/* Comment rows sit on their own warm card. */
.wp-block-comment-template > li {
	background-color: var(--wp--custom--surface--card);
	border: 1px solid var(--wp--custom--line--hairline);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: var(--wp--preset--shadow--sm);
	list-style: none;
	padding: var(--wp--preset--spacing--40);
}

.wp-block-comment-template {
	padding-inline-start: 0;
}

/* ------------------------------------------------------------------------- *
 * 9. Chrome — sticky header, footer
 * ------------------------------------------------------------------------- */

.lg-sticky-header {
	background-color: transparent;
	border-bottom: 1px solid var(--wp--custom--line--hairline);
	position: sticky;
	top: 0;
	z-index: 20;
}

/*
 * A hairline of the brand gradient sits on the bottom edge — the one place the
 * chrome is allowed colour. It reads as a route line under the bar.
 */
.lg-sticky-header::after {
	background-image: linear-gradient(
		90deg,
		var(--wp--preset--color--carris) 0%,
		var(--wp--custom--mode--tram) 42%,
		var(--wp--preset--color--tejo-deep) 100%
	);
	bottom: -1px;
	content: "";
	height: 2px;
	left: 0;
	opacity: 0.7;
	position: absolute;
	right: 0;
}

/*
 * The chrome and the page meet exactly at the route line. Without this the
 * root block gap leaves a band of ground below the header, which reads as the
 * header background bleeding past its own edge.
 */
.wp-site-blocks > .wp-block-template-part:first-child + * {
	margin-block-start: 0;
}

/* The header bar never wraps; the brand block is what gives way first. */
.lg-headerbar {
	min-height: 72px;
}

.lg-brand {
	min-width: 0;
}

/*
 * The site mark is a route badge, not a logo lockup — square, warm, faintly
 * lit, and the same size as a tap target. The artwork carries its own rounded
 * gold frame, so no border-radius is imposed on top of it.
 */
.lg-mark {
	flex-shrink: 0;
	line-height: 0;
	margin: 0;
}

.lg-mark .wp-block-site-logo,
.lg-sticky-header .wp-block-site-logo {
	line-height: 0;
	margin: 0;
}

.lg-mark img,
.lg-sticky-header .wp-block-site-logo img {
	display: block;
	filter: drop-shadow(0 2px 10px var(--wp--custom--glow--yellow));
	height: auto;
	transition: transform 180ms ease;
	width: 54px;
}

@media (max-width: 600px) {
	.lg-mark img,
	.lg-sticky-header .wp-block-site-logo img {
		width: 46px;
	}
}

.lg-sticky-header .wp-block-site-logo a:hover img {
	transform: scale(1.05);
}

.lg-brand__text {
	min-width: 0;
}

.lg-sticky-header .wp-block-site-title {
	line-height: 1.15;
	margin: 0;
}

.lg-sticky-header .wp-block-site-title a {
	color: var(--wp--preset--color--contrast);
	font-size: 1.15rem;
	font-weight: 750;
	letter-spacing: -0.015em;
	text-decoration: none;
	white-space: nowrap;
}

.lg-brand__sub {
	color: var(--wp--custom--text--muted);
	font-size: 0.7rem;
	font-weight: 650;
	letter-spacing: 0.08em;
	line-height: 1.2;
	margin: 0;
	text-transform: uppercase;
	white-space: nowrap;
}

/* Live status chip — the same language as the departure card's own chip. */
.lg-live-chip {
	align-items: center;
	background-color: var(--wp--custom--status--success-soft);
	border-radius: var(--wp--custom--radius--full);
	color: var(--wp--custom--status--success-dark);
	display: inline-flex;
	flex-shrink: 0;
	font-size: 0.78rem;
	font-weight: 700;
	gap: 0.4em;
	letter-spacing: 0.01em;
	line-height: 1;
	margin: 0;
	padding: 0.5em 0.8em;
}

.lg-live-chip__dot {
	background-color: currentColor;
	border-radius: 50%;
	display: inline-block;
	height: 6px;
	width: 6px;
}

/* Reuses the ETA chip's pulse from section 3 — one live rhythm, not two. */
@media (prefers-reduced-motion: no-preference) {
	.lg-live-chip__dot {
		animation: lg-pulse 2.4s ease-in-out infinite;
	}
}

/* Below the navigation block's own collapse point the bar is mark + burger. */
@media (max-width: 781px) {
	.lg-brand__sub {
		display: none;
	}
}

@media (max-width: 600px) {
	.lg-live-chip {
		display: none;
	}

	.lg-headerbar {
		min-height: 56px;
	}
}

/*
 * The blur lives on a pseudo-element, deliberately.
 *
 * backdrop-filter on the header itself would make it a containing block for
 * fixed-position descendants — which collapses the navigation block's mobile
 * overlay (position: fixed; inset: 0) down to the height of the header bar.
 * Keeping the filter on ::before leaves the header a plain containing block.
 */
.lg-sticky-header::before {
	background-color: color-mix(in srgb, var(--wp--custom--surface--page) 92%, transparent);
	content: "";
	inset: 0;
	position: absolute;
	z-index: -1;
}

@supports (backdrop-filter: blur(10px)) or (-webkit-backdrop-filter: blur(10px)) {
	.lg-sticky-header::before {
		-webkit-backdrop-filter: blur(10px);
		backdrop-filter: blur(10px);
	}
}

/*
 * Navigation links read as chrome, not as body links — in the top bar only.
 * Inside the open overlay core owns the layout, so these are scoped away from
 * it rather than fighting it.
 */
.wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation-item__content {
	border-radius: var(--wp--custom--radius--full);
	color: var(--wp--custom--text--soft);
	font-size: 0.92rem;
	font-weight: 650;
	padding: 0.55rem 0.85rem;
	text-decoration: none;
	transition: background-color 160ms ease, color 160ms ease;
}

.wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation-item__content:hover,
.wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation-item__content:focus-visible {
	background-color: var(--wp--custom--surface--deep);
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

/* The page you are on is held in warm yellow, the system's "you are here". */
.wp-block-navigation__responsive-container:not(.is-menu-open) .current-menu-item .wp-block-navigation-item__content,
.wp-block-navigation__responsive-container:not(.is-menu-open) .current-menu-item .wp-block-navigation-item__content:hover {
	background-color: var(--wp--preset--color--carris-soft);
	color: var(--wp--preset--color--contrast);
}

/*
 * The burger sits in the same pill language as the links beside it. Scoped to
 * the width where core actually shows it — setting `display` outside that
 * media query would override core's own rule and leak the button onto desktop.
 */
@media (max-width: 599px) {
	.lg-header-end .wp-block-navigation__responsive-container-open {
		align-items: center;
		background-color: var(--wp--custom--surface--deep);
		border-radius: var(--wp--custom--radius--full);
		color: var(--wp--preset--color--contrast);
		height: 44px;
		justify-content: center;
		width: 44px;
	}
}

/* Footer link lists read as navigation, not as prose bullets. */
.wp-block-page-list,
.lg-footer-links {
	list-style: none;
	padding-inline-start: 0;
}

.lg-footer-links a {
	color: var(--wp--custom--text--soft);
	text-decoration: none;
}

.lg-footer-links a:hover,
.lg-footer-links a:focus-visible {
	color: var(--wp--preset--color--contrast);
	text-decoration: underline;
}

/*
 * Legal links live in the footer's bottom rule. Spacing does the separating —
 * a typed or drawn middot between them strands itself at the start of a line
 * as soon as the row wraps on a narrow screen.
 */
.lg-legal-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 1.35rem;
	margin: 0;
}

.lg-legal-links a {
	color: inherit;
	position: relative;
	text-decoration: none;
}

.lg-legal-links a:hover,
.lg-legal-links a:focus-visible {
	color: var(--wp--preset--color--contrast);
	text-decoration: underline;
}


.wp-block-page-list .wp-block-pages-list__item__link {
	color: var(--wp--custom--text--soft);
	text-decoration: none;
}

.wp-block-page-list .wp-block-pages-list__item__link:hover,
.wp-block-page-list .wp-block-pages-list__item__link:focus-visible {
	color: var(--wp--preset--color--contrast);
	text-decoration: underline;
}

/*
 * Mobile overlay menu. The warm ground and ink text come from the navigation
 * block's own overlayBackgroundColor / overlayTextColor attributes in
 * parts/header.html — core sets the overlay background with `inherit`, so
 * styling it from here loses to core's own rules. Only the type scale is set.
 */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	border-bottom: 0;
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 700;
}

/* ------------------------------------------------------------------------- *
 * 10. Accessibility and motion
 * ------------------------------------------------------------------------- */

/* Calm, premium motion — and a visible focus ring everywhere. */
:where(.wp-site-blocks *:focus-visible) {
	outline: 2px solid var(--wp--preset--color--tejo);
	outline-offset: 2px;
}

/* Core outputs the skip link for block themes; give it brand chrome. */
.wp-site-blocks .skip-link:focus,
.skip-link:focus {
	background-color: var(--wp--custom--surface--raised);
	border-radius: var(--wp--custom--radius--sm);
	box-shadow: var(--wp--preset--shadow--md);
	color: var(--wp--preset--color--contrast);
	left: 1rem;
	padding: 0.75rem 1rem;
	top: 1rem;
	z-index: 100000;
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
		transition-duration: 0.01ms !important;
	}
}

/* Honour the operating system's high-contrast preference. */
@media (prefers-contrast: more) {
	:root {
		--wp--custom--line--hairline: var(--wp--custom--line--strong);
		--wp--custom--text--muted: var(--wp--custom--text--soft);
	}
}
