
/*
topbar-tabs.css
the default look of the tabs in the topbar (dark mode)
*/

.tabs {
    background-color: #2a2a2a;
    display: flex;
    /* The row never wraps : a window wide enough to show the tabs has always had room for all
       six on one line, and a window too narrow for them does not draw them here at all - the
       menu lists them vertically instead - so the row cannot be wider than the window there
       either. */
    justify-content: center;
    align-items: center;
    border-bottom: 1px solid #444;
    position: relative;
}
/* The padding sits on the link rather than on the box around it, so the whole area that looks
   like a tab is the area a tap actually reaches. With the padding on the outer box, only the
   text itself was the link and the inch of space around it did nothing - which is hard to
   notice with a mouse and constant on a finger. The box is unchanged in size : the same padding
   on the same font, carried by the element inside instead of the one outside. */
.tab { cursor: pointer; }
.tab a { display: block; padding: 14px 24px; text-decoration: none; color: #eaeaea; font-weight: 500; }
.tab.active { background-color: #3a3a3a; border-bottom: 3px solid #4db6ff; }
.tab:hover { background-color: #3f3f3f; }

/* the light mode override */

body.light-mode .tabs {
    background-color: #e5e5e5;
    border-bottom: 1px solid #ccc;
}
body.light-mode .tab a {
    color: #1f1f1f;
}
body.light-mode .tab.active {
    background-color: #dcdcdc;
    border-bottom: 3px solid #007acc;
}
body.light-mode .tab:hover {
    background-color: #d0d0d0;
}

/* the way in and out of an account, held at the row's right edge

   Out of the flow and pinned to the edge, which is what the theme toggle already does at the
   other end of this row and is the same trade made for the same reason. The cost, so that nobody
   meets it as a surprise : a box that has left the flow reserves no space, so the centred line of
   entries beside it is centred against the window rather than against what is left over next to
   this control. Left in the flow it would push that line sideways by its own width, and where
   that line sits is the one thing about this row that is not allowed to move.

   Being a positioned box is also what the menu below hangs off. It is placed against this element
   and not against the row, so the menu comes out under the name at every width and no number
   anywhere describes where the name happens to be.

   Nothing new enters the site here. The padding is the entries' own, so the word reads at the
   same size in the same place as the six beside it and the box a finger lands on is the whole of
   what looks like a control rather than just the letters. The colour is inherited rather than
   written, which is how both themes are answered by one rule : the surrounding text is already
   the pair of colours the entries above are drawn in. A button is the one element that arrives
   carrying a colour, a font and a border of the browser's own choosing, and it is the reason
   those are said out loud - said nowhere, the account button would be a pale slab with near-black
   text on the dark row, which is exactly how the two drawer buttons were once reported.

   The display value is the one declaration here that looks like tidying and is not, and it was
   arrived at by measuring the drawn box. Padding on a box that flows as text adds nothing to the
   height of the line it sits on, so the link came out twenty-one pixels tall - a target well under
   the size every other control at a phone width is held to on this site, while looking perfectly
   correct in the stylesheet. Made a box of its own it is forty-nine, which is the height of the
   entries beside it.

   The three controls are named one by one rather than as "every link and every button inside the
   control", and that is load-bearing rather than tidy : a selector naming an element as well as a
   class outweighs one naming a class alone, so the shared look written that way could not be
   answered by any of the rules below without a selector built to outweigh it. Named this way they
   all weigh the same and the later rule wins, which is what a reader expects.

   THE WIDTH IT MAY NOT EXCEED IS NOT DECORATION HERE EITHER, and it was found by driving a wide
   window rather than by reading this file. The row of entries is centred against the window and
   this box is out of the flow, so nothing pushes the two apart : an account name at the longest
   length this site allows made this control 433 pixels wide and it was drawn straight over the
   last two entries. Measured in a 1280 window, the entries end 173 pixels from the right-hand
   edge and this share of the window comes to 166 of them.

   A share of the window rather than a fixed number, because the room beside the entries grows
   twice as fast as this limit does : the entries are a fixed width whatever the window, so every
   pixel added to the window adds half a pixel of room on this side and thirteen hundredths of a
   pixel to the limit. It is therefore safe at the width it was measured at and safer at every
   width above it. Below that width the entries themselves are already close to filling the row,
   and one word at the right-hand edge has always overlapped them there. */
#identity-control {
    position: absolute;
    right: 10px;
    max-width: 13vw;
}

.identity-login-link,
.identity-menu-button,
.identity-menu-entry {
    display: inline-block;
    background-color: transparent;
    border: none;
    padding: 14px 24px;
    color: inherit;
    font: inherit;
    font-weight: 500;
    text-decoration: none;
    cursor: pointer;
}

/* The name and the arrow on one line, with the name free to be cut and the arrow never cut.

   A flex line is what makes those two different : the name is allowed to shrink below the width
   of its own text and the arrow is not, so what disappears when there is no room is the end of a
   name and never the mark that says this opens. `min-width: 0` is what allows that shrink at all -
   a flex item refuses by default to become narrower than its content, which is exactly the
   refusal that hides the arrow instead of the letters.

   The overflow is written here and not on the element around it, and the difference is the whole
   defect this control was rebuilt for : the menu is a sibling of this button, so a box clipped
   here clips a name and a box clipped one level up clips the opened menu away with it. */
.identity-menu-button {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    overflow: hidden;
}

/* One box around either kind of picture, so the unread dot has the same anchor whether the account
   supplies an image or uses the built-in artwork.

   The colour alias deliberately keeps a decorative warning surface outside the palette's text
   contrast matrix. That blind spot is acceptable only because the dot contains no text at all, a
   condition the discussion checker reads from rendered markup. If text is ever drawn on the dot or
   another surface using this alias, the alias has to be reconsidered and its contrast measured by
   hand. This differs from the unread tint beside ordinary surfaces: a tint can clear the text floor
   and still read as a tint, while a warning red cannot clear every palette colour and remain red. */
.identity-picture-box {
    --identity-unread-dot-colour: var(--error-dark);

    position: relative;
    display: inline-flex;
    flex: none;
}

body.light-mode .identity-picture-box {
    --identity-unread-dot-colour: var(--error-light);
}

/* The picture, which is the third thing on a line that was measured with two things on it.

   IT DOES NOT SHRINK, and that is the whole of what this rule has to get right. The name is the item
   allowed to be cut short and the arrow is the item that is never cut ; the picture belongs with the
   arrow, because the room it takes is a fixed number of pixels while a name's is whatever somebody
   chose, and a picture squeezed to a sliver says less than no picture at all. What gives way when the
   room runs out is therefore the end of the name, exactly as it was before this picture existed.

   Sized against the row and not against the stored file : the entries beside it are forty-nine pixels
   tall and this is about half of that, so it reads as a mark on the line rather than as a second
   control beside the name. The stored file is 256 pixels square and drawn here at a tenth of its
   area, which is why the topbar asks the account for the small copy rather than the large one.

   Square, with square corners. No circle and no rounded corners anywhere a picture of an account is
   drawn on this site - the same shape the profile page draws its own square in, decided once so that
   this row, that page and a list of comments cannot each answer it differently. */
.identity-picture {
    flex: none;
    width: 24px;
    height: 24px;
    object-fit: cover;
}

/* An empty mark on the picture's top-right corner. Its meaning is spoken by the numbered menu entry;
   this element is decoration and therefore has neither words nor a second accessible label. */
.identity-unread-dot {
    position: absolute;
    top: -2px;
    right: -2px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: var(--identity-unread-dot-colour);
}

/* The picture drawn for an account that has chosen none of its own : this site's own artwork, in the
   variant belonging to the theme the site is actually in.

   ONE CLASS, TWO DECLARATIONS, and the browser fetches only the one that wins. Written against the
   class this site's own toggle puts on the document rather than against a system-preference query,
   because such a query follows the operating system and would disagree with the toggle the moment
   somebody with a light desktop reads this site in dark mode - and it is the toggle that decides
   every other colour on the page, so the picture would be the one thing on screen answering a
   different question.

   A background rather than two image elements with one of them hidden : an image element hidden from
   view is still fetched by every browser this site cares about, so the two-element version costs both
   files on every page load for every visitor who has no picture, while a background declaration the
   other theme overrides is never fetched at all.

   The picture is declared here and the size deliberately is not. This class is what any other place
   drawing a default asks for - the profile page's own square is four times this one - so each place
   sets its own side and no place has to restate which files the default is. */
.avatar-default {
    background-image: url("../img/default_avatar_dark_v001.webp");
    background-size: cover;
    background-position: center;
}

body.light-mode .avatar-default {
    background-image: url("../img/default_avatar_light_v001.webp");
}

.identity-username {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Smaller than the name it follows, so it reads as a mark on the control rather than as a second
   word, and no smaller than that : at ten pixels the glyph is a dot on a phone and stops saying
   that anything opens, which is the only thing it is there for. */
.identity-menu-arrow {
    flex: none;
    font-size: 12px;
}

/* The menu itself, drawn only while the control carries the open state the script writes.

   Hung under the right-hand edge of the control rather than under its left, because on a wide
   screen the control is already against the right-hand edge of the window and a menu growing
   rightwards from there would grow off the screen. `min-width: 100%` keeps it at least as wide as
   the button, so a two-word entry never makes it narrower than the thing it belongs to.

   The layer number is one above the panel layer, and both are written down in the header of the
   screen-width stylesheet with everything else this site stacks. It has to clear the gallery's
   sticky toolbar, which is what sits under this row on the page a visitor is most likely to be on.

   The two colours are the bar's own - the same pair `.tabs` is drawn in and the same pair its
   light-mode override carries - so no new colour enters the site here. They are written out rather
   than inherited because this box is drawn over the page rather than over the bar : left
   transparent it would show the gem pictures behind it straight through the words. */
.identity-menu {
    display: none;
    position: absolute;
    top: 100%;
    right: 0;
    min-width: 100%;
    background-color: #2a2a2a;
    border: 1px solid #444;
    z-index: 1300;
}

#identity-control.identity-menu-open .identity-menu {
    display: block;
}

body.light-mode .identity-menu {
    background-color: #e5e5e5;
    border-color: #ccc;
}

/* One entry per line, each the whole width of the menu, so the strip a finger lands on is the
   line and not the word on it. The name is allowed to be cut short in the button above ; an entry
   here is not, because every destination has to remain readable rather than turn into an ellipsis. */
.identity-menu .identity-menu-entry {
    display: block;
    width: 100%;
    text-align: left;
    white-space: nowrap;
}

/* A small red ring rather than bare trailing text, so the number remains legible as the unread count
   beside the destination. The border follows the text through currentColor, leaving each theme one
   colour decision instead of two copies that can drift. */
.identity-menu-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.65em;
    min-height: 1.65em;
    margin-left: 8px;
    padding: 0 0.35em;
    border: 1px solid currentColor;
    border-radius: 999px;
    color: var(--error-dark);
    font-size: 0.875em;
    font-weight: 700;
    line-height: 1;
}

body.light-mode .identity-menu-count {
    color: var(--error-light);
}

.identity-menu .identity-menu-entry:hover {
    background-color: #3f3f3f;
}

body.light-mode .identity-menu .identity-menu-entry:hover {
    background-color: #d0d0d0;
}

/* The form is the security the sign-out needs and not a line of the layout : it wraps one entry of
   the menu, so it has to take up exactly the room that entry does and add nothing of its own. */
.identity-logout-form {
    display: block;
    margin: 0;
}

/* The second half of signing out : the red row that appears under Logout once a script has revealed
   it, and the button that actually posts the form. Drawn by nothing at all until then, which is why
   a browser running no script signs a visitor out on the first press exactly as it always did.

   NO NEW COLOUR ENTERS THE SITE HERE. The red is the palette's own refusal pair, one value per
   theme, and the text drawn on it is the palette's own too. Measured : #1f1f1f on #ff6b6b reads
   5.94 to 1 and #ffffff on #c62828 reads 5.62 to 1, both past the 4.5 a sentence of ordinary size
   has to reach. This is the FIRST time the refusal red is used as a surface rather than as ink -
   the comment beside the unread dot a few rules up asked for that to be said out loud the day it
   happened, and this is that day. Unlike the dot, this surface carries words, so both readings are
   written down here rather than left to be taken on trust.

   The two values reach the declarations through a pair of names declared in this rule, exactly as
   the gallery's report dialog draws its own primary button. That is not decoration : the palette
   checker measures every palette colour used as ink against every palette colour used as a surface,
   within a theme, and it does that on the names alone. Handing the refusal red straight to
   `background-color` would enrol it as a surface for EVERY text colour this site has, and the near
   black beside it as ink for every surface - seventeen readings about pairings nobody draws, on top
   of the three that rule already reports. A name declared here is not part of the palette, so the
   pairing measured is the one that exists : the two above, by hand.

   The box is the one the entries above are given - the same padding, so the strip a finger lands on
   is the same size and the row is as tall as its neighbours at every width. Bolder than they are,
   because it is the only destructive thing in this menu, and left-aligned like them, because a
   centred word here would read as a different kind of control than the four above it.

   THE ANIMATION NEEDS NO STATE CLASS. It is declared on the element itself, and the element is
   `display: none` until the script takes the `hidden` attribute off ; a browser starts an animation
   from the beginning the moment an element becomes drawn, so removing that attribute IS the trigger
   and nothing has to be timed in the script.

   What moves is the button and not the menu around it : the menu grows by one row in a single step
   while the button fades and slides into the space. Animating the menu's height as well was weighed
   and deliberately not done - it means giving a box that is sized by its contents an explicit height
   to travel between, which is a larger change than this control is worth. */
.identity-logout-confirm {
    --identity-logout-confirm-surface: var(--error-dark);
    --identity-logout-confirm-text: var(--bg-dark);

    display: block;
    width: 100%;
    padding: 14px 24px;
    border: none;
    background-color: var(--identity-logout-confirm-surface);
    color: var(--identity-logout-confirm-text);
    font: inherit;
    font-weight: 600;
    text-align: left;
    white-space: nowrap;
    cursor: pointer;
    animation: identity-logout-confirm-appear 160ms ease-out;
}

/* Written out rather than left to the browser's own meaning of the attribute. `hidden` is worth
   `display: none` in the browser's stylesheet only, so the `display: block` above - an author rule,
   however plain - outranks it, and without this the red row would be drawn at rest on every page a
   signed-in visitor loads. */
.identity-logout-confirm[hidden] {
    display: none;
}

body.light-mode .identity-logout-confirm {
    --identity-logout-confirm-surface: var(--error-light);
    --identity-logout-confirm-text: var(--surface-light);
}

/* Darkened rather than given a second pair of values, so the hover follows whichever red the theme
   put underneath it and there is nothing here to keep in step with the palette. */
.identity-logout-confirm:hover {
    filter: brightness(0.92);
}

@keyframes identity-logout-confirm-appear {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}

/* the drawer's furniture

   The hamburger, the site name, the close cross and the dim layer are hidden here and drawn
   only by the small-screen rules, so nothing about the wide picture can move on their account. */

.nav-toggle,
.site-name,
.nav-close,
.nav-backdrop { display: none; }

/* the colour those two buttons carry, one pair per theme

   Neither of them said anything about its own colour anywhere, and a button that says nothing is
   painted by the browser in its own button face : a pale grey slab with near-black text, whatever
   surface it happens to sit on. Over the dark row and the dark drawer that reads as a light pill
   nobody chose, which is exactly how it was reported.

   Both declarations are written out because a button does not inherit its text colour the way
   ordinary text does - the browser sets one on it, so the colour of the bar around it never
   arrives on its own. The four values are the bar's own, the same pair `.tabs` and `.tab a` are
   drawn in at the top of this file and the same pair their light-mode overrides carry, so no new
   colour enters the site here.

   The border is left exactly as the browser draws it, deliberately. The filter panel's own close
   cross is themed this same way and keeps its browser border ; leaving it alone here is what makes
   every button on a small screen edged alike, instead of making these two into a new thing.

   The one-line alternative - telling the whole document that its colour scheme is dark - is
   refused. It would repaint every control on every page at every width, the wide layout included,
   and that layout is the one thing this work is not allowed to move. A large bill for three
   buttons on a phone.

   These rules carry no width condition and must not gain one : all three of these controls are
   hidden at the wide layout by the block above and by the gallery's own, so a colour on them has
   no box to paint there. That is a stronger guarantee than a width test, and it keeps the colours
   beside the furniture they belong to.

   The two selectors weigh the same - two classes and two element names each, `:not()` counting its
   argument - and they can never both match, so neither one depends on being the later of the pair. */

body:not(.light-mode) button.nav-toggle,
body:not(.light-mode) button.nav-close {
    background-color: #2a2a2a;
    color: #eaeaea;
}

body.light-mode button.nav-toggle,
body.light-mode button.nav-close {
    background-color: #e5e5e5;
    color: #1f1f1f;
}

/* what an open drawer looks like

   These rules live outside any screen-width block because nothing carries the open state at
   rest : a drawer is opened by a tap and not by a window size, so no width can be moved by
   them. The two layer numbers are the ones the screen-width stylesheet's header writes down
   for a panel and for the layer that dims the page behind it ; neither is invented here. */

.nav-backdrop.is-open {
    display: block;
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 1100;
}

/* The row is already a positioned box with no layer of its own, so a fixed dim layer one step
   above it would paint over the open drawer and over the ✕ inside it. The close cross would
   then not be missing but unreachable - a pointer would land on the dim layer instead. */
#nav-drawer.is-open {
    z-index: 1200;
}

