/*
 * Universal box-sizing reset. Previously inlined as the first <style>
 * rule in ~14 views/layouts (login, register, recovery, recovery_reset,
 * challenge, activation, goodbye, dashboard, navigation, legal, profile,
 * users_index, faction_profile, admin/default); centralised here so the
 * reset is applied once and the per-view <style> blocks stay focused on
 * page-specific styling.
 */
*, *::before, *::after {
    box-sizing: border-box;
}

* {
    margin: 0;
    padding: 0;
}

:root {
    --bg: #000;
    --panel: #000;
    --panel-2: #111;
    --stroke: #222;
    --text: #fff;
    --text-2: #bbb;
}

button {
    font-family: 'Inter', sans-serif;
}

/* Loading spinner inside comments */
.cmt-spinner {
    display: flex;
    justify-content: center;
    padding: 14px 0;
    color: #444;
}

.noselect {
    user-select: none;
}

.m-0-a {
    margin: 0 auto;
}
.m-a-0 {
    margin: auto 0;
}
.m-15 {
    margin: 15px;
}
.mt-15 {
    margin-top: 15px;
}
.mb-15 {
    margin-bottom: 15px;
}

.pb-50 {
    padding-bottom: 50px;
}

.br-5 {
    border-radius: 5px;
}
.br-10 {
    border-radius: 10px;
}
.br-15 {
    border-radius: 15px;
}

.d-flex {
    display: flex;
}
.flex-col {
    flex-direction: column;
}
.flex-row {
    flex-direction: row;
}
.gap-5 {
    gap: 5px;
}
.gap-10 {
    gap: 10px;
}
.gap-15 {
    gap: 15px;
}
.gap-20 {
    gap: 20px;
}

.w-50 {
    width: 50%;
}

.absolute {
    position: absolute;
}

.relative {
    position: relative;
}

.context-menu-pill {
    display: flex;
    gap: 2px;
    padding: 4px 8px;
    max-width: max-content;
    background: transparent;
    border: none;
    font-weight: bold;
    font-size: 0.8rem;
    border-radius: 5px;
    cursor: pointer;
    height: 24px;
}
.context-menu-pill>.dot {
    width: 6px;
    height: 6px;
    align-self: center;
    border-radius: 3px;
    background: white;
}

.note-pill {
    background: #3d7b0b;
    padding: 5px 10px;
    border-radius: 10px;
    font-size: 0.6rem;
    font-weight: bold;
    text-transform: uppercase;
}

.ip-wrapper {
    display: inline-block;
    max-width: 100px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: middle;
    position: relative;
}

.ip-scroll {
    display: inline-block;
    padding-right: 40px;
}

.ip-wrapper:hover .ip-scroll {
    text-overflow: clip;
    animation: ip-marquee 8s linear infinite;
}

@keyframes ip-marquee {
    0% {
        transform: translateX(0);
    }
    49.9% {
        opacity: 1;
        transform: translateX(-100%);
    }
    50% {
        opacity: 0;
    }
    50.01% {
        opacity: 0;
        transform: translateX(100%);
    }
    50.91% {
        opacity: 1;
    }
    100% {
        transform: translateX(0);
    }
}

.slight-blur {
    filter: blur(1.5px);
}

.bean-icon {
    max-width: 12px;
    height: auto;
    vertical-align: text-bottom;
}

/* Frame ornament slots — admin-only placeholder overlays for decorative
   assets (wreaths etc.) that will land on rámečky around the portal.
   Variants: --top (bar straddling top border), --ring (frame around all
   four sides, 20px out + 20px in). Host element needs .has-frame-ornament. */
.has-frame-ornament {
    position: relative;
}
.frame-ornament {
    position: absolute;
    pointer-events: none;
    background: rgba(255, 255, 255, 0.06);
    transition: background 120ms ease, border-color 120ms ease;
    z-index: 2;
}
.frame-ornament--top {
    left: 0;
    right: 0;
    top: 0;
    height: 20px;
    transform: translateY(-50%);
    border: 1px dashed rgba(255, 255, 255, 0.25);
    border-radius: 6px;
}
.frame-ornament--ring {
    /* 40px-thick ring centered on host edge: 20px outside + 20px inside.
       Box extends -20px beyond host on every side, 40px border eats the
       outer-to-host-edge band on the outside and the host-edge-to-inside
       band on the inside, leaving the host content visible through the
       transparent core. */
    inset: -20px;
    border: 40px solid rgba(255, 255, 255, 0.06);
    background: transparent;
    border-radius: inherit;
}
/* Clickable ornament slot — opts back in to pointer events so the slot
   can host a picker / config click target while in placeholder state. */
.frame-ornament--clickable {
    pointer-events: auto;
    cursor: pointer;
}
/* Slot with an asset applied: drop placeholder visuals (background
   tint, border, transition) and let the ornament PNG drive what's
   visible via its own alpha channel. Default to 100% 100% sizing so
   the asset fills the slot exactly; per-asset JS can override
   background-size/position when the image is sprite-style or needs
   natural sizing. pointer-events:none keeps controls underneath
   clickable (e.g. avatar-change). */
.frame-ornament.has-image {
    border: 0;
    background-color: transparent;
    background-size: 100%;
    background-repeat: no-repeat;
    background-position: center;
    transition: none;
    pointer-events: none;
}
.has-frame-ornament:hover > .frame-ornament--top:not(.has-image) {
    background: rgba(255, 255, 255, 0.12);
    border-color: rgba(255, 255, 255, 0.4);
}
.has-frame-ornament:hover > .frame-ornament--ring:not(.has-image) {
    border-color: rgba(255, 255, 255, 0.14);
}