/* The look of every page on aule.dev: paper, beams, small caps. Horizontal measures in ch, vertical in lh.
   A page links this first, then its own sheet, whose layers come after these two. */
@layer reset, base;

/* Going from page to page is a view transition: the header morphs between its two sizes, the rest cross-fades. */
@view-transition { navigation: auto; }
::view-transition-group(brand), ::view-transition-group(header), ::view-transition-group(nav) { animation-duration: .3s; }

/* B612 Mono (Airbus, OFL): made for cockpit screens. Two weights and a true italic, so a heading is 700 and nothing is synthesized. */
@font-face { font-family: 'B612 Mono'; src: url('/fonts/B612Mono-Regular.woff2'); font-display: swap; }
@font-face { font-family: 'B612 Mono'; src: url('/fonts/B612Mono-Bold.woff2'); font-weight: 700; font-display: swap; }
@font-face { font-family: 'B612 Mono'; src: url('/fonts/B612Mono-Italic.woff2'); font-style: italic; font-display: swap; }
@font-face { font-family: 'B612 Mono'; src: url('/fonts/B612Mono-BoldItalic.woff2'); font-weight: 700; font-style: italic; font-display: swap; }

@layer reset {
    *, ::before, ::after { box-sizing: border-box; text-underline-offset: .35em; } /* an underline sits under its own words, whatever their size */
    body, p, h1, h2, h3, ul, ol, menu, dl, dd, figure, blockquote, pre, hr { margin: 0; }
    [hidden] { display: none; }
    button, input, textarea { font: inherit; color: inherit; }
    summary { cursor: pointer; list-style: none; &::-webkit-details-marker { display: none; } }
}