#nav-drawer.is-open .nav-close {
    display: block;
}

/* The page behind an open panel does not scroll. Hiding the root's overflow keeps the visitor's
   place by itself : there is no offset to write down and none to put back, so the lock and the
   panel state cannot drift apart. Pinning the body instead would drop the visitor at the top of
   a list of thousands of gems with no way of returning to where they were. */
html.panel-open {
    overflow: hidden;

    /* The strip the scrollbar was occupying, kept while the line above is hiding the scrollbar
       itself. This value reserves that strip for a box whose overflow is hidden as well as for one
       that scrolls, which is exactly the case here.

       NOTHING ABOUT THE LOCK WAS EVER WRONG - IT HAD SIMPLY NEVER BEEN EXERCISED WHERE A SCROLLBAR
       TAKES REAL SPACE. Both panels that existed before the comment panel are drawn on narrow
       screens only, where a scrollbar is an overlay costing no width at all, so hiding it moved
       nothing. The comment panel is the first this site opens at a desktop width, and there the
       document's scrollbar is fifteen to seventeen real pixels : without this line the whole
       gallery steps sideways the moment the panel opens and steps back when it closes.

       Where it is not understood the behaviour is the one this site had yesterday. */
    scrollbar-gutter: stable;

    /* A page whose overflow is hidden still answers a drag at its edge with the elastic bounce,
       and on a phone that bounce is also the gesture that pulls the browser's own toolbars back
       over the screen. Refusing it keeps a drag that started inside an open panel from moving
       anything behind it. */
    overscroll-behavior: none;
}

