/* 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(/fonts/archivo-expanded.woff2) format("woff2"); font-weight: 600 900; font-display: swap; }
@font-face { font-family: Archivo; src: url(/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; }
.page-head h1 { margin: 0; font: 800 56px/1 var(--display); letter-spacing: .02em; text-transform: uppercase; }
.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 the filters on the left and the sorts on the right, all text, every option on screen. */
.community-bar { width: 100%; margin: 0 0 32px; }
.community-bar .tab-bar { margin: 0; padding: 0 0 12px; border-bottom: 1px solid var(--line); }
.community-bar .tabs { gap: 4px 40px; }
.community-bar .tabs button { padding: 12px 0; font-size: 18px; letter-spacing: .14em; }
.community-bar .search { width: min(420px, 100%); height: 48px; }
.bar-line { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 40px; min-height: 56px; padding: 6px 0; border-bottom: 1px solid var(--line); }
.bar-filters, .bar-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0 24px; }
.bar-filters { gap: 0 36px; }
.bar-row > span { color: var(--dim); font: 700 11px/1 var(--display); letter-spacing: .2em; text-transform: uppercase; opacity: .7; }
.bar-line button { position: relative; padding: 14px 0; background: none; border: 0; border-radius: 0; color: var(--dim); font: 700 12px/1 var(--display); letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; cursor: pointer; outline: none; transition: color .12s ease-out; }
.bar-line button:is(:hover, :focus-visible), .bar-line button[aria-pressed=true] { color: var(--text); }
.bar-line button:focus-visible { box-shadow: 0 2px var(--text); }
.bar-row button[aria-pressed=true]::after { content: ""; position: absolute; left: 0; right: 0; bottom: 6px; height: 2px; background: var(--accent); }
/* A filter that is on or off: a small square before its name, filled with the accent while on. */
.bar-line .toggle::before { content: ""; display: inline-block; width: 10px; height: 10px; margin: 0 10px 0 0; vertical-align: -1px; box-shadow: inset 0 0 0 1.5px currentColor; transition: background-color .12s ease-out; }
.bar-line .toggle[aria-pressed=true]::before { background: var(--accent); box-shadow: none; }
/* The builder the list is narrowed to, with the × that shows everyone's again. */
.bar-line .toggle.author::before { content: none; }
.bar-line .toggle.author::after { content: "×"; margin-left: 10px; color: var(--accent); font: 400 18px/0 var(--body); vertical-align: -2px; }
.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; }

/* 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); }
/* 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; }
.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); }
.gallery .view, .gallery .view > * { position: absolute; inset: 0; width: 100%; height: 100%; }
.gallery .view > * { display: block; object-fit: contain; background: #0b0b0c; }
.gallery .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; } }
