/* =====================================================================
   SCOOP BBS 1.0  --  WEB INTERFACE, BUILD 4
   scoopbbs.css

   A BBS shown in a browser, not a website decorated to look like one.

   The rules this stylesheet keeps to:

     - Everything is monospaced and column-based.  Widths are in ch, so
       the layout is measured in characters the way a terminal is.
     - No rounded corners, no shadows, no gradients, no animation.  The
       only moving thing on the page is the block cursor, because a BBS
       had one.
     - Separators are real characters -- * = - -- not CSS borders
       pretending to be characters.
     - SIX COLOUR SCHEMES, ONE STYLESHEET.  Everything below paints with
       variables; the schemes at the top are the only place a colour is
       written down.  Adding a seventh is nine lines and no other edit.
   ===================================================================== */


/* ---------------------------------------------------------------------
   THE SCHEMES

   --bbs-background          the screen
   --bbs-text                ordinary text
   --bbs-bright              emphasised text
   --bbs-highlight           headings, values worth the eye
   --bbs-selection-background   the selected row
   --bbs-selection-text
   --bbs-border              rules, bands, box drawing
   --bbs-muted               secondary text, brackets, hints
   --bbs-hotkey              the command letter inside [B]
   --------------------------------------------------------------------- */

:root,
html[data-scheme="white-on-blue"] {
    --bbs-background: #0000aa;
    --bbs-text: #cccccc;
    --bbs-bright: #ffffff;
    --bbs-highlight: #ffff55;
    --bbs-selection-background: #cccccc;
    --bbs-selection-text: #0000aa;
    --bbs-border: #ffffff;
    --bbs-muted: #8888cc;
    --bbs-hotkey: #ffff55;
}

html[data-scheme="yellow-on-blue"] {
    --bbs-background: #0000aa;
    --bbs-text: #ffff55;
    --bbs-bright: #ffffff;
    --bbs-highlight: #ffffff;
    --bbs-selection-background: #ffff55;
    --bbs-selection-text: #0000aa;
    --bbs-border: #ffff55;
    --bbs-muted: #b0b040;
    --bbs-hotkey: #ffffff;
}

html[data-scheme="white-on-black"] {
    --bbs-background: #000000;
    --bbs-text: #c0c0c0;
    --bbs-bright: #ffffff;
    --bbs-highlight: #ffff55;
    --bbs-selection-background: #c0c0c0;
    --bbs-selection-text: #000000;
    --bbs-border: #ffffff;
    --bbs-muted: #808080;
    --bbs-hotkey: #ffff55;
}

html[data-scheme="green-on-black"] {
    --bbs-background: #000000;
    --bbs-text: #00cc33;
    --bbs-bright: #66ff66;
    --bbs-highlight: #ccffcc;
    --bbs-selection-background: #00cc33;
    --bbs-selection-text: #000000;
    --bbs-border: #00cc33;
    --bbs-muted: #007a1f;
    --bbs-hotkey: #ccffcc;
}

html[data-scheme="cyan-on-black"] {
    --bbs-background: #000000;
    --bbs-text: #00cccc;
    --bbs-bright: #66ffff;
    --bbs-highlight: #ccffff;
    --bbs-selection-background: #00cccc;
    --bbs-selection-text: #000000;
    --bbs-border: #00cccc;
    --bbs-muted: #007a7a;
    --bbs-hotkey: #ccffff;
}

html[data-scheme="amber-on-black"] {
    --bbs-background: #000000;
    --bbs-text: #ffb000;
    --bbs-bright: #ffd070;
    --bbs-highlight: #ffe8b0;
    --bbs-selection-background: #ffb000;
    --bbs-selection-text: #000000;
    --bbs-border: #ffb000;
    --bbs-muted: #a06800;
    --bbs-hotkey: #ffe8b0;
}


/* ---------------------------------------------------------------------
   THE PAGE

   The browser surround is the scheme's own background, so the BBS fills
   the window in colour while its CONTENT stays centred at the same
   width it has always had.
   --------------------------------------------------------------------- */

* { box-sizing: border-box; }

/*  THE WHOLE PAGE IS THE SCREEN.
    Build 1 painted the surround black always, which was right for the
    four black schemes and wrong for the two blue ones -- a small blue
    rectangle adrift in a black field.  The surround now follows
    --bbs-background, so the boundary between the BBS and the browser
    disappears in every scheme: black merges into black, blue into blue.
    The scheme variables live on <html>, so this needs nothing but the
    variable, and it repaints the instant the attribute changes.

    THE CONTENT IS STILL BOUNDED.  #terminal is centred at a fixed
    maximum -- 100ch from Build 3 -- and is deliberately given no
    background of its own: one flat field of colour with the screen in
    the middle of it, which is what the native client looks like when it
    is run full screen. */