/* the bar that carries a message from one page to the next, above the row

   It is drawn above this row and never inside it. The row's shape is measured to the pixel at a
   phone width, and a line inserted into it would move every one of those readings ; above it, in
   the flow, the row simply moves down by the height of whatever is being said and nothing about the
   row itself changes. Nothing here carries a width condition and nothing here needs one : the bar is
   a block as wide as the page at every width, and the only element it holds that is not text is
   sized in pixels rather than in shares of anything.

   EVERY SELECTOR NAMES THIS BAR BY ITS ID, and that is load-bearing rather than habit. Each line
   wears the class of its kind, and those two classes are defined in a stylesheet loaded AFTER this
   one - so a rule here naming a single class would lose the tie to a rule there naming a single
   class, and the layout written here would be quietly answered by margins meant for a message
   sitting under a form. That file documents the same defect from the other side : a selector naming
   a class and an element outweighed the refusal colour on every page of this site for years, and
   nothing anywhere reported it. An id outweighs both, and the script that dismisses a message looks
   this element up by that id in any case.

   THE COLOURS OF THE TWO KINDS ARE NOT WRITTEN HERE. Each line takes its colour from the class of
   its kind, so those two have one home ; what is written here is the surface they are read on. That
   pair is the row's own - the same two colours `.tabs` and its light-mode override carry - so no new
   colour enters the site at this bar.

   THE STACKING NUMBER SITS BELOW EVERY LAYER THIS SITE HAS, and the one it has to be below is the
   open drawer's. The drawer is a full-height panel pinned over the page ; a bar painted above it
   would sit over the drawer's own close cross, which is not a bar that looks wrong but a drawer
   nobody can shut - the same defect the dim layer's rule above records. Below the rest for a simpler
   reason : this bar covers nothing at all. It is in the flow and pushes what follows it down, so
   there is no box it ever has to be drawn on top of. A number is written all the same, so that
   "below the drawer" is a fact somebody can read here rather than a consequence of how this element
   happens to be positioned. Every layer this site stacks is listed in the header of the screen-width
   stylesheet, this one included. */
