/*
 * The custom CSS framework of the portal. Mobile first: the plain rules are the
 * phone layout, media queries only add on top of that for wider screens.
 *
 * Order: tokens, reset, base elements, layout, components.
 */

/* --- tokens ------------------------------------------------------------- */

:root {
    --color-bg: #ffffff;
    --color-bg-muted: #f4f2f7;
    --color-ink: #17141f;
    --color-ink-muted: #5b5470;
    --color-accent: #6d3bd4;
    --color-accent-ink: #ffffff;
    --color-accent-hover: #5a2eb8;
    --color-border: #ded9e8;

    /* system-ui covers thai on every current phone and desktop; the named thai
       families are the fallback for older systems whose UI font has no thai
       glyphs, which would otherwise show boxes. All of them are installed
       fonts, nothing is downloaded. */
    --font-body: system-ui, -apple-system, "Segoe UI", Roboto,
        "Noto Sans Thai", "Sarabun", "Leelawadee UI", "Thonburi", sans-serif;

    /* Spacing steps, roughly doubling. Used for every margin/padding so that
       vertical rhythm stays consistent without one-off values. */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 1rem;
    --space-4: 1.5rem;
    --space-5: 2.5rem;
    --space-6: 4rem;

    --radius: 0.5rem;
    --content-width: 68rem;
}

/* --- reset -------------------------------------------------------------- */

*,
*::before,
*::after {
    box-sizing: border-box;
}

body,
h1,
h2,
h3,
p,
ul,
figure {
    margin: 0;
}

ul {
    padding: 0;
    list-style: none;
}

img {
    display: block;
    max-width: 100%;
}

/* --- base --------------------------------------------------------------- */

html {
    /* Anchor links land below the sticky header instead of behind it */
    scroll-padding-top: 5rem;
}

body {
    background: var(--color-bg);
    color: var(--color-ink);
    font-family: var(--font-body);
    font-size: 1rem;
    line-height: 1.6;
    -webkit-text-size-adjust: 100%;
}

h1,
h2,
h3 {
    line-height: 1.2;
    text-wrap: balance;
}

h1 {
    font-size: 2.25rem;
}

h2 {
    font-size: 1.75rem;
}

h3 {
    font-size: 1.125rem;
}

/* Thai stacks tone marks above the line and vowel signs below it, so a
   line-height that is comfortable for latin text makes them touch the line
   above. It also has no capitals and no spaces between words, which makes the
   same font-size read denser. The selector matches on the lang attribute
   (<html lang="th">, and any element that overrides it — the language switcher
   marks its own links), never on a css class, so it follows the language of the
   text and not the language of the page. Only line-height is touched: a
   font-size in em would compound on every nesting level. */
:lang(th) {
    line-height: 1.8;
}

h1:lang(th),
h2:lang(th),
h3:lang(th) {
    line-height: 1.45;
}

a {
    color: var(--color-accent);
}

:focus-visible {
    outline: 2px solid var(--color-accent);
    outline-offset: 2px;
}

@media (min-width: 48rem) {
    h1 {
        font-size: 3.25rem;
    }

    h2 {
        font-size: 2.25rem;
    }
}

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

/* Horizontal frame for every page section */
.container {
    width: 100%;
    max-width: var(--content-width);
    margin: 0 auto;
    padding: 0 var(--space-3);
}

/* Vertical rhythm between the big blocks of a page */
.section {
    padding: var(--space-5) 0;
}

@media (min-width: 48rem) {
    .container {
        padding: 0 var(--space-4);
    }

    .section {
        padding: var(--space-6) 0;
    }
}

.section--muted {
    background: var(--color-bg-muted);
}

/* Row of call-to-action buttons below a block of text */
.actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3);
    margin-top: var(--space-4);
}

/* Card grid that collapses to a single column on phones */
.grid {
    display: grid;
    gap: var(--space-3);
    grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
    .grid {
        gap: var(--space-4);
        grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    }
}

