/**
 * Luminous Tables front-end styles.
 *
 * Colors are inherited from the theme rather than declared here. Text uses
 * whatever color the surrounding page uses, and surfaces are neutral
 * translucent layers that read correctly on a light or a dark background
 * without the plugin needing to know which it is on.
 *
 * Only the accent needs to know the mode, so lumtbl-front.js measures the
 * actual rendered background and sets .lumtbl-is-dark accordingly. A theme
 * can also set that class itself, or override any variable below.
 */

.lumtbl {
	--lumtbl-line: rgba(128, 128, 128, 0.35);
	--lumtbl-fill: rgba(128, 128, 128, 0.10);
	--lumtbl-fill-strong: rgba(128, 128, 128, 0.18);
	--lumtbl-accent: #146450;
	--lumtbl-accent-text: #ffffff;
	--lumtbl-shape: 3 / 4;
	--lumtbl-radius: 6px;
	--lumtbl-gap: 1.25rem;
	--lumtbl-muted-opacity: 0.72;

	color: inherit;
	margin: 0 0 2rem;
}

/* Cover art shape, set per table. */
.lumtbl-shape-p34 {
	--lumtbl-shape: 3 / 4;
}

.lumtbl-shape-p23 {
	--lumtbl-shape: 2 / 3;
}

.lumtbl-shape-square {
	--lumtbl-shape: 1 / 1;
}

.lumtbl-shape-l169 {
	--lumtbl-shape: 16 / 9;
}

.lumtbl-shape-natural {
	--lumtbl-shape: auto;
}

/* Fitting the whole image means letterboxing, so the gaps need a surface. */
.lumtbl-fit-fit .lumtbl-media img {
	object-fit: contain;
}

/* Shelf mode: the whole image, dropped to the bottom of its box. Mixed
   proportions then share a baseline instead of floating at different heights,
   and the leftover space sits above the art rather than around it. Dropping
   the media background is what makes the shelf invisible - the art appears to
   stand on the card rather than inside a panel. */
.lumtbl-fit-shelf .lumtbl-media {
	background: transparent;
}

.lumtbl-fit-shelf .lumtbl-media img {
	object-fit: contain;
	object-position: center bottom;
}

/* With no fixed shape, nothing in the chain may force a height. */
.lumtbl-shape-natural .lumtbl-media,
.lumtbl-shape-natural .lumtbl-media > a,
.lumtbl-shape-natural .lumtbl-media img {
	height: auto;
}

/* Tile sizes. The admin picks the starting point; the toolbar can change it. */
.lumtbl-size-small {
	--lumtbl-grid-min: 150px;
	--lumtbl-cover-min: 105px;
}

.lumtbl-size-medium {
	--lumtbl-grid-min: 190px;
	--lumtbl-cover-min: 145px;
}

.lumtbl-size-large {
	--lumtbl-grid-min: 250px;
	--lumtbl-cover-min: 200px;
}

/* Set by the script, or by a theme that manages its own mode. */
.lumtbl.lumtbl-is-dark,
.lumtbl-is-dark .lumtbl {
	--lumtbl-accent: #5fd3a8;
	--lumtbl-accent-text: #08201a;
}

/* ---------------------------------------------------------------- Controls */

.lumtbl-controls {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	padding: 0.9rem 1rem;
	margin-bottom: 1.5rem;
	background: var(--lumtbl-fill);
	border: 1px solid var(--lumtbl-line);
	border-radius: var(--lumtbl-radius);
}

.lumtbl-search {
	width: 100%;
}