@layer base {
    :root {
        color-scheme: light dark;
        --ink: light-dark(#111, #f2e6dc);
        --paper: light-dark(#f4f1ea, #351d17);
        --card: light-dark(#fffdf8, #3f2620);
        --accent: light-dark(#8a6a2a, #ff8a3d);
        --good: light-dark(#1f7a3a, #9fd8a4);
        --bad: light-dark(#7a1f1f, #ff6b5e);
        --shade: light-dark(#111, #0e0201); /* a shadow is dark in both looks: the dark paper is warm umber, not black, so it shows */
        --mute: color-mix(in oklab, var(--ink) 55%, var(--paper));
        --dot: color-mix(in oklab, var(--ink) 20%, var(--paper));
        --beam: 3px;
        --edge: var(--beam) solid var(--ink);
        --hair: 1px dashed var(--mute);
        &[data-scheme=light] { color-scheme: light; }
        &[data-scheme=dark] { color-scheme: dark; }
    }
    body {
        font: 16px/24px 'B612 Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
        color: var(--ink);
        background: var(--paper) radial-gradient(var(--dot) 1px, transparent 1.2px) 0 0 / 10px 10px;
    }
    p, dd, li, blockquote { text-wrap: pretty; }

    /* Two voices of capitals: a title (wide and bold), and a label (small, a little spaced): every button, summary and choice. */
    h1, h2, h3, .brand { text-transform: uppercase; letter-spacing: .25em; font-weight: 700; line-height: 1lh; }
    h1 { font-size: 1.25em; line-height: 1.5lh; } /* a page's own name, under the header */
    h2, h3 { font-size: .75em; }
    .label, button, summary, #prefs label, dt { font-size: .75em; letter-spacing: .1em; text-transform: uppercase; }
    .label, summary, .mute, .caption, .none, .musing, .quiet { color: var(--mute); }
    .none, .musing { font-style: italic; }
    .musing::after { content: '…'; animation: musing 1.2s steps(3) infinite; }
    @keyframes musing { to { content: ''; } }

    /* A title between two beams, which take its colour. */
    h2 { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; column-gap: 2ch; text-align: center;
        &::before, &::after { content: ''; border-block-start: var(--beam) solid; } }
    /* A box: a beam edge, a hard shadow, and lines inside. */
    .box { background: var(--card); border: var(--edge); box-shadow: .6ch .25lh 0 var(--shade); padding: .5lh 2ch; }

    a { color: inherit; text-decoration-thickness: 1px; &:hover { text-decoration-color: var(--accent); } }
    /* A button is underlined small caps; the primary action is a filled block. */
    button {
        cursor: pointer; line-height: 1lh; font-weight: 700; background: none; border: 0; padding: .25lh 0;
        text-decoration: underline 1px; &:hover { text-decoration-color: var(--accent); }
        &.primary { background: var(--ink); color: var(--paper); text-decoration: none; padding: .5lh 2ch; }
    }
    a.primary { display: inline-block; font-size: .75em; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; line-height: 1lh; background: var(--ink); color: var(--paper); text-decoration: none; padding: .5lh 2ch; } /* a link that is the primary action */
    :where(button):disabled { color: var(--mute); text-decoration: none; cursor: wait; } /* below what is on, so a picked answer stays picked */
    :focus-visible, label:has(:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
    /* What is on, whatever it is: a checked choice, a pressed toggle, a picked answer. */
    label:has(:checked), [aria-pressed=true], .picked { color: var(--accent); text-decoration: underline var(--beam) var(--accent); }
    /* An input is a line to write on. A form of one line and its button lays them side by side, its label and error above and below. */
    input {
        width: 100%; min-width: 0; line-height: 1lh; background: none; border: 0; border-block-end: 1px solid; padding: 0; border-radius: 0;
        &::placeholder { color: var(--mute); font-style: italic; }
        &:focus { outline: none; border-block-end-color: var(--accent); box-shadow: 0 1px var(--accent); }
    }
    form:has(> input + button) { display: grid; grid-template-columns: 1fr auto; gap: .25lh 1ch; align-items: end; > :is(.label, .err) { grid-column: 1 / -1; } }
    /* A form of labelled lines sets each label's words beside its line; anything else in it takes the whole width. */
    form:has(> label > .label + input) { display: grid; grid-template-columns: auto 1fr; align-items: baseline; gap: .25lh 1ch; label { display: contents; } > :not(label, input) { grid-column: 1 / -1; } }
    .err { color: var(--bad); font-style: italic; }

    /* One column of paper. */
    #page {
        container: page / inline-size;
        max-width: 72ch; margin: 0 auto; padding: .5lh 1.5ch 2lh; display: grid; gap: 1lh;
        > * { min-width: 0; }
    }
    /* The header every page shares: the name on the left, settings and where they stand on the right. Big on the home page,
       its links on the tagline's last baseline; one line elsewhere, with a chevron before the name, a cap high on its baseline. */
    header {
        display: flex; justify-content: space-between; align-items: baseline; gap: 2ch; border-block-end: var(--edge); padding-block-end: .25lh;
        view-transition-name: header;
        .brand { line-height: 1.5lh; text-decoration: none; view-transition-name: brand; a { text-decoration: none; } }
        &:not(.home) .brand { display: inline-flex; align-items: baseline; gap: 1ch; svg { height: 1cap; fill: currentColor; } }
        &.home { padding-block: 1lh .5lh; align-items: last baseline; .brand { font-size: 2.25em; line-height: 2lh; } > div { display: grid; } }
        nav { display: flex; flex-wrap: wrap; justify-content: end; gap: 0 2ch; align-items: baseline; view-transition-name: nav; > * { white-space: nowrap; } }
        /* Where they stand, as an LED linking to /join: off without a key, amber while a payment is unconfirmed, green with a key (a guest's too, the word muted), red when one was refused or a membership lapsed. */
        #who { display: inline-flex; align-items: center; gap: .75ch; color: var(--led, var(--mute)); font-weight: 700; font-size: .75em; letter-spacing: .1em; text-transform: uppercase; line-height: 1lh; padding-block: .25lh;
            &::before { content: ''; width: .75em; height: .75em; border-radius: 50%; background: var(--led, var(--dot)); box-shadow: 0 0 .5em var(--led, transparent); } }
        #who:is([data-state=member], [data-state=guest]) { --led: var(--good); }
        #who[data-state=guest] { color: var(--mute); }
        #who[data-state=pending] { --led: var(--accent); }
        #who:is([data-state=refused], [data-state=lapsed]) { --led: var(--bad); }
        #who[data-state=master] { --led: var(--ink); }
        #metrics { font-weight: 700; font-size: .75em; letter-spacing: .1em; text-transform: uppercase; line-height: 1lh; padding-block: .25lh; } /* the dashboard, for an insider or the master (metrics.odin) */
    }

    /* A block of prose, filled in from its HTML beside the page. For the master, a tiny "edit" in its top corner opens the
       editor: the prose written in place (dashed while it is; a click on a picture changes it), the helper bar, cancel and
       save. Where the items are cards (a picture and parts in a div, as the inspiration) each part is written alone, and the
       bar offers the card's buttons instead of the prose's. Without script the HTML shows in a textarea instead. */
    .block { position: relative; }
    #page:is([data-state=member], [data-state=master]) .signup { display: none; } /* the wording about joining, free and who gets in: for whoever has not got in yet */
    .prose { display: grid; gap: 1lh; :is(ul, ol) { padding-inline-start: 3ch; } blockquote { font-style: italic; color: var(--accent); } }
    .block.live .prose {
        outline: 1px dashed var(--accent); outline-offset: 1ch; caret-color: var(--accent);
        img { cursor: pointer; } img[hidden] { display: block; } /* a picture that failed to load shows, broken, so its address can be fixed */
        figure:empty { height: 3lh; align-self: start; border: 1px dashed var(--accent); display: grid; place-content: center; cursor: pointer;
            &::after { content: 'picture'; font-size: .625em; letter-spacing: .1em; text-transform: uppercase; color: var(--accent); } }
    }
    .block:not(:has(li > div)) [data-cmd$=card], .block:has(li > div) :is([data-cmd=bold], [data-cmd=italic], [data-cmd=heading], [data-cmd=list]) { display: none; }
    .block:not(.live) menu, .block.live textarea { display: none; } /* the bar is script's; the textarea is for no script */
    .editor {
        summary { position: absolute; inset-block-start: -.75lh; inset-inline-end: 0; font-size: .625em; font-weight: 700; line-height: 1lh; text-decoration: underline 1px; }
        &[open] summary { display: none; }
        form { margin-block-start: .5lh; display: grid; gap: .5lh; }
        menu { padding: 0; display: flex; flex-wrap: wrap; gap: 0 2ch; b, i { font-size: 1.25em; } }
        textarea {
            width: 100%; field-sizing: content; min-height: 6lh; max-height: 60vh; line-height: 1lh;
            background: var(--card); border: var(--hair); padding: .5lh 1ch; resize: vertical; border-radius: 0;
            &:focus { outline: none; border: 1px solid var(--accent); }
        }
        .row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: .5lh 2ch; }
        .label { font-size: .625em; white-space: nowrap; }
        .row span:last-child { display: flex; gap: 2ch; align-items: baseline; }
    }
    /* On a touch screen the bar stays in view while a block is edited: across the bottom, on top of the keyboard when it is
       up, one row that scrolls sideways. The keyboard overlays the page while a block is live (aule.js), so Chrome gives its
       height as keyboard-inset-height; the page gets room under the bar, and the caret is kept above both. */
    @media (pointer: coarse) {
        :root:has(.block.live) { scroll-padding-block-end: calc(4lh + env(keyboard-inset-height, 0px)); }
        .block.live menu {
            position: fixed; inset-inline: 0; inset-block-end: env(keyboard-inset-height, 0px); z-index: 1;
            flex-wrap: nowrap; overflow-x: auto; background: var(--paper); border-block-start: var(--edge);
            padding: .5lh 1.5ch calc(.5lh + env(safe-area-inset-bottom, 0px)); > * { flex: none; }
        }
        main:has(.block.live) { padding-block-end: calc(4lh + env(keyboard-inset-height, 0px)); }
    }

    /* A dialog is a box over a checker dither of black, short of the screen all round so a tap outside always closes it. */
    dialog {
        margin: auto; width: min(40ch, 100% - 6ch); max-height: calc(100% - 4lh); overflow: auto;
        color: var(--ink); background: var(--card); border: var(--edge); box-shadow: .6ch .25lh 0 var(--shade); padding: 1lh 2ch;
        &::backdrop { background: repeating-conic-gradient(#000 0 25%, transparent 0 50%) 0 0 / 4px 4px; }
        &[open] { display: grid; gap: .5lh; align-content: start; }
        form:not([hidden]) { display: grid; gap: .5lh; justify-items: start; }
    }
    /* The made-with list every page may open. */
    #credits {
        width: min(64ch, 100% - 6ch);
        dl { display: grid; grid-template-columns: auto 1fr; gap: .25lh 2ch; align-items: baseline; }
        dt { white-space: nowrap; font-weight: 700; }
        dd { font-size: .875em; .mute { white-space: nowrap; } }
        @container page (width < 56ch) { dl { grid-template-columns: 1fr; gap: 0; } dt { margin-block-start: .25lh; } }
    }
    /* The settings: a choice is its underlined label, the radio itself out of sight. */
    :where(#prefs) {
        h3:not(:first-child) { margin-block-start: .5lh; }
        label { cursor: pointer; text-decoration: underline 1px; }
        input { position: absolute; opacity: 0; width: 0; height: 0; }
        button { justify-self: end; }
    }
    /* Sharing a list: a link to copy, or the offer to take one. */
    #share {
        justify-items: start;
        .key { padding: .5lh 2ch; border: var(--hair); font-size: 1.125em; line-height: 1.5lh; color: var(--accent); user-select: all; white-space: pre-wrap; overflow-wrap: anywhere; justify-self: stretch; }
        .row { display: flex; justify-content: space-between; align-items: baseline; justify-self: stretch; form { display: contents; } }
    }
}