/* A grid as the body of a section, below the section intro */
.section .grid {
    margin-top: var(--space-4);
}

/* Keeps the footer at the bottom on short pages */
.page {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

.page__body {
    flex: 1;
}

/* --- header ------------------------------------------------------------- */

.site-header {
    position: sticky;
    top: 0;
    z-index: 10;
    background: var(--color-bg);
    border-bottom: 1px solid var(--color-border);
}

.site-header__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    min-height: 4rem;
}

.site-header__logo {
    color: inherit;
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    text-decoration: none;
}

.site-nav {
    display: flex;
    align-items: center;
    gap: var(--space-2);
}

.site-nav__link {
    color: var(--color-ink-muted);
    padding: var(--space-2);
    text-decoration: none;
}

.site-nav__link:hover {
    color: var(--color-ink);
}

/* Language switcher. Only the other language(s) are shown (see base.html), so
   this is one short link that has to stay legible without stealing room from
   the login buttons next to it. */
.site-nav__lang {
    color: var(--color-ink-muted);
    font-size: 0.9375rem;
    padding: var(--space-2) 0;
    text-decoration: none;
    white-space: nowrap;
}

.site-nav__lang:hover {
    color: var(--color-ink);
    text-decoration: underline;
}

/* The signed-in address is a nice-to-have, the phone header is too narrow */
.site-nav__user {
    display: none;
    color: var(--color-ink-muted);
    font-size: 0.9375rem;
}

@media (min-width: 40rem) {
    .site-nav__user {
        display: inline;
    }
}

/* --- footer ------------------------------------------------------------- */

.site-footer {
    border-top: 1px solid var(--color-border);
    color: var(--color-ink-muted);
    font-size: 0.875rem;
    padding: var(--space-4) 0;
}

/* --- buttons ------------------------------------------------------------ */

.button {
    display: inline-block;
    border: 1px solid transparent;
    border-radius: var(--radius);
    font: inherit;
    font-weight: 600;
    /* Stays above the 44px touch target on phones */
    padding: 0.7rem var(--space-4);
    text-align: center;
    text-decoration: none;
    cursor: pointer;
}

.button--primary {
    background: var(--color-accent);
    color: var(--color-accent-ink);
}

.button--primary:hover {
    background: var(--color-accent-hover);
}

.button--secondary {
    background: transparent;
    border-color: var(--color-border);
    color: var(--color-ink);
}

.button--secondary:hover {
    border-color: var(--color-ink-muted);
}

/* Header-sized button, sits next to the navigation links */
.button--small {
    font-size: 0.9375rem;
    padding: 0.4rem var(--space-3);
}

/* --- hero --------------------------------------------------------------- */

.hero {
    padding: var(--space-5) 0 var(--space-6);
}

.hero__lead {
    color: var(--color-ink-muted);
    font-size: 1.125rem;
    margin-top: var(--space-3);
    max-width: 38rem;
}

@media (min-width: 48rem) {
    .hero__lead {
        font-size: 1.25rem;
    }
}

/* --- cards -------------------------------------------------------------- */

.card {
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    padding: var(--space-4);
}

.card__text {
    color: var(--color-ink-muted);
    margin-top: var(--space-2);
}

/* --- artists ------------------------------------------------------------ */

/* The explore grid. Two columns on a phone rather than the one column .grid
   collapses to: these cards are a picture with a name under it, so they read
   fine narrow, and a browse page that shows two rows at a time instead of one
   is the difference between scanning and scrolling. */
.artist-grid {
    display: grid;
    gap: var(--space-3);
    grid-template-columns: repeat(2, 1fr);
    margin-top: var(--space-4);
}

@media (min-width: 40rem) {
    .artist-grid {
        gap: var(--space-4);
        /* auto-fill, not auto-fit: a single artist should stay card-sized
           instead of stretching across the whole row */
        grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr));
    }
}