html {
    background: var(--bbs-background);
}

body {
    margin: 0;
    padding: 1.25rem 0.75rem 2rem;
    background: var(--bbs-background);
    color: var(--bbs-text);
    font-family: "DejaVu Sans Mono", "Liberation Mono", "Consolas",
                 "Menlo", "Courier New", monospace;
    font-size: clamp(12px, 1.55vw, 16px);
    line-height: 1.35;
    -webkit-text-size-adjust: 100%;
}

#terminal {
    /*  ONE HUNDRED COLUMNS, from Build 3.
        A BBS screen is 80 wide and the frame still draws as though it
        were; this is the room around it, and at 100ch a message list
        has space for a subject without eliding it.  It is a MAXIMUM:
        a narrower window still gets the whole interface, reflowed by
        the rules at the bottom of this file, and a very wide one still
        gets a bounded, centred screen rather than a stretched one. */
    width: 100%;
    max-width: 100ch;
    margin: 0 auto;
    color: var(--bbs-text);
    padding: 0.5rem 1ch 0.75rem;
    min-height: 90vh;
    display: flex;
    flex-direction: column;
    /*  No background and no border.  The page behind it is already the
        right colour, so there is nothing here to see the edge of. */
}


/* ---------------------------------------------------------------------
   THE TITLE BAND -- rows 1 to 3

   Three lines of asterisks with the screen's name in the middle of the
   second one.  The fill rows hold far more asterisks than will fit and
   are clipped, so the band is full width at any window size without
   any JavaScript counting columns.
   --------------------------------------------------------------------- */

.band { flex: 0 0 auto; }

.fill {
    overflow: hidden;
    white-space: nowrap;
    color: var(--bbs-border);
    user-select: none;
}

.fill::before {
    content: "****************************************************************"
             "****************************************************************"
             "****************************************************************";
}

.bandline {
    display: grid;
    grid-template-columns: 1ch 1fr 1ch;
    align-items: baseline;
    color: var(--bbs-border);
}

.edge { user-select: none; }

.bandtitle {
    margin: 0;
    font-size: inherit;
    font-weight: normal;
    text-align: center;
    color: var(--bbs-bright);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}


/* ---------------------------------------------------------------------
   RULES

   Same trick as the band: a long string, clipped.
   --------------------------------------------------------------------- */

.rule, .thinrule {
    overflow: hidden;
    white-space: nowrap;
    color: var(--bbs-border);
    user-select: none;
}

.rule::before {
    content: "================================================================"
             "================================================================"
             "================================================================";
}

.thinrule {
    color: var(--bbs-muted);
}

.thinrule::before {
    content: "----------------------------------------------------------------"
             "----------------------------------------------------------------"
             "----------------------------------------------------------------";
}


/* ---------------------------------------------------------------------
   THE WORK AREA
   --------------------------------------------------------------------- */

#screen {
    flex: 1 1 auto;
    padding: 1em 0 1em;
    outline: none;
    min-height: 20em;
}

#screen h2 {
    margin: 0 0 1em;
    font-size: inherit;
    font-weight: normal;
    color: var(--bbs-highlight);
    text-align: center;
}

.pad { padding-left: 2ch; }

p { margin: 0 0 1em; }

.muted   { color: var(--bbs-muted); }
.bright  { color: var(--bbs-bright); }
.hilite  { color: var(--bbs-highlight); }

/* Text that came from a person or from the server.  Always set with
   textContent; this class only says "keep the author's line breaks". */
.plain {
    white-space: pre-wrap;
    overflow-wrap: break-word;
    margin: 0;
    font: inherit;
    color: var(--bbs-text);
}


/* ---------------------------------------------------------------------
   COMMANDS

   [B] Bulletin Board -- the brackets are quiet, the letter is not.
   A command is a real <button> so that it is clickable, focusable and
   reachable by a screen reader, but it is painted as plain text.
   --------------------------------------------------------------------- */

.cmd {
    display: inline;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: var(--bbs-text);
    cursor: pointer;
    text-align: left;
}

.cmd .br { color: var(--bbs-muted); }
.cmd .k  { color: var(--bbs-hotkey); }