.lumtbl-panel {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

/* Filters and tools flow together on as few rows as the width allows. */
.lumtbl-controlrow {
	display: flex;
	flex-wrap: wrap;
	gap: 0.55rem 0.9rem;
	align-items: flex-end;
}

.lumtbl-toolgroup {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
}

.lumtbl-section-label {
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	opacity: var(--lumtbl-muted-opacity);
}

.lumtbl-status {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 0.75rem;
	align-items: center;
}

/* Inputs inherit the page's text color so they never go dark-on-dark. */
.lumtbl-search-input,
.lumtbl-filter-select,
.lumtbl-sort-select {
	font: inherit;
	color: inherit;
	background-color: transparent;
	border: 1px solid var(--lumtbl-line);
	border-radius: var(--lumtbl-radius);
}

.lumtbl-search-input {
	width: 100%;
	padding: 0.55rem 0.7rem;
}

.lumtbl-filter-select,
.lumtbl-sort-select {
	padding: 0.45rem 0.5rem;
	font-size: 0.92rem;
}

/* Native dropdown popups render with system colors, so give the options an
   explicit pair rather than inheriting one the popup will not match. */
.lumtbl-filter-select option,
.lumtbl-sort-select option {
	color: #1c1d20;
	background: #ffffff;
}

.lumtbl-filter,
.lumtbl-sort {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
}

.lumtbl-tool-label {
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	opacity: var(--lumtbl-muted-opacity);
}

.lumtbl-viewtoggle {
	display: inline-flex;
	overflow: hidden;
	border: 1px solid var(--lumtbl-line);
	border-radius: var(--lumtbl-radius);
}

.lumtbl-viewbtn {
	padding: 0.45rem 0.75rem;
	font: inherit;
	font-size: 0.88rem;
	color: inherit;
	cursor: pointer;
	background: transparent;
	border: 0;
}

.lumtbl-viewbtn + .lumtbl-viewbtn {
	border-left: 1px solid var(--lumtbl-line);
}

.lumtbl-viewbtn[aria-pressed="true"] {
	color: var(--lumtbl-accent-text);
	background: var(--lumtbl-accent);
}

.lumtbl-active {
	display: inline-flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.4rem;
}

.lumtbl-active-label {
	font-size: 0.78rem;
	font-weight: 600;
	opacity: var(--lumtbl-muted-opacity);
}

.lumtbl-active-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

.lumtbl-chip {
	display: inline-flex;
	gap: 0.35rem;
	align-items: center;
	padding: 0.25rem 0.55rem;
	font: inherit;
	font-size: 0.82rem;
	color: var(--lumtbl-accent-text);
	cursor: pointer;
	background: var(--lumtbl-accent);
	border: 0;
	border-radius: 99px;
}

.lumtbl-clear {
	padding: 0;
	font: inherit;
	font-size: 0.82rem;
	color: inherit;
	text-decoration: underline;
	cursor: pointer;
	background: none;
	border: 0;
	opacity: var(--lumtbl-muted-opacity);
}

.lumtbl-count {
	margin: 0;
	font-size: 0.82rem;
	opacity: var(--lumtbl-muted-opacity);
}

/* ------------------------------------------------------------------- Key */

.lumtbl-key {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem 0.9rem;
	align-items: center;
	padding-top: 0.6rem;
	margin-top: 0.1rem;
	border-top: 1px solid var(--lumtbl-line);
}

.lumtbl-key-items {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 0.9rem;
}

.lumtbl-key-item {
	display: inline-flex;
	gap: 0.35rem;
	align-items: center;
}

.lumtbl-badge-key {
	width: 1.8rem;
	height: 1.8rem;
	font-size: 1rem;
	color: inherit;
	background: var(--lumtbl-fill-strong);
}

.lumtbl-key-text {
	font-size: 0.82rem;
}

/* --------------------------------------------------------- Collapsing */

.lumtbl-collapse,
.lumtbl-heading {
	display: inline-flex;
	gap: 0.45rem;
	align-items: center;
	align-self: flex-start;
	padding: 0;
	font: inherit;
	font-size: 1.05rem;
	font-weight: 700;
	line-height: 1.2;
	color: inherit;
	text-align: left;
	background: none;
	border: 0;
}

.lumtbl-collapse {
	cursor: pointer;
}

.lumtbl-collapse-icon {
	display: inline-block;
	font-size: 0.8em;
	opacity: var(--lumtbl-muted-opacity);
	transition: transform 0.15s ease;
}

.lumtbl-collapse-count {
	padding: 0 0.35rem;
	font-size: 0.78rem;
	color: var(--lumtbl-accent-text);
	background: var(--lumtbl-accent);
	border-radius: 99px;
}

/* Collapsed hides the filters and the key. The search field, the tools, and
   any active filter chips stay put, so nothing in effect is ever hidden. */
.lumtbl-filters-collapsed .lumtbl-panel {
	display: none;
}

.lumtbl-filters-collapsed .lumtbl-collapse-icon {
	transform: rotate(-90deg);
}

/* ------------------------------------------------------------------ Groups */

.lumtbl-group {
	margin: 0 0 2rem;
}

.lumtbl-group-title {
	display: flex;
	gap: 0.5rem;
	align-items: baseline;
	padding-bottom: 0.4rem;
	margin: 0 0 1rem;
	color: inherit;
	border-bottom: 2px solid var(--lumtbl-line);
}

.lumtbl-group-count {
	font-size: 0.78rem;
	font-weight: 400;
	opacity: var(--lumtbl-muted-opacity);
}

/* ------------------------------------------------------------- Grid layout */

.lumtbl-items {
	display: grid;
	gap: var(--lumtbl-gap);
}

.lumtbl-view-grid .lumtbl-items {
	grid-template-columns: repeat(auto-fill, minmax(min(var(--lumtbl-grid-min, 190px), 100%), 1fr));
}

.lumtbl-view-grid .lumtbl-item {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	color: inherit;
	background: var(--lumtbl-fill);
	border: 1px solid var(--lumtbl-line);
	border-radius: var(--lumtbl-radius);
}

.lumtbl-view-grid .lumtbl-media {
	position: relative;
	aspect-ratio: var(--lumtbl-shape);
	background: var(--lumtbl-fill-strong);
}

/* The wrapping link must fill the media box, or the image inside it has no
   definite height to size against and overflows onto the card body. */
.lumtbl-media > a {
	display: block;
	width: 100%;
	height: 100%;
}

.lumtbl-view-grid .lumtbl-media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.lumtbl-view-grid .lumtbl-body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: 0.35rem;
	padding: 0.8rem;
}