#supertopbar {
    position: relative;
    z-index: 900;
    background-color: #2a2a2a;
    border-bottom: 1px solid #444;

    /* The size of the box a finger has to land on, which is the minimum every control this site
       draws at a phone width is held to. Written once here and read by both the cross and the room
       the sentence leaves for it, because those two have to agree : a sentence inset by less than
       the cross is wide is a sentence drawn underneath a control that is still perfectly tappable
       and completely illegible. */
    --supertopbar-tap-size: 44px;
}

body.light-mode #supertopbar {
    background-color: #e5e5e5;
    border-bottom-color: #ccc;
}

/* One line per sentence, the sentence centred against the whole bar and the cross at the trailing
   edge.

   The cross is taken out of the flow and the line is inset by its size on BOTH sides, which is what
   centres the sentence against the bar rather than against whatever is left over beside the cross,
   and what keeps the longest sentence from running underneath it. Left in the flow, the cross would
   take its width off one end and the centring would be wrong by exactly that much.

   min-height and not height : a sentence long enough to wrap has to be free to make this line taller
   rather than spill out of it, which is the same choice the row below makes for the same reason.

   The margin is flattened deliberately. Both message classes carry twenty pixels of bottom margin
   for the pages they were written for, where that space separates a refusal from the field above it.
   A bar is not that : the space would be drawn between the sentence and the row below, on a surface
   whose whole height is the sentence. */