.cmd:hover .lbl,
.cmd:focus-visible .lbl { color: var(--bbs-bright); }

.cmd:focus-visible {
    outline: 1px solid var(--bbs-border);
    outline-offset: 1px;
}

.cmd[disabled] { cursor: default; opacity: 0.45; }
.cmd[disabled] .k { color: var(--bbs-muted); }

/* The two-column menu of the Scoop client. */
.menu {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.15em 2ch;
    padding-left: 2ch;
    margin-bottom: 1.25em;
}

.menu .cmd { display: block; }

.menu-note {
    padding-left: 2ch;
    color: var(--bbs-muted);
    margin-bottom: 0;
}

/* New-material marker. */
.newmark { color: var(--bbs-highlight); }


/* ---------------------------------------------------------------------
   LISTS

   Message lists, user lists and file lists are all the same shape: a
   header row, a thin rule, then rows that can be selected.  They are
   laid out with grid rather than a <table> so that a narrow screen can
   reflow them without horizontal scrolling.
   --------------------------------------------------------------------- */

.list { margin: 0 0 0.75em; }

.listhead {
    color: var(--bbs-bright);
    padding: 0 1ch;
}

.row {
    display: block;
    width: 100%;
    border: 0;
    background: none;
    font: inherit;
    color: var(--bbs-text);
    text-align: left;
    padding: 0 1ch;
    cursor: pointer;
}

.row:hover { color: var(--bbs-bright); }

.row.sel {
    background: var(--bbs-selection-background);
    color: var(--bbs-selection-text);
}

.row.sel .muted,
.row.sel .hilite,
.row.sel .bright { color: var(--bbs-selection-text); }

.row:focus-visible {
    outline: 1px solid var(--bbs-border);
    outline-offset: -1px;
}

.cols {
    display: grid;
    align-items: baseline;
    gap: 0 1ch;
}

/* NUM  DATE  FROM  SUBJECT */
.cols-msg   { grid-template-columns: 5ch 15ch 12ch 1fr; }
/* HANDLE  DISPLAY NAME  LAST CALL */
.cols-user  { grid-template-columns: 14ch 1fr 14ch; }
/* FILENAME  TYPE  SIZE  DESCRIPTION */
.cols-file  { grid-template-columns: 22ch 9ch 8ch 1fr; }