.lumtbl-title {
	margin: 0;
	font-size: 1rem;
	line-height: 1.3;
	color: inherit;
}

.lumtbl-title a {
	color: inherit;
	text-decoration: none;
}

.lumtbl-title a:hover,
.lumtbl-title a:focus {
	text-decoration: underline;
}

.lumtbl-meta {
	margin: 0;
	font-size: 0.85rem;
	opacity: var(--lumtbl-muted-opacity);
}

.lumtbl-excerpt {
	margin: 0;
	font-size: 0.85rem;
	line-height: 1.45;
	opacity: var(--lumtbl-muted-opacity);
}

/* ---------------------------------------------------------------- Badges */

.lumtbl-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.7rem;
	height: 1.7rem;
	font-size: 0.9rem;
	line-height: 1;
	border-radius: 50%;
}

/* The strip sits under the artwork rather than over it, so it can inherit the
   theme's colors instead of carrying a fixed light chip. */
.lumtbl-badgestrip {
	display: flex;
	flex-wrap: wrap;
	gap: 0.35rem;
}

.lumtbl-badge-strip {
	width: 2.2rem;
	height: 2.2rem;
	font-size: 1.2rem;
	color: inherit;
	background: var(--lumtbl-fill-strong);
}

.lumtbl-view-grid .lumtbl-badgestrip {
	padding: 0.7rem 0.8rem 0;
}

/* Keep the strip and the tags below it reading as one block. */
.lumtbl-view-grid .lumtbl-badgestrip + .lumtbl-body {
	padding-top: 0.45rem;
}

.lumtbl-view-covers .lumtbl-badgestrip {
	justify-content: center;
	padding: 0.45rem 0.35rem;
	border-top: 1px solid var(--lumtbl-line);
}

.lumtbl-view-covers .lumtbl-badge-strip {
	width: 1.95rem;
	height: 1.95rem;
	font-size: 1.05rem;
}

/* List view has its own labelled treatment. */
.lumtbl-view-list .lumtbl-badgestrip {
	display: none;
}

/* -------------------------------------------------------------- Tag chips */

.lumtbl-tags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem;
}

.lumtbl-tag {
	display: inline-block;
	padding: 0.15rem 0.45rem;
	font: inherit;
	font-size: 0.78rem;
	color: inherit;
	background: var(--lumtbl-fill-strong);
	border: 0;
	border-radius: 4px;
}

.lumtbl-tag-button {
	cursor: pointer;
}

.lumtbl-tag-button:hover,
.lumtbl-tag-button:focus {
	color: var(--lumtbl-accent-text);
	background: var(--lumtbl-accent);
}

/* ------------------------------------------------------------- List layout */

.lumtbl-view-list .lumtbl-items {
	grid-template-columns: 1fr;
	gap: 0;
}

.lumtbl-view-list .lumtbl-item {
	display: flex;
	gap: 1rem;
	align-items: flex-start;
	padding: 0.85rem 0.5rem;
	color: inherit;
	border-bottom: 1px solid var(--lumtbl-line);
}

/* The list thumbnail follows the same shape, sized from its width. */
.lumtbl-view-list .lumtbl-media {
	position: relative;
	flex: 0 0 56px;
	width: 56px;
	aspect-ratio: var(--lumtbl-shape);
}

.lumtbl-view-list .lumtbl-media > a {
	width: 100%;
	height: 100%;
}