/* The whole card is the link, so the name and the text below the picture are
   part of the click target — the picture alone is a small target on a phone. */
.artist-card {
    display: block;
    color: inherit;
    text-decoration: none;
}

/* aspect-ratio holds the space before the picture has loaded, so the grid does
   not jump as the thumbnails arrive, and it does that whatever shape the
   original was. The background is what fills that space in the meantime. */
.artist-card__image {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--radius);
    background: var(--color-bg-muted);
}

.artist-card__name {
    display: block;
    margin-top: var(--space-2);
    font-weight: 600;
}

.artist-card:hover .artist-card__name {
    color: var(--color-accent);
}

.artist-card__text {
    display: block;
    margin-top: var(--space-1);
    color: var(--color-ink-muted);
    font-size: 0.875rem;
}

/* The access level on a my-artists card. A quiet pill, not the accent badge
   premium content wears: this states a fact about the account, it does not
   sell anything. */
.artist-card__level {
    display: inline-block;
    margin-top: var(--space-1);
    padding: 0 var(--space-2);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    color: var(--color-ink-muted);
    font-size: 0.75rem;
    font-weight: 600;
}

/* The loader at the end of the grid is not a card, so it spans the whole row
   instead of one cell — a small box in the corner would read as a bug. htmx
   replaces it with the next page of cards when it scrolls into view; without
   javascript the link inside is the plain "next page" (see
   main/templates/main/_artist_cards.html). */
.artist-grid__loader {
    grid-column: 1 / -1;
    margin-top: var(--space-3);
    text-align: center;
}

/* The discipline filter of the explore grid. Pills rather than the underlined
   tabs of a profile (.content-tabs): switching a filter is a different
   gesture from switching a tab, and it should look like one. overflow-x for
   small phones — the whole taxonomy plus "All" outgrows a 320px screen, and
   scrolling the row beats wrapping it. */
.filter-chips {
    display: flex;
    gap: var(--space-2);
    margin-top: var(--space-4);
    overflow-x: auto;
    /* The active pill's border is part of its height; keep the row from
       clipping the focus ring of the last chip */
    padding-bottom: var(--space-1);
}

.filter-chips__chip {
    border: 1px solid var(--color-border);
    border-radius: 999px;
    color: var(--color-ink-muted);
    font-size: 0.9375rem;
    font-weight: 600;
    padding: var(--space-1) var(--space-3);
    text-decoration: none;
    white-space: nowrap;
}

.filter-chips__chip:hover {
    border-color: var(--color-ink-muted);
    color: var(--color-ink);
}

.filter-chips__chip--active,
.filter-chips__chip--active:hover {
    background: var(--color-accent);
    border-color: var(--color-accent);
    color: var(--color-accent-ink);
}

/* The picture above the text on a phone, beside it once there is room */
.artist-detail {
    display: grid;
    gap: var(--space-4);
    grid-template-columns: 1fr;
    align-items: start;
}

@media (min-width: 48rem) {
    .artist-detail {
        grid-template-columns: 20rem 1fr;
    }
}

.artist-detail__image {
    display: block;
    width: 100%;
    aspect-ratio: 1;
    object-fit: cover;
    border-radius: var(--radius);
    background: var(--color-bg-muted);
}

.artist-detail__text {
    color: var(--color-ink-muted);
    margin-top: var(--space-3);
}

/* The discipline under the artist's name — the same label the explore cards
   and filter chips use */
.artist-detail__discipline {
    color: var(--color-ink-muted);
    font-weight: 600;
    margin-top: var(--space-1);
}

/* --- content (the kind tabs on a profile) --------------------------------- */

/* The tabs are plain links (?kind=...) rendered server-side, so they work
   without javascript. overflow-x for small phones: three labels plus counts
   can outgrow a 320px screen, and scrolling the bar beats wrapping it. */
.content-tabs {
    display: flex;
    gap: var(--space-1);
    border-bottom: 1px solid var(--color-border);
    margin-top: var(--space-5);
    overflow-x: auto;
}