.cell { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.cell.num { text-align: right; }
.cell.size { text-align: right; }

.tally {
    padding: 0 1ch;
    color: var(--bbs-muted);
    /*  Runs of spaces are columns here, not accidents.  Without this the
        browser collapses "3 messages,     2 new" into one space and the
        line stops lining up with the one above it. */
    white-space: pre;
    overflow: hidden;
    text-overflow: ellipsis;
}


/* ---------------------------------------------------------------------
   MESSAGE VIEW
   --------------------------------------------------------------------- */

.msghead { padding-left: 2ch; margin-bottom: 0.5em; }

.msghead .line { display: block; }

.msghead .label {
    display: inline-block;
    width: 10ch;
    color: var(--bbs-text);
}

.msgtop {
    color: var(--bbs-highlight);
    margin-bottom: 0.35em;
    white-space: pre;          /* the header's column spacing is real */
    overflow: hidden;
    text-overflow: ellipsis;
}

.msgbody { padding: 0.75em 2ch; }


/* ---------------------------------------------------------------------
   FIELDS

   A real <input>, painted to look like a BBS entry field: an underline
   of characters is not workable in a browser, so a flat block in the
   selection colour stands in for it, exactly as the Scoop client draws
   an input field as a filled bar.
   --------------------------------------------------------------------- */

.field { padding-left: 2ch; margin-bottom: 0.6em; }

.field label {
    display: inline-block;
    width: 12ch;
    color: var(--bbs-text);
}

.field input,
.field textarea,
.field select {
    font: inherit;
    color: var(--bbs-selection-text);
    background: var(--bbs-selection-background);
    border: 0;
    padding: 0 1ch;
    width: min(44ch, 100%);
    vertical-align: baseline;
}

.field textarea {
    display: block;
    margin-top: 0.4em;
    width: min(72ch, 100%);
    height: 12em;
    resize: vertical;
    line-height: 1.35;
}

.field input:focus,
.field textarea:focus {
    outline: 1px solid var(--bbs-border);
    outline-offset: 1px;
}

.field .hint {
    display: block;
    padding-left: 12ch;
    color: var(--bbs-muted);
}

/*  BUILD 4.  A wider label column, for the Request an Account screen.

    Every label on the older screens is short -- "Handle:", "Subject:",
    "To:" -- and 12ch held them all.  The request screen asks for a
    "Desired handle:" and an "Email/contact:", which are 15 and 14, and
    at 12ch the first two wrapped onto a second line while the third,
    having no space in it to break at, simply ran under its own input
    box and read "Email/contac".

    So the wider column is asked for by name, on the one screen that
    needs it, rather than widening every form on the board.  */
.field.wide label { width: 18ch; }
.field.wide .hint { padding-left: 18ch; }

@media (max-width: 52ch) {
    /*  On a narrow screen the label sits above its field anyway (the
        rule further down), so the wide column would only push the
        inputs off the edge. */
    .field.wide label,
    .field.wide .hint { width: auto; padding-left: 0; }
}

.actions { padding-left: 2ch; margin-top: 1em; }
.actions .cmd { margin-right: 3ch; }

.error {
    padding-left: 2ch;
    color: var(--bbs-highlight);
    margin-bottom: 0.75em;
}


/*  The composer's character counter.  Quiet until it matters. */
.counter {
    padding-left: 2ch;
    color: var(--bbs-muted);
    white-space: pre;
}

.counter.over { color: var(--bbs-highlight); }


/*  Label-and-value rows, as the Information screen uses.  A class, not
    an inline style, so the label column is set in one place. */
.kv { padding-left: 2ch; }

.kv-label {
    display: inline-block;
    width: 13ch;
    color: var(--bbs-text);
}

/*  BUILD 4.  One row, on the request-sent screen, whose label is
    "Desired handle:" -- fifteen characters against the thirteen that
    fits every label on the Information screen.  Widened where it is
    used rather than everywhere, so the Information screen keeps its
    existing column.  */
.kv.wide .kv-label { width: 17ch; }

.kv-gap { height: 1em; }


/* ---------------------------------------------------------------------
   THE FRAME BELOW THE WORK AREA
   --------------------------------------------------------------------- */

#frame { flex: 0 0 auto; }

.boardname {
    text-align: center;
    color: var(--bbs-bright);
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.status { color: var(--bbs-text); }

.statline {
    display: block;
    overflow: hidden;
    /*  pre, not nowrap: the status block is columns of text separated by
        runs of spaces, exactly as the Scoop client draws it, and nowrap
        would collapse them all to one space. */
    white-space: pre;
    text-overflow: ellipsis;
}

/* The command/help line above the status block. */
.cmdline { color: var(--bbs-text); margin-bottom: 0.15em; }
.cmdline .cmd { margin-right: 2ch; }

.prompt { margin-top: 0.75em; color: var(--bbs-text); }
.prompt-label { color: var(--bbs-bright); }

/* The block cursor.  The one animation on the page, because a BBS
   prompt blinked and a still one looks broken. */
.caret {
    display: inline-block;
    width: 1ch;
    background: var(--bbs-text);
    animation: blink 1.1s steps(1) infinite;
}

@keyframes blink {
    0%, 49%   { opacity: 1; }
    50%, 100% { opacity: 0; }
}

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

.software {
    color: var(--bbs-muted);
    margin-top: 0.4em;
}


/* ---------------------------------------------------------------------
   THE NOTICE LINE

   A one-off message at the top of a screen -- "your message was
   posted", and the like.  In Build 1 this said, every time, that the
   board was running on invented data; there is no invented data any
   more, but the line itself is still used for ordinary notices.
   --------------------------------------------------------------------- */

.sample {
    color: var(--bbs-highlight);
    padding: 0 1ch 0.5em;
}


/* ---------------------------------------------------------------------
   NARROW SCREENS

   Still a BBS: same characters, same colours, same structure.  What
   changes is that columns which cannot fit are dropped rather than
   squeezed, and the menu becomes one column.  Nothing here turns it
   into a phone app.
   --------------------------------------------------------------------- */

@media (max-width: 52ch) {
    .menu { grid-template-columns: 1fr; }
    .cols-msg  { grid-template-columns: 4ch 11ch 1fr; }
    .cols-user { grid-template-columns: 13ch 1fr; }
    .cols-file { grid-template-columns: 1fr 7ch; }
    .hide-narrow { display: none; }
    .field label { display: block; width: auto; }
    .field .hint { padding-left: 0; }
    .msghead .label { width: 9ch; }
    body { padding: 0.5rem 0.4rem 1.5rem; }
    #terminal { padding: 0.4rem 0.5ch 0.6rem; }
}