.lumtbl-view-list .lumtbl-media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: 3px;
}

.lumtbl-view-list.lumtbl-fit-fit .lumtbl-media img {
	object-fit: contain;
}

.lumtbl-view-list.lumtbl-fit-shelf .lumtbl-media img {
	object-fit: contain;
	object-position: center bottom;
}

/* List view has room, so badges get a readable size and their name in words
   rather than relying on the icon alone. */
.lumtbl-badges-labelled {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 0.85rem;
}

.lumtbl-badge-labelled {
	display: inline-flex;
	gap: 0.4rem;
	align-items: center;
}

.lumtbl-view-list .lumtbl-badge-labelled .lumtbl-badge {
	width: 2.1rem;
	height: 2.1rem;
	font-size: 1.25rem;
	color: inherit;
	background: var(--lumtbl-fill-strong);
}

.lumtbl-badge-text {
	font-size: 0.85rem;
	white-space: nowrap;
}

@media (max-width: 600px) {
	.lumtbl-badge-text {
		white-space: normal;
	}
}

.lumtbl-view-list .lumtbl-body {
	display: grid;
	flex: 1;
	grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
	gap: 0.35rem 1rem;
	align-items: start;
}

.lumtbl-view-list .lumtbl-title {
	grid-column: 1 / -1;
}

.lumtbl-cell {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	font-size: 0.85rem;
}

.lumtbl-cell-label {
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	opacity: var(--lumtbl-muted-opacity);
}

.lumtbl-cell-value a {
	color: var(--lumtbl-accent);
}

/* ------------------------------------------------------------ Covers layout */

/* Artwork only. The title stays in the document for screen readers and search
   engines, and surfaces as a caption on hover and keyboard focus. */
.lumtbl-view-covers .lumtbl-items {
	grid-template-columns: repeat(auto-fill, minmax(min(var(--lumtbl-cover-min, 145px), 100%), 1fr));
	gap: 0.75rem;
}

.lumtbl-view-covers .lumtbl-item {
	position: relative;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	color: inherit;
	background: var(--lumtbl-fill);
	border: 1px solid var(--lumtbl-line);
	border-radius: var(--lumtbl-radius);
}

.lumtbl-view-covers .lumtbl-media {
	aspect-ratio: var(--lumtbl-shape);
	background: var(--lumtbl-fill-strong);
}

.lumtbl-view-covers .lumtbl-media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The title is read by screen readers and indexed, but never painted over the
   artwork - an invisible layer there would swallow clicks on the cover. The
   name is available as the link's native tooltip instead. */
.lumtbl-view-covers .lumtbl-body {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Everything except the title is noise at this size. */
.lumtbl-view-covers .lumtbl-meta,
.lumtbl-view-covers .lumtbl-excerpt,
.lumtbl-view-covers .lumtbl-cell {
	display: none;
}

/* Destinations sit under the cover, centred. */
.lumtbl-view-covers .lumtbl-links {
	justify-content: center;
	gap: 0.25rem 0.6rem;
	padding: 0.4rem 0.35rem;
	border-top: 1px solid var(--lumtbl-line);
}

/* A small tile has no room for words, so the icon carries it and the name
   stays available to screen readers and as a tooltip. Large tiles show both. */
.lumtbl-view-covers:not(.lumtbl-size-large) .lumtbl-linkicon-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	white-space: nowrap;
}

.lumtbl-view-covers .lumtbl-linkicon-mark {
	font-size: 1.15rem;
}

.lumtbl-view-covers .lumtbl-linkicon {
	font-size: 0.78rem;
}

/* A record with no artwork would be an empty tile, so it keeps its caption. */
/* With no artwork there is nothing to show but the title, so it becomes the
   tile rather than leaving a blank square. */
.lumtbl-view-covers .lumtbl-no-media .lumtbl-body {
	position: static;
	display: flex;
	align-items: center;
	width: auto;
	height: auto;
	min-height: 5.5rem;
	padding: 0.6rem;
	overflow: visible;
	clip: auto;
	clip-path: none;
	white-space: normal;
}

.lumtbl-view-covers .lumtbl-no-media .lumtbl-title {
	font-size: 0.85rem;
	line-height: 1.3;
}

.lumtbl-view-covers .lumtbl-no-media .lumtbl-title,
.lumtbl-view-covers .lumtbl-no-media .lumtbl-title a {
	color: inherit;
}

/* ------------------------------------------------------- View-only toggles */