#supertopbar .supertopbar-line {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--supertopbar-tap-size);
    padding-left: var(--supertopbar-tap-size);
    padding-right: var(--supertopbar-tap-size);
    margin: 0;
    text-align: center;

    /* The fade is a change of opacity and never a movement, which is why the block answering a
       visitor who has asked for less movement deliberately does not name this bar. How long it takes
       is decided here and the script reads it back off the drawn element rather than holding a copy
       of it, so this file goes on being the one place that decides. */
    transition: opacity 400ms ease;
}

#supertopbar .supertopbar-line.supertopbar-fading {
    opacity: 0;
}

/* The cross, at the full tap size, and not one pixel of that size coming from padding.

   A control that flows as text takes no height at all from padding, so the same box written that way
   comes out about twenty pixels tall while looking perfectly correct in this file - which is how the
   account control's own link was found, and its rule a few dozen lines above says the same thing.
   Explicit width and height is the one spelling that cannot go wrong.

   Everything else here is what a button arrives carrying and has to be told not to : a background of
   the browser's own choosing, a border, a font, a colour. Said nowhere, this cross would be a pale
   slab on the dark bar, which is exactly how the drawer's two buttons were once reported. The colour
   is the sentence's own, inherited, so the cross belongs to the message it dismisses and no colour is
   written twice. The glyph is larger than the sentence beside it because it is the whole of what this
   control says - at the surrounding size it reads as punctuation rather than as something to press. */
#supertopbar .supertopbar-close {
    position: absolute;
    top: 0;
    right: 0;
    width: var(--supertopbar-tap-size);
    height: var(--supertopbar-tap-size);
    padding: 0;
    background-color: transparent;
    border: none;
    color: inherit;
    font: inherit;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}

/* ------------ */
