/* The front end shared by the main menu, the join screen and the in-game menu: big type, one accent block for focus, flat panels. */
/* Every class here is a shared primitive or one of its modifiers: a page's own <style> may tune one in place, but a page-local class never reuses a name used here (a page's .link once undid .field's padding as .field.link). */
/* The accent is acid lime unless Community's admin set another: theme.js puts that on the page as --theme-*, before the first paint. */
:root, :host { --text: #f3f1ec; --dim: #8f8c86; --faint: rgba(243,241,236,.5); --line: rgba(255,255,255,.12); --accent: var(--theme-accent, #c4f03c); --accent-hover: var(--theme-hover, #d7f77a); --on-accent: var(--theme-on-accent, #0b0b0c); --ok: #7fe0a0; --err: #ff6b5b; --shade: rgba(0,0,0,.55); --pane: rgba(9,10,12,.9); --display: "Archivo Expanded", "Helvetica Neue", Arial, system-ui, sans-serif; --body: Archivo, "Helvetica Neue", Arial, sans-serif; }

@font-face { font-family: "Archivo Expanded"; src: url(/v/32c0421c00/fonts/archivo-expanded.woff2) format("woff2"); font-weight: 600 900; font-display: swap; }
@font-face { font-family: Archivo; src: url(/v/32c0421c00/fonts/archivo.woff2) format("woff2"); font-weight: 400 700; font-display: swap; }

.backdrop { position: fixed; inset: 0; background: #1b1b1d; overflow: hidden; }
.backdrop :is(img, video) { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 1.2s ease; }
.backdrop img.on { opacity: 1; }
.backdrop::after { content: ""; position: absolute; inset: 0; background: var(--shade); transition: background-color .4s ease; }
/* Every other screen keeps the stills, darker, so its text reads as easily as the title's. */
body:not(:has(.screen.title:not([hidden]))) .backdrop::after { background: rgba(9,10,12,.82); }

.logo { display: block; height: 48px; width: auto; max-width: 100%; aspect-ratio: 65 / 5; align-self: flex-start; }
.logo rect { fill: var(--text); }
.logo rect.block { fill: var(--accent); }
/* Morph's face on the O: dark eyes with a glint, and a darker bottom row in whatever the accent is. */
.logo rect.shade { fill: #000; fill-opacity: .27; }
.logo rect.eye { fill: var(--on-accent); }

.front { position: fixed; inset: 0; display: flex; flex-direction: column; padding: 96px 96px 72px; overflow-y: auto; scrollbar-width: none; }
/* Every menu is one group in the middle, over the stills, like the title screen; a page (Community, a world) is wider and starts at the top. Auto margins rather than centering the flex box, so a long screen scrolls instead of being cut off at the top. */
.front:has(> .screen) { align-items: center; }
.front > .screen:not(.page) { margin-block: auto; align-items: center; text-align: center; }
.front > .screen.page { width: min(1180px, 100%); }
/* Community spreads wider on a big screen, so more of its worlds show at once. */
.front > .screen.page:has(> .community-bar) { width: min(1600px, 100%); }
.screen:not(.page, :has(.item.pictured)) .items { align-items: center; }
.screen:not(.page) .item:not(.pictured, .entry) { width: auto; padding-right: 32px; }
/* A centred entry is as wide as what is in it, so its mark sits right beside the text; a picture's row renamed in place keeps its list's width and left edge. */
.screen:not(.page) > .item.entry:not(.pictured), .screen:not(.page) .items > .item.entry:not(.pictured) { width: auto; max-width: 100%; align-self: center; padding-right: 32px; }
.screen:not(.page) .item.entry:not(.pictured) input { field-sizing: content; min-width: 6ch; max-width: min(900px, calc(100vw - 256px)); text-align: center; }
.screen:not(.page) .lead { max-width: 560px; }
.screen.title { align-items: center; text-align: center; }
.screen.title .logo { align-self: center; }
.screen.title .items { align-items: center; }
.screen.title .item { width: auto; padding-right: 32px; color: rgba(243,241,236,.92); }
.screen.title :is(.item, .lead) { text-shadow: 0 1px 3px rgba(0,0,0,.8); }
.screen.title .item:focus { color: var(--text); }
/* Play is what the title is for: the one solid button, over Settings and Quit. */
.screen.title .primary { min-width: 300px; min-height: 76px; margin-bottom: 20px; font-size: 30px; }
.screen { display: flex; flex-direction: column; width: min(640px, 100%); }
/* A menu's title may run wider than its entries, so a world's name stays on one or two lines. */
.screen:not(.page) > h1 { width: min(1100px, calc(100vw - 192px)); align-self: center; font-size: clamp(40px, 5vw, 64px); text-wrap: balance; }
.screen > h1, .screen-title { margin: 0 0 40px; font: 800 64px/1 var(--display); letter-spacing: .02em; text-transform: uppercase; overflow-wrap: normal; word-break: keep-all; }

.items { display: flex; flex-direction: column; align-items: flex-start; }
.item { position: relative; display: flex; align-items: baseline; gap: 20px; width: 100%; margin: 0; padding: 8px 0 8px 32px; background: none; border: 0; border-radius: 0; color: var(--faint); font: 800 34px/1.1 var(--display); letter-spacing: .03em; text-transform: uppercase; text-align: left; cursor: pointer; outline: none; white-space: nowrap; }
.item::before { content: ""; position: absolute; left: 0; top: 50%; width: 14px; height: 14px; translate: 0 -50%; background: var(--accent); scale: 0; transition: scale .12s ease-out; }
.item:hover { background: none; color: var(--faint); }
.item:focus-visible, .item:focus, .item.active { color: var(--text); background: none; }
.item:focus::before, .item.active::before { scale: 1; }
.item:disabled { opacity: .3; pointer-events: none; }
.item .value { color: var(--dim); font-size: 16px; font-weight: 700; letter-spacing: .12em; overflow: hidden; text-overflow: ellipsis; }
.item .value.live { color: var(--accent); }
.item .value:empty { display: none; }
/* A text entry that is itself a menu entry: what is typed is the entry. */
.item.entry { cursor: text; }
.item.entry:focus-within { color: var(--text); }
.item.entry:focus-within::before { scale: 1; }
.item.entry input { all: unset; width: 100%; padding-bottom: 4px; border-bottom: 2px solid rgba(255,255,255,.22); font: inherit; letter-spacing: inherit; text-transform: none; caret-color: var(--accent); transition: border-color .12s ease-out; }
.item.entry input:focus { border-color: var(--accent); }
.item.entry input::placeholder { color: var(--faint); opacity: 1; text-transform: uppercase; }
.item.danger:focus { color: var(--err); }
.gap { height: 24px; flex: none; }

/* Back, in the top left corner, for the mouse; Esc does the same. */
.front > .back { position: absolute; top: 28px; left: 40px; margin: 0; z-index: 2; }
.back { align-self: flex-start; display: flex; align-items: center; gap: 12px; margin: 0 0 24px; padding: 8px 0; background: none; border: 0; border-radius: 0; color: var(--dim); font: 700 14px/1 var(--display); letter-spacing: .16em; text-transform: uppercase; cursor: pointer; outline: none; }
.back:hover, .back:focus-visible { color: var(--text); background: none; }
.back kbd { font: inherit; font-size: 11px; border: 1px solid rgba(255,255,255,.35); padding: 3px 6px; color: var(--text); }
.lead { margin: -16px 0 32px; color: var(--text); font-size: 18px; }

/* A setting: its name on the left, its value on the right; a long row of choices wraps under the name. */
.field { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; width: 100%; min-height: 64px; padding: 0 0 0 32px; position: relative; border-bottom: 1px solid var(--line); }
.field::before { content: ""; position: absolute; left: 0; top: 50%; width: 14px; height: 14px; translate: 0 -50%; background: var(--accent); scale: 0; transition: scale .12s ease-out; }
.field:focus-within::before { scale: 1; }
.field > span:first-child { flex: 1; min-width: 0; text-align: left; font: 700 20px/1.2 var(--display); letter-spacing: .06em; text-transform: uppercase; color: var(--faint); }
.field:focus-within > span:first-child { color: var(--text); }
.field input:is([type=text], [type=password]) { width: 60%; background: none; border: 0; border-radius: 0; color: var(--text); font: 700 24px/1.2 var(--display); padding: 12px 0; text-align: right; outline: none; }
.field input:is([type=text], [type=password])::placeholder { color: rgba(255,255,255,.3); text-decoration: underline 1px rgba(255,255,255,.3); text-underline-offset: 6px; }
.field:has(.choices) { padding-block: 10px; }

.field .range { display: flex; align-items: center; gap: 12px; }
/* A square accent thumb on a thin track, like every other control here. */
.field input[type=range] { width: 180px; height: 24px; margin: 0; background: none; appearance: none; cursor: pointer; outline: none; }
.field input[type=range]::-webkit-slider-runnable-track { height: 2px; background: rgba(255,255,255,.28); }
.field input[type=range]::-moz-range-track { height: 2px; background: rgba(255,255,255,.28); }
.field input[type=range]::-moz-range-progress { height: 2px; background: var(--accent); }
.field input[type=range]::-webkit-slider-thumb { appearance: none; width: 14px; height: 14px; margin-top: -6px; border: 0; border-radius: 0; background: var(--accent); }
.field input[type=range]::-moz-range-thumb { width: 14px; height: 14px; border: 0; border-radius: 0; background: var(--accent); }
.field input[type=range]:focus-visible::-webkit-slider-thumb { outline: 2px solid var(--text); outline-offset: 2px; }
.field input[type=range]:focus-visible::-moz-range-thumb { outline: 2px solid var(--text); outline-offset: 2px; }
.field .percent { display: flex; align-items: baseline; padding: 6px 0; border-bottom: 1px solid rgba(255,255,255,.28); color: var(--dim); font: 700 18px/1.2 var(--display); }
.field .percent:focus-within { border-color: var(--accent); }
.field input[type=number] { width: 44px; padding: 0 2px 0 0; background: none; border: 0; color: var(--text); font: inherit; text-align: right; outline: none; -moz-appearance: textfield; }
.field input[type=number]::-webkit-inner-spin-button { display: none; }

/* Settings: its categories as tabs across the top, then rows of one height, the name on the left and its control on the right. */
.settings { display: flex; flex-direction: column; width: min(760px, 100%); }
/* All six tabs on one row in its 760px. */
.settings > .tabs { justify-content: center; gap: 4px 24px; margin: 0 0 24px; }
/* Every tab seven rows tall, Controls' longer list scrolling inside it, so switching never moves the tabs. */
.settings > [data-panel] { width: 100%; min-height: calc(7 * 72px); }
.settings > [data-panel=controls] { height: calc(7 * 72px); overflow-y: auto; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.28) transparent; }
.settings .field { min-height: 72px; outline: none; }
.settings .field input:is([type=text], [type=password]) { width: 45%; }
/* One dim line under a row's label saying what it does. */
.field .hint { display: block; margin-top: 4px; font: 400 14px/1.3 var(--body); letter-spacing: normal; text-transform: none; color: var(--dim); }
.field .hint a { color: var(--text); text-underline-offset: 3px; }
.settings button.field { background: none; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; outline: none; }
.settings button.field:is(:hover, :focus-visible)::before { scale: 1; }
.settings button.field:is(:hover, :focus-visible) > span:first-child { color: var(--text); }
.field .value { margin-left: auto; font: 700 20px/1.2 var(--display); letter-spacing: .04em; color: var(--text); }
.field.opens .value::after { content: "›"; margin-left: 14px; color: var(--accent); }
.field .error { flex-basis: 100%; margin: -6px 0 12px; text-align: right; }
.field .error:empty { display: none; }
.field .caps { display: flex; gap: 6px; }
.field .caps kbd, .field .keycap > * { min-width: 34px; padding: 7px 9px; border: 1px solid rgba(255,255,255,.35); font: 700 13px/1 var(--display); letter-spacing: .08em; text-align: center; text-transform: uppercase; color: var(--text); }
/* Controls: the engine's actions, then each mod's under its name; each key is a cap that, clicked, waits for the next key or mouse button. */
.settings .group { margin: 32px 0 0; padding: 0 0 12px 32px; border-bottom: 1px solid var(--line); font: 700 12px/1 var(--display); letter-spacing: .2em; text-transform: uppercase; text-align: left; color: var(--dim); }
.settings .group:first-child { margin-top: 8px; }
.field .keycap { display: flex; margin-left: auto; padding: 0; background: none; border: 0; border-radius: 0; cursor: pointer; outline: none; }
.field .keycap:is(:hover, :focus-visible) > *, .field.capturing .keycap > * { border-color: var(--accent); }
.field.capturing .keycap > * { color: var(--accent); }
.field .hint.clash { color: var(--err); }
.field .quiet { padding-block: 14px; }
/* Delete account stands apart under the rest, quiet until pointed at. */
.settings .field.danger { margin-top: 40px; min-height: 56px; border-bottom: 0; }
.settings .field.danger > span:first-child { font-size: 14px; letter-spacing: .14em; color: var(--dim); }
.settings .field.danger:is(:hover, :focus-visible) > span:first-child { color: var(--err); }
.settings .field.danger::before { background: var(--err); }

/* A setting's few values, every one in view on one dark plate, the chosen one a solid accent block like the logo's O. */
.choices { display: inline-flex; flex-wrap: wrap; margin-left: auto; background: rgba(9,10,12,.62); border: 1px solid rgba(255,255,255,.14); }
.choices button { min-height: 44px; padding: 0 18px; background: none; border: 0; border-radius: 0; color: var(--dim); font: 700 13px/1 var(--display); letter-spacing: .12em; text-transform: uppercase; white-space: nowrap; cursor: pointer; outline: none; transition: color .12s ease-out, background-color .12s ease-out; }
.choices button + button { box-shadow: inset 1px 0 rgba(255,255,255,.1); }
.choices button:hover { color: var(--text); }
.choices button[aria-checked=true] { background: var(--accent); color: var(--on-accent); box-shadow: none; }
.choices button:focus-visible { outline: 2px solid var(--text); outline-offset: -4px; }
.choices button[aria-checked=true]:focus-visible { outline-color: var(--on-accent); }

.copy-row { display: flex; align-items: center; gap: 16px; width: 100%; text-align: left; min-height: 56px; border-bottom: 1px solid var(--line); }
.copy-row > span { width: 150px; flex: none; color: var(--dim); font: 700 12px/1.2 var(--display); letter-spacing: .14em; text-transform: uppercase; }
/* Paths and commands are typed as they are spelled, whatever the text around them does. */
code { text-transform: none; letter-spacing: normal; }
.copy-row code { flex: 1; min-width: 0; font: 13px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; color: #d9d6cf; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.copy-row .tabs { margin: 0 0 0 auto; gap: 4px 24px; }
.copy-row button[data-copy] { min-width: 88px; text-align: right; }
/* Streamer mode hides what a row copies; its Copy stays where it was. */
.copy-row > [hidden] + button { margin-left: auto; }
.copy-row button, .quiet { flex: none; background: none; border: 0; padding: 10px 4px; color: var(--dim); font: 700 12px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; cursor: pointer; outline: none; }
.copy-row button:hover, .copy-row button:focus, .quiet:hover, .quiet:focus { color: var(--text); background: none; }
.copy-row button.danger:hover, .copy-row button.danger:focus { color: var(--err); }
/* The small text buttons get a mark on hover or focus, like the menu's entries, taking no room. */
:is(.back, .quiet, .copy-row button)::before { content: ""; display: inline-block; width: 6px; height: 6px; margin: 0 8px 0 -14px; vertical-align: middle; background: var(--accent); scale: 0; transition: scale .12s ease-out; }
:is(.back, .quiet, .copy-row button):is(:hover, :focus-visible)::before { scale: 1; }
/* Tag-qualified to outrank the :is() rule above, whose .copy-row button argument sets its specificity. */
.back:is(a, button)::before { margin-right: -4px; }

/* A world as a row with its picture: dim until the row is picked, like its name. */
.item.pictured { align-items: center; white-space: normal; }
/* Picture rows need more than a menu's width, so names fit before the status. */
.screen:has(.item.pictured) { width: min(960px, 100%); }
/* Their lists fill that column, so a long name ends in an ellipsis instead of widening the list past the window. */
.screen:has(.item.pictured) > .items { align-self: stretch; }
.item.pictured .what { flex: 1; min-width: 0; font-size: 26px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.item.pictured small { display: block; margin-top: 6px; color: var(--dim); font: 600 15px/1.3 var(--body); letter-spacing: normal; text-transform: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cover { width: 160px; aspect-ratio: 16 / 9; flex: none; background: #1b1c1f; opacity: .6; transition: opacity .12s ease-out; }
.cover img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* A world without a picture of its own shows the hub, darkened. */
.cover:not(:has(> img:not(.motion), > .motion.on)) { background: linear-gradient(rgba(9,10,12,.55), rgba(9,10,12,.55)), url(stills/world.webp) center / cover; }
/* A live world without a picture of its own on Community stays its plain fill instead: the hub is another world's. */
.cover.live:not(:has(> img:not(.motion), > .motion.on)) { background: #1b1c1f; }
/* A tile's picture fades in once it is in (front.js tilePicture); until then its empty poster keeps the cover its plain fill, at the size the picture will be. */
.cover > .poster { opacity: 0; transition: opacity .18s ease-out; }
.cover > .poster.on { opacity: 1; }
.item.pictured:is(:focus, :focus-visible, .active) .cover, .item.renaming .cover { opacity: 1; }
.item.renaming input, .item.renaming input:not(:placeholder-shown) { flex: 1; min-width: 0; font-size: 26px; letter-spacing: .03em; }

.error { color: var(--err); min-height: 1.4em; margin-top: 16px; font: 600 14px/1.4 var(--display); }
.hints { position: fixed; left: 96px; right: 96px; bottom: 36px; display: flex; flex-wrap: wrap; gap: 10px 28px; color: var(--dim); font: 700 12px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; pointer-events: none; }
.hints kbd { font: inherit; display: inline-block; min-width: 24px; text-align: center; border: 1px solid rgba(255,255,255,.35); padding: 4px 6px; margin-right: 8px; color: var(--text); }

@media (prefers-reduced-motion: reduce) { .backdrop img { transition: none; } .item::before, .field::before, :is(.back, .quiet, .copy-row button)::before, .choices button, .tabs button::before { transition: none; } }

/* The one thing a screen is for: a solid accent block, like the logo's O. */
.primary { display: inline-flex; align-items: center; justify-content: center; gap: 14px; min-height: 64px; padding: 0 44px; background: var(--accent); border: 0; border-radius: 0; color: var(--on-accent); font: 800 22px/1 var(--display); letter-spacing: .06em; text-transform: uppercase; text-decoration: none; cursor: pointer; outline: none; white-space: nowrap; transition: background-color .12s ease-out, translate .12s ease-out; }
.primary:hover { background: var(--accent-hover); }
.primary:focus-visible { outline: 3px solid var(--text); outline-offset: 4px; }
.primary:active { translate: 0 1px; }
.primary:disabled { opacity: .45; cursor: default; }
.primary.danger { background: var(--err); color: #0b0b0c; }
.primary svg { width: 20px; height: 20px; fill: currentColor; flex: none; }
/* Everything else a screen offers: dark plates over the picture, with an icon where one says it faster. */
.action { display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 48px; padding: 0 20px; background: rgba(9,10,12,.62); border: 1px solid rgba(255,255,255,.14); border-radius: 0; color: var(--text); font: 700 14px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; text-decoration: none; cursor: pointer; outline: none; white-space: nowrap; transition: border-color .12s ease-out, background-color .12s ease-out; }
.action:hover { border-color: rgba(255,255,255,.5); background: rgba(9,10,12,.8); }
.action:focus-visible { border-color: var(--accent); }
.action.on { border-color: var(--accent); color: var(--accent); }
/* Where things stand rather than something to do: no hover, no pointer. */
.action.state { cursor: default; pointer-events: none; }
.action.state:not(.on) { color: var(--dim); }
.action:disabled { opacity: .45; cursor: default; }
.action svg { width: 16px; height: 16px; fill: currentColor; flex: none; }
.action .count { color: var(--dim); }
.action .count:empty { display: none; }
.action.on .count { color: inherit; }
.action.icon { width: 48px; padding: 0; }
.action.danger:hover { border-color: var(--err); color: var(--err); }
.actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px; }
.publish-line { justify-content: flex-start; margin: 8px 0 32px; }

/* A text field in a form: its name above, a line under what is typed, accent when it has the focus. */
.line { display: flex; flex-direction: column; gap: 8px; width: 100%; text-align: left; }
.line > span { color: var(--dim); font: 700 12px/1 var(--display); letter-spacing: .16em; text-transform: uppercase; }
.line input { width: 100%; padding: 10px 0 12px; background: none; border: 0; border-bottom: 2px solid rgba(255,255,255,.22); border-radius: 0; color: var(--text); font: 600 22px/1.2 var(--body); caret-color: var(--accent); outline: none; transition: border-color .12s ease-out; }
.line input:focus { border-bottom-color: var(--accent); }
.line:focus-within > span { color: var(--text); }
.form { display: flex; flex-direction: column; align-items: stretch; gap: 28px; width: min(440px, 100%); }
.form .primary { margin-top: 12px; }
.switch { margin: 32px 0 0; color: var(--dim); font-size: 15px; }
.switch :is(a, button) { margin-left: 6px; padding: 0; background: none; border: 0; color: var(--text); font: 700 13px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; text-decoration: none; border-bottom: 2px solid var(--accent); cursor: pointer; outline: none; }
.switch :is(a, button):is(:hover, :focus-visible) { color: var(--accent); }
/* A line for what only the app does: what it needs, then Open and Download; once the app didn't open, it says so in the text's own colour. */
.needs-app { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 22px; }
.needs-app > :is(a, button) { margin-left: 0; }
.needs-app.missed > span { color: var(--text); }

/* A page's own header: its title in the middle, tabs under it, what it does on the right. */
.page-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px 24px; width: 100%; margin: 0 0 28px; }
/* About the size of the app's Play tabs; on a phone small enough that "Notifications" fits the width. */
.page-head h1 { margin: 0; font: 800 32px/1 var(--display); letter-spacing: .02em; text-transform: uppercase; }
@media (max-width: 560px) { .page-head h1 { font-size: 26px; } }
.page-head .tools { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.tabs { display: flex; justify-content: flex-start; flex-wrap: wrap; gap: 4px 32px; margin: 0 0 36px; }
.tabs button { position: relative; padding: 10px 0; background: none; border: 0; color: var(--dim); font: 700 14px/1 var(--display); letter-spacing: .16em; text-transform: uppercase; cursor: pointer; outline: none; }
.tabs button:is(:hover, :focus-visible) { color: var(--text); }
.tabs button[aria-selected=true] { color: var(--text); }
.tabs button[aria-selected=true]::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px; background: var(--accent); }
/* The keyboard's place among the tabs: the small accent mark the text buttons get, taking no room. */
.tabs button::before { content: ""; display: inline-block; width: 6px; height: 6px; margin: 0 8px 0 -14px; vertical-align: middle; background: var(--accent); scale: 0; transition: scale .12s ease-out; }
.tabs button:focus-visible::before { scale: 1; }
/* A menu's tabs sit in its middle, like everything else on it. */
.screen:not(.page) > .tabs { justify-content: center; margin-bottom: 8px; }
/* Tabs and the search that narrows what they show, in one row. */
.tab-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px; width: 100%; margin: 0 0 36px; }
.tab-bar .tabs { margin: 0; }
/* Search: a magnifier, what to look for, and × to empty it. */
.search { position: relative; display: flex; align-items: center; width: min(340px, 100%); height: 44px; background: rgba(9,10,12,.62); border: 1px solid rgba(255,255,255,.14); cursor: text; transition: border-color .12s ease-out; }
.search:hover { border-color: rgba(255,255,255,.3); }
.search:focus-within { border-color: var(--accent); }
.search > svg { position: absolute; left: 14px; top: 50%; width: 16px; height: 16px; translate: 0 -50%; fill: none; stroke: var(--dim); stroke-width: 2; pointer-events: none; }
.search:focus-within > svg { stroke: var(--text); }
.search input { flex: 1; min-width: 0; height: 100%; padding: 0 4px 0 42px; background: none; border: 0; border-radius: 0; outline: none; color: var(--text); font: 500 15px/1 var(--body); caret-color: var(--accent); appearance: none; }
.search input::placeholder { color: var(--dim); opacity: 1; }
.search input::-webkit-search-cancel-button, .search input::-webkit-search-decoration { appearance: none; }
.search button { flex: none; width: 40px; height: 100%; padding: 0; background: none; border: 0; color: var(--dim); font: 400 22px/1 var(--body); cursor: pointer; outline: none; }
.search button:is(:hover, :focus-visible) { color: var(--text); }
.search button:focus-visible { box-shadow: inset 0 -3px var(--accent); }
.search:has(input:placeholder-shown) button { visibility: hidden; }
/* Community's toolbar (front.js communityBar): the tabs and the search on one row, under it one line with the filters on the left and the sorts on the right, and Filters' panel under that while it is open. */
.community-bar { width: 100%; margin: 0 0 28px; }
.community-bar .tab-bar { margin: 0; padding: 0 0 6px; }
.community-bar .tabs { gap: 4px 28px; }
.community-bar .tabs button { padding: 10px 0; font-size: 15px; letter-spacing: .12em; }
.community-bar .search { width: min(360px, 100%); height: 40px; }
/* On a phone the tabs keep to one line. */
@media (max-width: 560px) { .community-bar .tabs { gap: 4px 20px; } .community-bar .tabs button { font-size: 14px; letter-spacing: .1em; } }
.bar-line { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 24px; padding: 8px 0 10px; border-bottom: 1px solid var(--line); }
/* A tab with no filters or sorts (People) has no line for them. */
.bar-line:has(> .bar-filters:empty + .bar-sort:empty) { display: none; }
.bar-filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.bar-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0 18px; }
.bar-row:has(.chip) { gap: 8px; }
.bar-row > span { color: var(--dim); font: 500 14px/1 var(--body); }
/* Words to choose between, a sort or a filter's row: dim until chosen, the chosen one underlined in the accent. */
.bar-row button:not(.chip) { position: relative; padding: 8px 0; background: none; border: 0; color: var(--dim); font: 600 14px/1 var(--body); white-space: nowrap; cursor: pointer; outline: none; transition: color .12s ease-out; }
.bar-row button:not(.chip):is(:hover, :focus-visible, [aria-pressed=true]) { color: var(--text); }
.bar-row button:not(.chip):focus-visible { box-shadow: 0 2px var(--text); }
.bar-row button:not(.chip)[aria-pressed=true]::after { content: ""; position: absolute; left: 0; right: 0; bottom: 1px; height: 2px; background: var(--accent); }
/* Filters' panel: Live now, then the tags. */
.bar-panel:not([hidden]) { display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.bar-panel > [data-filter]:has(+ [data-tag]) { margin-right: 12px; }
/* A pill: Category and Filters, 2D and 3D, Live now and the tags, outlined, filled with the accent while on; picks share it. */
:is(.community-bar, .kinds-pick) button.chip { padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; background: none; color: var(--dim); font: 600 13px/1 var(--body); letter-spacing: 0; text-transform: none; white-space: nowrap; cursor: pointer; outline: none; }
:is(.community-bar, .kinds-pick) button.chip:is(:hover, :focus-visible) { border-color: var(--text); color: var(--text); box-shadow: none; }
:is(.community-bar, .kinds-pick) button.chip[aria-pressed=true] { border-color: var(--accent); background: var(--accent); color: var(--on-accent); }
:is(.community-bar, .kinds-pick) button.chip:disabled { opacity: .4; cursor: default; }
/* Category and Filters open what they hold; Filters stays lit while its panel is open. */
.community-bar .chip.menu::after { content: ""; display: inline-block; width: 5px; height: 5px; margin: 0 1px 3px 9px; border: solid currentColor; border-width: 0 1.5px 1.5px 0; rotate: 45deg; }
.community-bar .chip.menu[aria-expanded=true]::after { rotate: -135deg; margin-bottom: -1px; }
.community-bar .chip.menu[aria-expanded=true] { border-color: var(--text); color: var(--text); }
/* A filter that is on: Category with its pick, and a chip whose × turns it off. */
.community-bar .chip.on { border-color: var(--accent); color: var(--text); }
.community-bar .chip.on:not(.menu)::after { content: "×"; margin-left: 8px; color: var(--accent); font: 400 17px/0 var(--body); vertical-align: -1px; }
/* Community's categories: two columns of words, the one chosen marked. */
.menu-pop.columns { display: grid; grid-template-columns: repeat(2, auto); }
.menu-pop.columns button { padding: 10px 24px 10px 34px; font: 600 15px/1 var(--body); letter-spacing: 0; text-transform: none; }
.menu-pop.columns button:first-child { grid-column: 1 / -1; }
.menu-pop button[aria-checked=true] { color: var(--text); }
.menu-pop button[aria-checked=true]::before { scale: 1; }
.kinds-pick { display: flex; flex-direction: column; gap: 14px; width: 100%; text-align: left; }
.kinds-group { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.kinds-group > span { width: 100%; color: var(--dim); font: 700 11px/1 var(--display); letter-spacing: .2em; text-transform: uppercase; }
/* What a world is, on its tile and its page: its categories and dimension, then its tags, dimmer. */
.kinds { display: flex; flex-wrap: wrap; gap: 2px 10px; color: var(--text); font: 600 13px/1.4 var(--body); }
.tile .kinds { display: flex; white-space: normal; color: var(--text); font-size: 13px; }
.kinds .kind-tag { color: var(--dim); }
.kinds .kind-tag::before { content: "#"; }
/* Under a world's byline on its page, with its owner's Edit beside it. */
.kinds-line:not([hidden]) { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 16px; margin: -12px 0 28px; }
.kinds-line .kinds { justify-content: center; font-size: 15px; }
.kinds-line button { padding: 0; background: none; border: 0; color: var(--accent); font: 600 14px/1.4 var(--body); text-decoration: underline; cursor: pointer; }
.section-title { width: 100%; margin: 8px 0 16px; color: var(--dim); font: 700 13px/1 var(--display); letter-spacing: .16em; text-transform: uppercase; }
.empty { width: 100%; margin: 8px 0 40px; color: var(--dim); font: 400 16px/1.5 var(--body); }
/* Profile signed out: what signing in shows, big in the middle of the page, and Sign in under it, the same on the site and in the app. */
.signin-ask:not([hidden]) { display: flex; flex-direction: column; align-items: center; gap: 32px; width: 100%; margin: 12vh 0 40px; text-align: center; }
.signin-ask b { font: 800 clamp(26px, 2.6vw, 36px)/1.15 var(--display); letter-spacing: .02em; text-transform: uppercase; text-wrap: balance; }
.signin-ask .primary { min-width: 280px; }
/* A list with nothing in it says so in its empty line, without its heading. */
.section-title:has(+ .grid:empty) { display: none; }

/* Numbers side by side, each over its name. */
.stats { display: flex; justify-content: center; margin: 0 0 36px; padding: 0; }
.stats div { display: flex; flex-direction: column-reverse; padding: 0 28px; border-left: 1px solid rgba(255,255,255,.18); }
.stats div:first-child { border-left: 0; }
.stats dt { color: var(--dim); font: 700 11px/1 var(--display); letter-spacing: .16em; text-transform: uppercase; }
.stats dd { margin: 0 0 8px; font: 800 30px/1 var(--display); letter-spacing: .02em; text-transform: uppercase; white-space: nowrap; }
/* A number that goes to what it counts, its name too; the number's button takes the focus. */
.stats .to { cursor: pointer; }
.stats .to button { padding: 0; background: none; border: 0; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; outline: none; }
.stats .to:is(:hover, :has(:focus-visible)) dd { color: var(--accent); }

/* Worlds to browse: their pictures in rows, the name and who made it under each. */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 28px 20px; width: 100%; margin: 0 0 36px; }
.tile { position: relative; display: flex; flex-direction: column; gap: 12px; min-width: 0; padding: 0; background: none; border: 0; border-radius: 0; color: var(--text); text-align: left; text-decoration: none; cursor: pointer; outline: none; font: inherit; }
.tile .cover { width: 100%; opacity: .88; outline: 3px solid transparent; outline-offset: 0; transition: opacity .12s ease-out, outline-color .12s ease-out; }
.tile:is(:hover, :focus-visible, .active) .cover { opacity: 1; outline-color: var(--accent); }
.tile b { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: normal; font: 800 19px/1.15 var(--display); letter-spacing: .03em; text-transform: uppercase; }
.tile small { display: block; margin-top: 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dim); font: 500 14px/1.3 var(--body); }
/* Community keeps every number readable at the grid's real card widths, without reducing the metadata font. Other tiles keep their single-line description. */
.tile.community-tile small { white-space: normal; overflow: visible; overflow-wrap: anywhere; }
.community-tile :is(.tile-stat, .remixes) { white-space: nowrap; }
.tile small .remixes:hover { color: var(--text); text-decoration: underline; }
/* A Community search hides the tiles it doesn't match and keeps them on the page, pictures and all, for when it changes (searchTiles in front.js). */
.tile.unmatched { display: none; }
/* The tag and ⋯ sit in opposite corners of the picture, the same height and the same way in from its edges. */
.tile .tag { position: absolute; left: 10px; top: 10px; display: flex; align-items: center; height: 30px; padding: 0 10px; background: rgba(9,10,12,.82); color: var(--text); font: 700 11px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; }
.tile .tag.live { background: var(--accent); color: var(--on-accent); }
.tile .more { position: absolute; right: 10px; top: 10px; width: 30px; height: 30px; padding: 0; background: rgba(9,10,12,.82); border: 0; color: var(--text); cursor: pointer; opacity: 0; outline: none; }
.tile:is(:hover, :focus-within) .more, .tile .more:focus-visible { opacity: 1; }
.tile .more:is(:hover, :focus-visible) { background: var(--accent); color: var(--on-accent); }
.tile.renaming { cursor: text; }
.tile.renaming .cover { opacity: 1; outline-color: var(--accent); }
.tile.renaming input { all: unset; display: block; width: 100%; box-sizing: border-box; padding: 0 0 6px; border-bottom: 2px solid var(--accent); font: 800 19px/1.15 var(--display); letter-spacing: .03em; caret-color: var(--accent); }
.renaming input::selection { background: var(--accent); color: var(--on-accent); }
/* An answer that starts something new, like joining a world or creating one: its icon in a dashed frame over its name. */
.tile.new .cover { display: grid; place-items: center; background: rgba(9,10,12,.4); outline: 2px dashed rgba(255,255,255,.3); outline-offset: -2px; }
.tile.new:is(:hover, :focus-visible) .cover { outline-color: var(--accent); }
.tile.new .cover svg { width: 40px; height: 40px; fill: var(--dim); }
.tile.new:is(:hover, :focus-visible) .cover svg { fill: var(--accent); }
.tile.new small { display: none; }
/* Two such answers side by side, under the question they answer. */
.grid.answers { grid-template-columns: repeat(2, minmax(0, 1fr)); width: min(720px, 100%); margin: 0 0 28px; }
/* What a Community world was built with (front.js showBuilt): its mods and the assets they credit. One without a picture is a plain tile, never a stand-in picture;
   lines its credits wrote some other way read as text under them, at a reading width. */
.built { width: 100%; }
.built .tile .cover.plain { background: rgba(255,255,255,.07); }
.built div.tile { cursor: default; }
.built div.tile:hover .cover { outline-color: transparent; }
/* On a phone two to a row, so a world of thirty mods isn't thirty screen-wide tiles, with names small enough for the half width and a long one broken, never cut. */
@media (max-width: 560px) { .built .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 12px; } .built .tile b { font-size: 14px; overflow-wrap: anywhere; } }
.built-lines { width: min(760px, 100%); margin: 0 0 36px; padding: 0; list-style: none; color: var(--dim); font: 500 14px/1.5 var(--body); overflow-wrap: anywhere; }
.built-lines li + li { margin-top: 6px; }
.built-lines a { color: var(--text); }
.built-lines a:hover { color: var(--accent); }

/* A thing's own page: its name big in the middle over its picture, who made it, its numbers and its one action. */
.hero { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0; width: 100%; margin-bottom: 56px; text-align: center; }
.hero h1 { width: min(1080px, 100%); margin: 0 0 18px; font: 800 96px/1 var(--display); letter-spacing: .02em; text-transform: uppercase; overflow-wrap: normal; word-break: keep-all; text-shadow: 0 2px 16px rgba(0,0,0,.45); }
.byline { margin: 0 0 28px; color: var(--text); font: 700 15px/1.4 var(--display); letter-spacing: .14em; text-transform: uppercase; }
.byline a { text-decoration: none; border-bottom: 2px solid color-mix(in srgb, var(--accent) 60%, transparent); }
.byline a:hover { color: var(--accent); }
.byline .tag { margin-left: 14px; padding: 5px 8px; background: rgba(9,10,12,.7); font-size: 11px; color: var(--dim); }
.column { width: min(720px, 100%); margin: 0 auto 48px; text-align: left; }
/* A page keeps one left edge: its title, sections, rows and grids all start where the page does. Menus and a world's page stay centered. */
.page:not(:has(> .hero)) :is(.column, .rows) { margin-left: 0; }
.page .person { align-items: flex-start; text-align: left; }
.page .person :is(.stats, .actions) { justify-content: flex-start; }
.page .person .stats div:first-child { padding-left: 0; }
.page .gallery { width: 100%; }
.column > .section-title { display: flex; align-items: baseline; gap: 12px; }
.column > .section-title span { color: var(--text); }

/* Comments and messages: who and when on one line, what they said under it; options on right click or ⋯. */
.comment { position: relative; padding: 16px 48px 16px 0; border-bottom: 1px solid var(--line); }
.comment p { margin: 6px 0 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.comment.removed p { color: var(--dim); }
.comment small { color: var(--dim); font-size: 13px; }
.comment small a { color: var(--text); font: 700 13px/1 var(--display); letter-spacing: .1em; text-transform: uppercase; text-decoration: none; }
.comment .more { position: absolute; right: 0; top: 12px; width: 36px; height: 36px; display: grid; place-items: center; background: none; color: var(--dim); font: 800 18px/1 var(--display); cursor: pointer; opacity: 0; outline: none; }
.comment:is(:hover, :focus-within) .more, .comment .more:focus-visible { opacity: 1; }
.comment .more:is(:hover, :focus-visible) { background: var(--accent); color: var(--on-accent); }
.post { display: flex; align-items: flex-end; gap: 12px; margin: 0 0 8px; }
.post .line { flex: 1; }
/* With Love it and Needs work, the box takes the whole row and they sit under it, left, with Post on the right. */
.post:has(.verdicts) { flex-wrap: wrap; }
.post:has(.verdicts) .line { flex-basis: 100%; }
.post .verdicts { display: flex; gap: 8px; margin-right: auto; }
.comment .review { display: block; margin-top: 4px; color: var(--accent); }
.post .line input { font-size: 18px; }
.post .action { flex: none; }

/* Lists that are people or conversations: one row each, in a centered column. */
.rows { display: flex; flex-direction: column; width: min(720px, 100%); margin: 0 auto 36px; }
.rows:empty { display: none; }
.row { position: relative; display: flex; align-items: center; gap: 16px; width: 100%; min-height: 64px; padding: 12px 0; background: none; border: 0; border-bottom: 1px solid var(--line); border-radius: 0; color: var(--text); font: inherit; text-align: left; text-decoration: none; outline: none; }
.row .what { flex: 1; min-width: 0; color: inherit; text-decoration: none; outline: none; }
:is(a, button):is(.row, .what) { cursor: pointer; }
.row b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 600 16px/1.3 system-ui, sans-serif; color: var(--text); transition: color .12s ease-out; }
:is(a.row, button.row, .row a.what):is(:hover, :focus-visible) b { color: var(--accent); }
.row small { display: block; margin-top: 4px; color: var(--dim); font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row .value { flex: none; color: var(--dim); font: 400 14px/1.3 system-ui, sans-serif; white-space: nowrap; }
.row .value.new { color: var(--accent); }
.row .action { min-height: 36px; padding: 0 14px; font-size: 12px; }
.item .more { display: grid; place-items: center; width: 36px; height: 36px; margin-left: 12px; flex: none; color: var(--dim); font: 800 18px/1 var(--display); opacity: 0; }
.item:is(:hover, :focus, :focus-within) .more { opacity: 1; }
.item .more:hover { background: var(--accent); color: var(--on-accent); }
.row .more { display: grid; place-items: center; width: 36px; height: 36px; flex: none; color: var(--dim); font: 800 18px/1 var(--display); opacity: 0; }
.row:is(:hover, :focus-within) .more { opacity: 1; }
.row .more:hover { background: var(--accent); color: var(--on-accent); }

/* A builder's page and the account page: their name, their numbers, then their worlds. */
.person { display: flex; flex-direction: column; align-items: center; width: 100%; margin: 0 0 40px; text-align: center; }
.person h1 { width: min(960px, 100%); margin: 0 0 16px; font: 800 72px/1 var(--display); letter-spacing: .02em; text-transform: uppercase; white-space: nowrap; }
.person .stats { margin-bottom: 28px; }

/* A tooltip: one short line saying what a control does, in the menus' flat pane. */
.tip { position: fixed; z-index: 80; max-width: 320px; padding: 8px 12px; background: rgba(9,10,12,.97); border: 1px solid rgba(255,255,255,.16); color: var(--text); font: 500 13px/1.35 var(--body); text-transform: none; letter-spacing: normal; pointer-events: none; }

/* Options for a row, on right click or its ⋯ button: a flat pane of the menu's entries. */
.menu-pop { position: fixed; z-index: 50; min-width: 220px; padding: 8px 0; background: rgba(9,10,12,.97); border: 1px solid rgba(255,255,255,.16); box-shadow: 0 12px 32px rgba(0,0,0,.5); }
.menu-pop button { position: relative; display: block; width: 100%; padding: 12px 24px 12px 34px; background: none; border: 0; color: rgba(243,241,236,.85); font: 800 15px/1 var(--display); letter-spacing: .08em; text-transform: uppercase; text-align: left; cursor: pointer; outline: none; white-space: nowrap; }
.menu-pop button::before { content: ""; position: absolute; left: 14px; top: 50%; width: 9px; height: 9px; translate: 0 -50%; background: var(--accent); scale: 0; transition: scale .1s ease-out; }
.menu-pop button:is(:hover, :focus) { color: var(--text); }
.menu-pop button:is(:hover, :focus)::before { scale: 1; }
.menu-pop button.danger:is(:hover, :focus) { color: var(--err); }
.menu-pop button:disabled { opacity: .35; pointer-events: none; }

/* A question in the middle of the screen, over the page darkened. */
.scrim { position: fixed; inset: 0; z-index: 60; display: grid; place-items: center; padding: 16px; background: rgba(9,10,12,.72); }
.dialog { display: flex; flex-direction: column; align-items: center; gap: 28px; width: min(560px, 100%); padding: 48px 40px 32px; background: rgba(9,10,12,.97); border: 1px solid rgba(255,255,255,.16); box-shadow: 0 24px 64px rgba(0,0,0,.6); text-align: center; }
.dialog h2 { margin: 0; font: 800 32px/1.1 var(--display); letter-spacing: .02em; text-transform: uppercase; overflow-wrap: anywhere; color: var(--text); }
.dialog .actions { flex-direction: column; align-items: stretch; min-width: min(360px, 100%); max-width: 100%; gap: 12px; }
.dialog .error:empty { display: none; }
.dialog .error { margin: -12px 0 0; }
/* An asset of a world's credits over the page: the asset viewer's stage and facts (community/server/viewer), or its picture or sound, under its name and source. The viewer's
   own look (viewer-style.ts) reads its colours and buttons from here. */
.asset-view { place-items: stretch; z-index: 61; --border: var(--line); --border-hover: rgba(255,255,255,.4); --divider: var(--line); --card: #141518; --surface: #1f2024; --fg: var(--text); --muted: var(--dim); --blue: var(--accent); --blue-soft: rgba(255,255,255,.14); }
.asset-view-box { display: grid; grid-template-rows: auto minmax(0, 1fr); width: min(1440px, 100%); min-height: 0; margin: 0 auto; background: #0b0b0c; border: 1px solid rgba(255,255,255,.16); box-shadow: 0 24px 64px rgba(0,0,0,.6); outline: none; color: var(--text); font: 500 14px/1.4 var(--body); }
.asset-view-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 14px 16px 14px 20px; border-bottom: 1px solid var(--line); }
.asset-view-head > div:first-child { min-width: 0; }
.asset-view-head h2 { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 800 22px/1.15 var(--display); letter-spacing: .03em; text-transform: uppercase; }
.asset-view-head small { display: block; margin-top: 4px; color: var(--dim); font: 500 14px/1.3 var(--body); }
.asset-view-head .actions { flex: none; flex-wrap: nowrap; }
.asset-view-body { display: grid; min-height: 0; }
.asset-view-still { display: grid; place-items: center; min-height: 0; padding: 24px; background: #8e8e8e; }
.asset-view-still img { max-width: 100%; max-height: 100%; object-fit: contain; }
.asset-view-still audio { width: min(560px, 100%); }
.asset-view-state { place-self: center; margin: 0; color: var(--dim); }
.mod-view { grid-template-rows: minmax(0, 1fr) auto; }
.mod-view-stage { position: relative; display: grid; min-height: 0; background: #dfe4e8; }
.mod-view-stage iframe { width: 100%; height: 100%; border: 0; }
.mod-view-stage .asset-view-state { position: absolute; place-self: center; padding: 8px 12px; background: #141518; color: var(--text); }
.mod-view-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 10px 14px; border-top: 1px solid var(--line); }
.mod-view-views { display: contents; }
.mod-view-views[hidden] { display: none; }
/* Play's keys: each key's cap, what it does when its mod says, and the mod. */
.mod-view-keys { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-left: 8px; }
.mod-view-keys:empty { display: none; }
.mod-view-key { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
.mod-view-key kbd { min-width: 24px; padding: 3px 6px; border: 1px solid rgba(255,255,255,.35); font: 700 12px/1 var(--display); letter-spacing: .06em; text-align: center; text-transform: uppercase; }
.mod-view-key small, .mod-view-note { color: var(--dim); font-size: 12px; }
.mod-view-note { margin-left: auto; }
.asset-view .button { display: inline-flex; align-items: center; justify-content: center; height: 32px; padding: 0 12px; background: var(--accent); border: 1px solid transparent; border-radius: 0; color: var(--on-accent); font: 700 12px/1 var(--display); letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; cursor: pointer; outline: none; }
.asset-view .button:hover { background: var(--accent-hover); }
.asset-view .button.secondary { background: var(--card); border-color: var(--border); color: var(--fg); }
.asset-view .button.secondary:hover, .asset-view .button.secondary.active { border-color: var(--accent); color: var(--accent); }
.asset-view .button.ghost { height: 30px; padding: 0 10px; background: transparent; color: var(--dim); font: 500 13px/1 var(--body); letter-spacing: 0; text-transform: none; }
.asset-view .button.ghost:hover, .asset-view .button.ghost.active { background: var(--surface); color: var(--text); }
.asset-view .button:focus-visible { border-color: var(--accent); }
.asset-view .muted { color: var(--dim); }
.asset-view .search-input { height: 32px; padding: 0 10px; background: var(--card); border: 1px solid var(--border); border-radius: 0; color: var(--text); font: inherit; outline: none; }
.asset-view .search-input:focus { border-color: var(--accent); }
@media (max-width: 700px) { .asset-view { padding: 0; } .asset-view-head { flex-wrap: wrap; } }

.more { display: grid; place-items: center; }
.more svg { display: block; width: 16px; height: 16px; fill: currentColor; }

/* A world's first picture, or the poster under its first video or animated picture, which plays over it while on screen (front.js showFirst). */
.cover:has(> .motion) { position: relative; }
:is(.cover, .backdrop) > .motion { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity .18s ease-out; pointer-events: none; }
:is(.cover, .backdrop) > .motion.on { opacity: 1; }

/* A world page's pictures and videos: one big, arrows on its sides, its place in the corner, thumbnails in a row under it. */
.gallery { width: min(1040px, 100%); margin: 0 auto 48px; }
.gallery .stage { position: relative; aspect-ratio: 16 / 9; background: #0b0b0c; outline: 1px solid var(--line); }
/* The big one is the stage's own .view, never an editor's "Add this view" tile (.edit-item.view), which the same rules would stretch over the page. */
.gallery .stage > .view, .gallery .stage > .view > * { position: absolute; inset: 0; width: 100%; height: 100%; }
.gallery .stage > .view > * { display: block; object-fit: contain; background: #0b0b0c; }
.gallery .stage > .view img { cursor: zoom-in; }
.gallery .stage:fullscreen { outline: 0; }
.gallery .stage:fullscreen > .view img { cursor: zoom-out; }
.gallery :is(.prev, .next) { position: absolute; top: 50%; width: 48px; height: 72px; margin-top: -36px; display: grid; place-items: center; padding: 0; background: rgba(9,10,12,.72); border: 0; color: var(--text); cursor: pointer; outline: none; opacity: 0; transition: opacity .12s ease-out; }
.gallery .prev { left: 0; }
.gallery .next { right: 0; }
.gallery .stage:is(:hover, :focus-within) :is(.prev, .next), .gallery :is(.prev, .next):focus-visible { opacity: 1; }
.gallery :is(.prev, .next):is(:hover, :focus-visible) { background: var(--accent); color: var(--on-accent); }
.gallery :is(.prev, .next) svg { width: 12px; height: 20px; fill: currentColor; }
.gallery .count { position: absolute; left: 10px; top: 10px; display: flex; align-items: center; height: 30px; padding: 0 10px; background: rgba(9,10,12,.82); font: 700 11px/1 var(--display); letter-spacing: .14em; pointer-events: none; }
.gallery .label { position: absolute; right: 10px; top: 10px; display: flex; align-items: center; height: 30px; padding: 0 10px; background: rgba(9,10,12,.82); border-left: 3px solid var(--accent); font: 700 11px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; pointer-events: none; }
.gallery .label:empty { display: none; }
.gallery .thumbs { display: flex; gap: 8px; margin-top: 8px; overflow-x: auto; scrollbar-width: none; }
.gallery .thumb { position: relative; flex: none; width: 128px; aspect-ratio: 16 / 9; padding: 0; background: #1b1c1f; border: 0; outline: 2px solid transparent; outline-offset: -2px; cursor: pointer; opacity: .62; transition: opacity .12s ease-out; }
.gallery .thumb :is(img, video) { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.gallery .thumb:is(:hover, :focus-visible) { opacity: 1; outline-color: rgba(255,255,255,.5); }
.gallery .thumb.on { opacity: 1; outline-color: var(--accent); }
.gallery .thumb.video::after { content: ""; position: absolute; left: 8px; bottom: 8px; border-style: solid; border-width: 6px 0 6px 10px; border-color: transparent transparent transparent var(--text); filter: drop-shadow(0 1px 2px rgba(0,0,0,.8)); }
.gallery .thumb.edit { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; background: none; outline: 2px dashed rgba(255,255,255,.28); color: var(--dim); font: 700 11px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; opacity: 1; }
.gallery .thumb.edit svg { width: 16px; height: 16px; fill: currentColor; }
.gallery .thumb.edit:is(:hover, :focus-visible) { outline: 2px solid var(--accent); color: var(--accent); }

/* The owner's own page, edited where it shows (front.js editText, editGallery): words that turn into a field in their own type, and the gallery a strip to drag, remove from and add to. */
.editable { cursor: text; outline: 1px dashed transparent; outline-offset: 8px; }
.editable:hover { outline-color: rgba(255,255,255,.45); }
.editable:focus-visible { outline: 2px solid var(--accent); }
.editable:is(:hover, :focus-visible):not(.editing)::after { content: ""; display: inline-block; width: max(14px, .3em); height: max(14px, .3em); margin-left: .25em; vertical-align: .1em; background: var(--accent); mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M11.3 1.3a1 1 0 0 1 1.4 0l2 2a1 1 0 0 1 0 1.4L5.4 14H2v-3.4z'/%3E%3C/svg%3E") center / contain no-repeat; }
.editable.blank { color: var(--dim); }
.editable.editing { width: 100%; outline: 0; cursor: auto; }
.in-place { display: block; width: 100%; margin: 0; padding: 0 0 4px; background: none; border: 0; border-bottom: 2px solid var(--accent); border-radius: 0; color: inherit; font: inherit; letter-spacing: inherit; text-transform: inherit; text-align: inherit; text-shadow: inherit; caret-color: var(--accent); outline: none; resize: none; overflow: hidden; }
.editable.invalid .in-place { border-bottom-color: var(--err); }
.editable.saving .in-place { opacity: .55; }
.in-place-error { min-height: 0; margin: -6px 0 24px; text-shadow: 0 1px 3px rgba(0,0,0,.8); }
.in-place-error:empty { display: none; }
.gallery .edit-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 24px; margin-bottom: 14px; }
.gallery .budget { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; color: var(--dim); font: 700 12px/1 var(--display); letter-spacing: .1em; text-transform: uppercase; white-space: nowrap; }
.gallery .budget .at { color: var(--accent); }
.gallery .budget .meter { display: flex; align-items: center; gap: 10px; }
.gallery .budget .meter i { width: 64px; height: 4px; background: linear-gradient(var(--accent), var(--accent)) no-repeat 0 0 / var(--used, 0%) 100%, rgba(255,255,255,.18); transition: background-size .2s ease-out; }
.gallery.editing > .error { margin: 12px 0 0; }
.gallery.editing > .error:empty { display: none; }
.gallery .edit-views { margin-top: 28px; }
.edit-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.edit-strip.dropping { outline: 2px dashed var(--accent); outline-offset: 6px; }
.edit-item { position: relative; display: block; min-width: 0; padding: 0; background: none; border: 0; color: var(--text); text-align: left; cursor: grab; outline: none; font: inherit; }
.edit-item .pic { position: relative; display: block; aspect-ratio: 16 / 9; overflow: hidden; background: #1b1c1f; outline: 2px solid transparent; outline-offset: -2px; }
.edit-item .pic > :is(img, video) { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; transition: opacity .12s ease-out; }
.edit-item:hover .pic, .edit-item.over .pic { outline-color: rgba(255,255,255,.5); }
.edit-item:focus-visible .pic, .edit-item.over .pic { outline-color: var(--accent); }
.edit-item.dragging { opacity: .4; }
.edit-item .tag { position: absolute; left: 8px; top: 8px; display: flex; align-items: center; height: 26px; padding: 0 9px; background: var(--accent); color: var(--on-accent); font: 700 11px/1 var(--display); letter-spacing: .12em; text-transform: uppercase; pointer-events: none; }
.edit-item.video .pic::after { content: ""; position: absolute; left: 10px; bottom: 10px; border-style: solid; border-width: 6px 0 6px 10px; border-color: transparent transparent transparent var(--text); filter: drop-shadow(0 1px 2px rgba(0,0,0,.8)); pointer-events: none; }
.edit-item :is(.remove, .more) { position: absolute; top: 8px; width: 28px; height: 28px; display: grid; place-items: center; background: rgba(9,10,12,.82); color: var(--text); cursor: pointer; opacity: 0; transition: opacity .12s ease-out; }
.edit-item .remove { right: 8px; }
.edit-item .more { right: 40px; }
.edit-item .remove svg { width: 10px; height: 10px; fill: currentColor; }
.edit-item:is(:hover, :focus-within) :is(.remove, .more) { opacity: 1; }
.edit-item :is(.remove, .more):hover { background: var(--accent); color: var(--on-accent); }
.edit-item .note { position: absolute; left: 0; right: 0; top: 0; aspect-ratio: 16 / 9; display: grid; place-items: center; overflow: hidden; background: rgba(9,10,12,.62); font: 700 11px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; pointer-events: none; }
.edit-item .note::after { content: ""; position: absolute; left: 0; bottom: 0; width: 40%; height: 3px; background: var(--accent); animation: sending 1.1s ease-in-out infinite; }
@keyframes sending { from { translate: -100% 0; } to { translate: 250% 0; } }
.edit-item.sending :is(.remove, .more) { display: none; }
.edit-item.add, .edit-item.view { cursor: pointer; }
.edit-item.add .pic { display: grid; place-items: center; background: none; outline: 2px dashed rgba(255,255,255,.28); color: var(--dim); font: 800 28px/1 var(--display); }
.edit-item.add small { display: block; margin-top: 8px; color: var(--dim); font: 700 12px/1 var(--display); letter-spacing: .1em; text-transform: uppercase; }
.edit-item.add:is(:hover, :focus-visible) .pic { outline: 2px solid var(--accent); color: var(--accent); }
.edit-item.add:is(:hover, :focus-visible) small { color: var(--text); }
.edit-item.add[aria-disabled=true] { cursor: not-allowed; opacity: .4; }
.edit-item.view .pic > img { opacity: .55; }
.edit-item.view:is(:hover, :focus-visible) .pic > img { opacity: 1; }
.edit-item.view .plus { position: absolute; z-index: 1; left: 0; right: 0; top: 0; aspect-ratio: 16 / 9; display: grid; place-items: center; font: 800 28px/1 var(--display); opacity: 0; pointer-events: none; }
.edit-item.view:is(:hover, :focus-visible) .plus { opacity: 1; }
.gallery.busy :is(.edit-item, .edit-strip) { cursor: progress; }
@media (max-width: 760px) { .edit-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (prefers-reduced-motion: reduce) { .edit-item .note::after { animation: none; width: 100%; opacity: .5; } }
