/* Member profiles — /profile/<username>
 *
 * Loaded AFTER detail.css and dependent on it, the same arrangement the
 * festival hubs use. The venue, artist and festival pages already answer "what
 * does a Moshradar page about one subject look like" — breadcrumb, full-bleed
 * hero, a figure strip, chip tabs, main column plus sidebar — and a profile
 * answering it differently would be the fourth look on one site.
 *
 * Replaces profile_page.css, which was a self-contained 1,500-line sheet from
 * before that system existed: its own spacing scale, its own card treatment,
 * its own idea of a heading. What survives here is only what a profile has
 * that a venue does not — a monogram for members with no picture, a presence
 * dot, a comment wall, and the member's own accent and background colours.
 *
 * No :root block. The --dp-* tokens come from detail.css; the accent overrides
 * are set per-page on .pf from the member's saved hex, so one member's red
 * profile and another's purple one are the same stylesheet.
 */

/* --- The member's own colours -------------------------------------------
 *
 * .pf carries --pf-accent as an inline custom property (a validated six-digit
 * hex — see _profile_hex in views.py) and re-points detail.css's red tokens at
 * it. Everything downstream — chips, row hovers, section rules, buttons —
 * follows without knowing a member can pick a colour at all.
 */

.pf {
    --dp-red: var(--pf-accent, #ff0000);
    --dp-red-dim: color-mix(in srgb, var(--pf-accent, #ff0000) 78%, #000);
    --dp-red-soft: color-mix(in srgb, var(--pf-accent, #ff0000) 70%, #fff);
    --pf-accent-wash: color-mix(in srgb, var(--pf-accent, #ff0000) 14%, transparent);
}

/* detail.css writes literal rgba(255, 0, 0, …) in the few places a red wash is
   painted rather than a token used. Those are exactly the "headings, links and
   highlights" the accent picker promises, so they are re-pointed here too --
   otherwise a member picks purple and the page still glows red. The ticket
   button is deliberately not in this list: red is what a Get Tickets link
   looks like everywhere on the site, and a profile is not the place to
   re-teach that. */
.pf .dp-hero::after {
    background:
        radial-gradient(120% 100% at 15% 0%, var(--pf-accent-wash), transparent 60%),
        linear-gradient(to top, rgba(0, 0, 0, 0.92), rgba(0, 0, 0, 0.55));
}

.pf .dp-chip:hover,
.pf .dp-btn--on {
    background: var(--pf-accent-wash);
}

/* Anything actually filled with the accent needs a foreground chosen against
   it, not the flat #fff detail.css can assume when the fill is always red. A
   member who picked a pale accent got a white pill with white writing on it --
   the Edit profile button, invisible. --pf-ink is set inline beside the accent
   and is #111 over a light one, #fff over a dark one (see _accent_ink). */
.pf .dp-btn--primary,
.pf .dp-btn--primary:hover {
    color: var(--pf-ink, #fff);
}

.pf .dp-btn--on:hover {
    background: color-mix(in srgb, var(--pf-accent, #ff0000) 26%, transparent);
}

/* Where a member has set a background image, the panels go translucent so the
   picture they chose is actually visible between the rows, instead of being
   covered by 1,280px of #101010 and only showing in the page margins. */
.pf--has-bg {
    --dp-surface: rgba(16, 16, 16, 0.82);
    --dp-surface-2: rgba(22, 22, 22, 0.82);
}

.pf--has-bg .dp-hero {
    background: linear-gradient(150deg, rgba(20, 20, 20, 0.82) 0%, rgba(27, 12, 12, 0.86) 55%, rgba(36, 8, 8, 0.9) 100%);
}

/* --- Hero ---------------------------------------------------------------- */

.pf-avatar {
    position: relative;
}

/* Members without a picture used to get a hotlinked stock portrait from an
   unrelated company's website. A monogram is honest, costs no request, and
   matches the one the comment wall has always drawn. */
.pf-monogram {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    background: linear-gradient(155deg, var(--dp-surface-2), #000);
    color: var(--dp-red-soft);
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: clamp(2.2rem, 6vw, 3.6rem);
    font-weight: 900;
    letter-spacing: -0.03em;
    line-height: 1;
    user-select: none;
}

.pf-presence {
    position: absolute;
    right: 6%;
    bottom: 6%;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid #0b0b0b;
    background: #4a4a4a;
}

.pf-presence--online { background: #3ddc84; }

.pf-presence--idle { background: #f5a623; }

.pf-badge {
    display: inline-block;
    vertical-align: middle;
    margin-left: 0.65rem;
    padding: 0.22rem 0.6rem;
    border: 1px solid var(--dp-red);
    border-radius: 999px;
    background: var(--pf-accent-wash);
    color: #fff;
    /* The name is clamp()'d up to 3.25rem; the badge beside it must not be. */
    font-size: 0.6rem;
    font-weight: 800;
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

/* Icon-only social buttons. The .dp-btn pill squared off to a circle, so a row
   of four reads as one set rather than four differently-sized words. */
.pf-social {
    width: 38px;
    height: 38px;
    padding: 0;
    justify-content: center;
    border-radius: 50%;
    font-size: 0.95rem;
}

.pf-social--instagram:hover { border-color: #e1306c; background: rgba(225, 48, 108, 0.16); }

.pf-social--twitter:hover { border-color: #1d9bf0; background: rgba(29, 155, 240, 0.16); }

.pf-social--spotify:hover { border-color: #1ed760; background: rgba(30, 215, 96, 0.16); }

.pf-social--soundcloud:hover { border-color: #ff5500; background: rgba(255, 85, 0, 0.16); }

/* --- Tabs ----------------------------------------------------------------
 *
 * The festival hubs' tab strip, with one difference: those are separate URLs
 * with their own content, these are panels on one page. They are still real
 * links carrying ?tab=…, so a tab is shareable, the back button works, and the
 * page is usable with scripting off — see .pf-panel below.
 */

.pf-tabs {
    position: sticky;
    /* Clear of the fixed site header, so the tabs stay reachable part-way down
       a long comment wall. 89px is the header's measured height -- the same
       number detail.css cites where it pads the breadcrumb past it. */
    top: 89px;
    z-index: 3;
    border-top: 1px solid var(--dp-line-soft);
    border-bottom: 1px solid var(--dp-line);
    background: rgba(8, 8, 8, 0.92);
    backdrop-filter: blur(8px);
}

.pf-tabs-inner {
    max-width: var(--dp-max);
    margin: 0 auto;
    padding: 0.8rem var(--dp-gut);
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.pf-tabs .dp-chip.is-active {
    border-color: var(--dp-red);
    background: var(--pf-accent-wash);
    color: #fff;
}

.pf-tabs .dp-chip.is-active span { color: var(--dp-red-soft); }

/* Every panel is in the DOM on every request, so all of it is crawlable and a
   visitor with no scripting gets the whole profile stacked under its headings.
   The class that hides the inactive ones is scoped to .dp-js, which is set by
   an inline script before first paint — so there is no flash either way. */
.dp-js .pf-panel.is-off {
    display: none;
}

.pf-panel-label {
    display: none;
}

/* --- Overview ------------------------------------------------------------ */

/* Bios are typed into a textarea, so the line breaks the member put in are the
   ones they meant. */
.pf-bio {
    white-space: pre-line;
}

/* A profile with nothing on it yet. Says what to do rather than leaving a
   blank column under a heading. */
.pf-blank {
    padding: 2rem 1.5rem;
    border: 1px dashed var(--dp-line);
    border-radius: 8px;
    background: var(--dp-surface);
    color: var(--dp-muted);
    line-height: 1.7;
    text-align: center;
}

.pf-blank i {
    display: block;
    margin-bottom: 0.75rem;
    font-size: 1.6rem;
    color: #333;
}

.pf-blank p { margin: 0 0 0.35rem; }

.pf-blank p:last-child { margin-bottom: 0; }

.pf-blank a { color: var(--dp-red-soft); }

/* --- Photos -------------------------------------------------------------- */

.pf-media {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 0.9rem;
}

/* .dp-tile is sized for a horizontal rail; in a grid the cell decides. */
.pf-media .dp-tile {
    width: auto;
    flex: 1 1 auto;
    position: relative;
}

.pf-media img,
.pf-media video {
    height: 150px;
}

.pf-media-none {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 150px;
    background: #0a0a0a;
    color: #333;
    font-size: 1.4rem;
}

/* Only the owner is served anything but 'approved', and only they need telling
   which is which. */
.pf-media-status {
    position: absolute;
    top: 0.5rem;
    left: 0.5rem;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.75);
    border: 1px solid rgba(255, 255, 255, 0.25);
    color: #fff;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.pf-media-status--pending { border-color: #f5a623; color: #ffca6b; }

.pf-media-status--rejected { border-color: #ff4444; color: #ff8a8a; }

/* --- Comment wall -------------------------------------------------------- */

.pf-compose {
    display: flex;
    gap: 0.85rem;
    padding: 1rem;
    margin-bottom: 1.5rem;
    border: 1px solid var(--dp-line);
    border-radius: 8px;
    background: var(--dp-surface);
}

.pf-compose-body {
    flex: 1 1 auto;
    min-width: 0;
}

.pf-compose textarea {
    width: 100%;
    min-height: 84px;
    padding: 0.7rem 0.85rem;
    border: 1px solid var(--dp-line);
    border-radius: 6px;
    background: #0a0a0a;
    color: #eee;
    font: inherit;
    font-size: 0.9rem;
    line-height: 1.6;
    resize: vertical;
    transition: border-color 0.2s ease;
}

.pf-compose textarea:focus {
    outline: none;
    border-color: var(--dp-red);
}

.pf-compose textarea::placeholder { color: #555; }

.pf-compose-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: 0.65rem;
}

.pf-compose-hint {
    font-size: 0.76rem;
    color: var(--dp-muted);
}

.pf-signin {
    margin-bottom: 1.5rem;
}

.pf-comments {
    list-style: none;
    margin: 0;
    padding: 0;
}

.pf-comment {
    display: flex;
    gap: 0.85rem;
    padding: 1rem 0;
    border-bottom: 1px solid var(--dp-line-soft);
}

.pf-comment:last-child { border-bottom: none; }

/* Shared by the wall and the compose box, so whoever is writing sees
   themselves in the same shape as the people who already have. */
.pf-initial {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--dp-surface-2);
    border: 1px solid var(--dp-line);
    color: var(--dp-red-soft);
    font-size: 1rem;
    font-weight: 800;
    text-decoration: none;
    transition: border-color 0.2s ease;
}

a.pf-initial:hover { border-color: var(--dp-red); }

.pf-comment-body {
    flex: 1 1 auto;
    min-width: 0;
}

.pf-comment-head {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-bottom: 0.3rem;
}

/* Pushed to the far end of the head row, quiet until the row is hovered --
   it is a destructive control sitting on every comment its owner can see, and
   it should not read as the loudest thing on the wall. Always visible on
   touch, where there is no hover to reveal it. */
.pf-comment-del {
    margin-left: auto;
}

.pf-comment-del button {
    padding: 0.2rem 0.4rem;
    border: 0;
    border-radius: 5px;
    background: none;
    color: var(--dp-muted);
    font-size: 0.78rem;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.pf-comment:hover .pf-comment-del button,
.pf-comment-del button:focus-visible {
    opacity: 1;
}

.pf-comment-del button:hover,
.pf-comment-del button:focus-visible {
    color: var(--dp-red-soft);
    background: var(--pf-accent-wash);
}

@media (hover: none) {
    .pf-comment-del button { opacity: 1; }
}

.pf-comment-author {
    font-size: 0.88rem;
    font-weight: 700;
    color: #fff;
    text-decoration: none;
}

.pf-comment-author:hover { color: var(--dp-red); }

.pf-comment-date {
    font-size: 0.74rem;
    color: var(--dp-muted);
}

.pf-comment-text {
    margin: 0;
    font-size: 0.9rem;
    line-height: 1.65;
    color: var(--dp-text);
    overflow-wrap: anywhere;
}

/* --- Pagination ---------------------------------------------------------- */

.pf-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-top: 1.5rem;
}

.pf-pager a,
.pf-pager span {
    min-width: 34px;
    padding: 0.35rem 0.6rem;
    border: 1px solid var(--dp-line);
    border-radius: 6px;
    color: var(--dp-text);
    font-size: 0.82rem;
    text-align: center;
    text-decoration: none;
    font-variant-numeric: tabular-nums;
}

.pf-pager a:hover { border-color: var(--dp-red); color: #fff; }

.pf-pager .is-current {
    border-color: var(--dp-red);
    background: var(--pf-accent-wash);
    color: #fff;
    font-weight: 700;
}

/* The elision between windowed page numbers. Not a link, and not a target. */
.pf-pager-gap {
    border-color: transparent !important;
    color: var(--dp-muted) !important;
    min-width: 0 !important;
    padding: 0.35rem 0.2rem !important;
}

/* --- Narrow screens ------------------------------------------------------ */

@media (max-width: 700px) {
    .pf-tabs-inner {
        flex-wrap: nowrap;
        overflow-x: auto;
        scrollbar-width: none;
    }

    .pf-tabs-inner::-webkit-scrollbar { display: none; }

    .pf-tabs .dp-chip { white-space: nowrap; }

    .pf-social { width: 34px; height: 34px; }
}

/* --- No scripting --------------------------------------------------------
 *
 * The panels are all open, so the strip above them reads as a table of
 * contents and each panel has to announce which one it is.
 */

html:not(.dp-js) .pf-panel {
    margin-bottom: 2.5rem;
}

html:not(.dp-js) .pf-panel-label {
    display: block;
    margin: 0 0 1rem;
    font-size: 0.7rem;
    font-weight: 800;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--dp-red-soft);
}


/* --- Light profiles ------------------------------------------------------
 *
 * `theme` has been on the model, in the edit form and in that page's live
 * preview since profiles were built, and nothing ever read it: a member who
 * picked Light watched the preview go light, saved, and got the same dark
 * profile back. This is the half that was missing.
 *
 * Scoped to .pf--light, so it is a profile-only inversion -- the venue, artist
 * and festival pages share detail.css and are unaffected by every rule here.
 *
 * The first block is the whole theme for anything that reads a token. What
 * follows it is the exception list: the places detail.css writes #fff or a
 * white film literally, because a page that was only ever dark had no reason
 * not to. Those need naming one by one.
 */

.pf--light {
    --dp-line: rgba(0, 0, 0, 0.14);
    --dp-line-soft: rgba(0, 0, 0, 0.07);
    --dp-surface: #f4f4f4;
    --dp-surface-2: #eaeaea;
    --dp-muted: #5f5f5f;
    --dp-text: #242424;
    /* Strong text: what #fff means in the dark sheet. */
    --pf-strong: #0d0d0d;
    /* The film white fills are painted with, inverted. */
    --pf-film: rgba(0, 0, 0, 0.05);
    --pf-film-2: rgba(0, 0, 0, 0.10);
    /* .pf mixes the soft accent towards white, which is right on a black page
       and all but invisible on this one. Re-mixed towards black here, which
       carries the monogram, the comment initials and the no-script panel
       labels without naming any of them. */
    --dp-red-soft: color-mix(in srgb, var(--pf-accent, #ff0000) 72%, #000);
    color: var(--dp-text);
}

/* The hero gradient is a dark scrim with the accent washed over it. Lightened,
   or the one full-bleed element on the page stays black. */
.pf--light .dp-hero::after {
    background:
        radial-gradient(120% 100% at 15% 0%, var(--pf-accent-wash), transparent 60%),
        linear-gradient(to top, rgba(255, 255, 255, 0.92), rgba(255, 255, 255, 0.55));
}

.pf--light .dp-crumbs a:hover,
.pf--light .dp-crumbs span[aria-current],
.pf--light .dp-title,
.pf--light .dp-sub a:hover,
.pf--light .dp-h,
.pf--light .dp-stat-value,
.pf--light .dp-row-date b,
.pf--light .dp-row-title,
.pf--light .dp-faq-q,
.pf--light .dp-peer-name,
.pf--light .dp-tile-name,
.pf--light .dp-track-name,
.pf--light .pf-comment-author,
.pf--light .dp-card-title {
    color: var(--pf-strong);
}

.pf--light .dp-sub a {
    text-decoration-color: rgba(0, 0, 0, 0.3);
}

/* Buttons and chips are a white film over a dark page; over a light one they
   have to be a dark film or they vanish. */
.pf--light .dp-btn {
    border-color: rgba(0, 0, 0, 0.2);
    background: var(--pf-film);
    color: var(--pf-strong);
}

.pf--light .dp-btn:hover,
.pf--light .dp-row:hover,
.pf--light .dp-showall:hover {
    background: var(--pf-film-2);
    border-color: rgba(0, 0, 0, 0.35);
}

/* Except the ones filled with the member's accent, which already choose their
   own foreground from the accent's brightness -- see _accent_ink in views.py.
   Without this they would inherit the dark ink above and lose that. */
.pf--light .dp-btn--primary,
.pf--light .dp-btn--primary:hover {
    background: var(--pf-accent);
    border-color: var(--pf-accent);
    color: var(--pf-ink, #fff);
}

.pf--light .dp-hero-portrait,
.pf--light .pf-avatar {
    border-color: rgba(0, 0, 0, 0.18);
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.18);
}

/* The monogram's gradient ends at a literal #000. The initials beside it read
   --dp-surface-2 and need nothing. */
.pf--light .pf-monogram {
    background: linear-gradient(155deg, var(--dp-surface-2), #fff);
}

.pf--light .pf-pager a:hover,
.pf--light .pf-pager .is-current {
    color: var(--pf-strong);
}

/* A media tile with no image is a white-film placeholder holding an icon. */
.pf--light .pf-media-none {
    background: var(--pf-film);
    color: var(--dp-muted);
}