.content-tabs__tab {
    color: var(--color-ink-muted);
    font-weight: 600;
    padding: var(--space-2) var(--space-3);
    text-decoration: none;
    white-space: nowrap;
    /* The active tab underlines onto the bar's own border */
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;
}

.content-tabs__tab:hover {
    color: var(--color-ink);
}

.content-tabs__tab--active {
    color: var(--color-accent);
    border-bottom-color: var(--color-accent);
}

.content-tabs__count {
    color: var(--color-ink-muted);
    font-weight: 400;
}

/* The cards sit in the generic .grid (one column on a phone, auto-fit above
   40rem). The whole card is the link when the user may open the content —
   same reasoning as .artist-card. */
.content-card {
    display: block;
    position: relative;
    color: inherit;
    text-decoration: none;
}

/* 16:9: posters are the teaser image of a video/audio track, that is the
   shape they come in. aspect-ratio also holds the space before the picture
   arrives, so the grid does not jump. */
.content-card__poster {
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    border-radius: var(--radius);
    background: var(--color-bg-muted);
}

/* A piece without a poster gets the same box via the --empty modifier in the
   markup, which carries no styles of its own: .content-card__poster above
   already gives it shape and background, and there is no broken-image icon */

.content-card__title {
    display: block;
    margin-top: var(--space-2);
    font-weight: 600;
}

/* Only a card that actually links somewhere gets the hover colour — an <a>
   without href (a locked premium card) never matches this */
a.content-card:hover .content-card__title {
    color: var(--color-accent);
}

/* The premium marker, overlaid on the poster's corner */
.content-card__badge {
    position: absolute;
    top: var(--space-2);
    right: var(--space-2);
    background: var(--color-accent);
    color: var(--color-accent-ink);
    border-radius: var(--radius);
    font-size: 0.75rem;
    font-weight: 600;
    padding: var(--space-1) var(--space-2);
}

/* The overlay player (main/js/content-player.js). A native <dialog>: open it
   with showModal() and the browser centers it, traps focus and wires Esc —
   none of that is ours to reimplement. Light like the rest of the site, over
   a darkened backdrop. */
.content-player {
    width: min(56rem, 100vw - 2 * var(--space-3));
    border: none;
    border-radius: var(--radius);
    padding: var(--space-3);
    background: var(--color-bg);
    color: var(--color-ink);
}

.content-player::backdrop {
    background: rgba(0, 0, 0, 0.55);
}

.content-player__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-2);
    margin-bottom: var(--space-2);
}

.content-player__title {
    font-size: 1.125rem;
}

.content-player__close {
    border: none;
    background: none;
    color: var(--color-ink-muted);
    font-size: 1.5rem;
    line-height: 1;
    padding: var(--space-1) var(--space-2);
    cursor: pointer;
}

.content-player__close:hover {
    color: var(--color-ink);
}

/* 75dvh, not vh: on a phone the browser chrome comes out of vh and the media
   would sit under the controls. object-fit keeps a portrait image or an odd
   video inside the box without cropping. */
.content-player__stage img,
.content-player__stage video {
    display: block;
    width: 100%;
    max-height: 75dvh;
    object-fit: contain;
    background: var(--color-bg-muted);
    border-radius: var(--radius);
}

.content-player__stage audio {
    display: block;
    width: 100%;
    margin-top: var(--space-2);
}


/* --- auth pages --------------------------------------------------------- */

/* Allauth renders plain semantic markup (form > p > label + input, button,
   ul > li > a for the providers), so the pages are styled by element inside
   this one wrapper instead of by overriding every allauth template. */

.auth {
    max-width: 32rem;
    margin: 0 auto;
}

.auth h1 {
    font-size: 1.75rem;
}

.auth form {
    margin-top: var(--space-4);
}

.auth form p {
    margin-bottom: var(--space-3);
}

.auth label {
    display: block;
    font-weight: 600;
    margin-bottom: var(--space-1);
}