.lumtbl-view-grid .lumtbl-only-list,
.lumtbl-view-covers .lumtbl-only-list,
.lumtbl-view-list .lumtbl-only-grid {
	display: none;
}

.lumtbl-empty {
	padding: 2rem 0;
	text-align: center;
	opacity: var(--lumtbl-muted-opacity);
}

.lumtbl-active[hidden],
.lumtbl-item[hidden],
.lumtbl-group[hidden],
.lumtbl-flat[hidden] {
	display: none !important;
}

/* ------------------------------------------------------------ Accessibility */

.lumtbl .screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	white-space: nowrap;
}

.lumtbl button:focus-visible,
.lumtbl a:focus-visible,
.lumtbl select:focus-visible,
.lumtbl input:focus-visible {
	outline: 2px solid var(--lumtbl-accent);
	outline-offset: 2px;
}

@media (max-width: 600px) {
	.lumtbl-view-grid .lumtbl-items {
		grid-template-columns: repeat(auto-fill, minmax(min(var(--lumtbl-grid-min, 190px), 47%), 1fr));
	}

	.lumtbl-view-list .lumtbl-body {
		grid-template-columns: 1fr;
	}
}

.lumtbl-sizetoggle {
	display: inline-flex;
	overflow: hidden;
	border: 1px solid var(--lumtbl-line);
	border-radius: var(--lumtbl-radius);
}

.lumtbl-sizebtn {
	min-width: 2.1rem;
	padding: 0.45rem 0.5rem;
	font: inherit;
	font-size: 0.88rem;
	color: inherit;
	cursor: pointer;
	background: transparent;
	border: 0;
}

.lumtbl-sizebtn + .lumtbl-sizebtn {
	border-left: 1px solid var(--lumtbl-line);
}

.lumtbl-sizebtn[aria-pressed="true"] {
	color: var(--lumtbl-accent-text);
	background: var(--lumtbl-accent);
}

/* Nothing to resize in list view. */
.lumtbl-view-list .lumtbl-sizewrap {
	display: none;
}

/* The grouping toggle sits beside the view toggle and shares its treatment. */
.lumtbl-groupbtn {
	padding: 0.45rem 0.75rem;
	font: inherit;
	font-size: 0.88rem;
	color: inherit;
	cursor: pointer;
	background: transparent;
	border: 1px solid var(--lumtbl-line);
	border-radius: var(--lumtbl-radius);
}

.lumtbl-groupbtn[aria-pressed="true"] {
	color: var(--lumtbl-accent-text);
	background: var(--lumtbl-accent);
	border-color: var(--lumtbl-accent);
}

/* A key entry can explain itself, which is the point of a key. */
.lumtbl-key-wording {
	display: flex;
	flex-direction: column;
	line-height: 1.3;
}

.lumtbl-key-note {
	font-size: 0.75rem;
	opacity: var(--lumtbl-muted-opacity);
}

.lumtbl-key-item {
	align-items: center;
}

/* A link field renders as its icon plus its name, so a row of them reads as a
   set of destinations rather than a column of identical "Link" text. */
.lumtbl-linkicon {
	display: inline-flex;
	gap: 0.3rem;
	align-items: center;
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--lumtbl-accent);
	text-decoration: none;
}

.lumtbl-linkicon:hover,
.lumtbl-linkicon:focus {
	text-decoration: underline;
}

.lumtbl-linkicon-mark {
	font-size: 1.05rem;
	line-height: 1;
}

/* The line under a title: an artist, an author, a developer. */
.lumtbl-subtitle {
	margin: 0;
	font-size: 0.85rem;
	font-weight: 600;
	opacity: var(--lumtbl-muted-opacity);
}

/* In Covers view the artwork identifies the record, so the subtitle is only
   needed where there is none and the title would stand alone. */
.lumtbl-view-covers .lumtbl-no-media .lumtbl-body {
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	gap: 0.2rem;
}

.lumtbl-view-covers .lumtbl-no-media .lumtbl-subtitle {
	font-size: 0.78rem;
}

/* Destinations sit together and look alike, so the difference between them is
   their wording rather than their styling. */
.lumtbl-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.3rem 0.85rem;
	margin-top: auto;
}

.lumtbl-view-grid .lumtbl-links {
	padding: 0 0.8rem 0.8rem;
}

/* The record's own page leads, so it carries the weight. */
.lumtbl-linkicon-primary {
	font-weight: 700;
}

.lumtbl-links .lumtbl-linkicon:not(.lumtbl-linkicon-primary) {
	font-weight: 500;
	opacity: 0.9;
}