.auth input {
    width: 100%;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    color: inherit;
    font: inherit;
    padding: 0.6rem var(--space-2);
}

.auth input:focus {
    border-color: var(--color-accent);
}

/* Checkboxes ("remember me") keep their label on the same line */
.auth input[type="checkbox"],
.auth input[type="radio"] {
    width: auto;
    margin-right: var(--space-2);
}

.auth input[type="checkbox"] + label,
.auth input[type="radio"] + label {
    display: inline;
    font-weight: 400;
}

.auth button {
    display: inline-block;
    background: var(--color-accent);
    border: 1px solid transparent;
    border-radius: var(--radius);
    color: var(--color-accent-ink);
    font: inherit;
    font-weight: 600;
    padding: 0.7rem var(--space-4);
    cursor: pointer;
}

.auth button:hover {
    background: var(--color-accent-hover);
}

.auth .helptext,
.auth form span {
    color: var(--color-ink-muted);
    font-size: 0.875rem;
}

.auth .errorlist {
    color: #b3261e;
    font-size: 0.875rem;
    margin-bottom: var(--space-1);
}

/* Social provider list ("Sign in with ...") */
.auth .providers {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    margin-top: var(--space-4);
}

.auth .providers a {
    border: 1px solid var(--color-border);
    border-radius: var(--radius);
    color: var(--color-ink);
    display: block;
    font-weight: 600;
    padding: 0.7rem var(--space-4);
    text-align: center;
    text-decoration: none;
}

.auth .providers a:hover {
    border-color: var(--color-ink-muted);
}

/* --- messages ----------------------------------------------------------- */

/* The overlay base.html renders django messages into: fixed above the page
   instead of a block inside it, so any page can show one without making room
   in its layout. On a phone it spans the width, from tablet width up it is a
   column in the top right corner. */

.messages {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    position: fixed;
    top: var(--space-2);
    left: var(--space-2);
    right: var(--space-2);
    /* Above the sticky header (10) and the focused skip link (20) */
    z-index: 30;
}

@media (min-width: 40rem) {
    .messages {
        left: auto;
        width: 24rem;
    }
}

.message {
    align-items: baseline;
    animation: message-slide-in 0.25s ease-out;
    background: var(--color-bg);
    border: 1px solid var(--color-border);
    border-left-width: 4px;
    border-radius: var(--radius);
    box-shadow: 0 8px 24px rgba(23, 20, 31, 0.18);
    display: flex;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
    transition: opacity 0.4s, transform 0.4s;
}

/* Set by the dismiss script in base.html just before it removes the element */
.message--leaving {
    opacity: 0;
    transform: translateY(-0.5rem);
}

@keyframes message-slide-in {
    from {
        opacity: 0;
        transform: translateY(-0.5rem);
    }
}

@media (prefers-reduced-motion: reduce) {
    .message {
        animation: none;
        transition: none;
    }
}

.message__text {
    flex: 1;
}

.message__dismiss {
    background: none;
    border: 0;
    color: var(--color-ink-muted);
    cursor: pointer;
    font-size: 1.25rem;
    line-height: 1;
    padding: 0 var(--space-1);
}

.message__dismiss:hover {
    color: var(--color-ink);
}

.message--success {
    border-left-color: #2e7d32;
}

.message--warning {
    border-left-color: #b26a00;
}

.message--error {
    border-left-color: #b3261e;
}

/* --- misc --------------------------------------------------------------- */

.lead {
    color: var(--color-ink-muted);
    margin-top: var(--space-3);
    max-width: 42rem;
}

/* Visible only once it receives keyboard focus */
.skip-link {
    position: absolute;
    left: var(--space-3);
    top: -4rem;
    background: var(--color-accent);
    color: var(--color-accent-ink);
    border-radius: var(--radius);
    padding: var(--space-2) var(--space-3);
    z-index: 20;
}

.skip-link:focus {
    top: var(--space-2);
}
