/* The saved-lists selector.
 *
 * Lives inside #dice-roller-header, sharing that row with the save and sound
 * toggles. #expand-all is absolutely positioned off to the left, so everything
 * after those toggles is free space and this fills it.
 *
 * Sized to belong to the roller rather than sit above it: same height as the
 * controls beside it, no border of its own, no panel. Colours are themes.css
 * custom properties, so it follows the colour schemes and day/night mode. */

/* ── the header row as a grid ────────────────────────────────────────
   Column for column with the dice line below: the list box sits over
   .d-line (192px), the sound toggle over .line-result (58px), and the list
   buttons over .roll (54px). space-between then reproduces the same two
   17px gaps the line and footer rows already use, without hard-coding them. */
#dice-roller-header {
    justify-content: space-between;
}

#dice-list-bar {
    position: relative;      /* anchor for the transient status overlay */
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    min-width: 180px;
    max-width: 192px;
    width: 192px;
}

/* Constrained to the .line-result column width. The wrapper's own sizing is a
   content-box 32px plus a 24px left pad (a text-indent trick that positions the
   checkbox and the speaker glyph), which measures 86px and would overhang the
   result box below it. */
#dice-roller-header .checkbox-wrapper {
    box-sizing: border-box;
    flex: 0 0 58px;
    width: 58px;
    height: 30px;
    padding-top: 4px;
    padding-left: 22px;
    margin-left: 0;
}

/* Empty now that "+" lives inside the name box and the delete button is gone,
   but the column is kept: it is the .roll column of the grid, and dropping it
   would let space-between spread the remaining two across the row and pull the
   name box out of line with .d-line below. */
#dice-list-actions {
    flex: 0 0 54px;
}

/* The list box. Deliberately the same width, border and corner radius as
   .d-line directly below it, so the two read as one column rather than as a
   toolbar sitting on top of a list. */
.dl-name,
.dl-signin {
    box-sizing: border-box;
    width: 100%;
    height: 30px;
    border: var(--theme-primary, #cc0000) solid 2px;
    border-radius: 15px;
    background-color: var(--bg-button, #efefde);
}

/* Padding clears a control at each end, so the centred name stays honestly
   centred against the .d-line below, and matches the width of the hit areas so
   a long name cannot run underneath one. Both affixes are out of flow, so this
   costs the box no width at all. */
.dl-name {
    min-width: 0;
    padding: 0 32px;
    font-size: 0.82em;
    color: var(--text-primary, #000);
    text-align: center;
}

/* ── the controls inside the box ─────────────────────────────────────
   The row is a three-column grid tracking the dice line (192/58/54) and has
   no spare width, so neither control gets a column. Both are absolutely
   positioned inside the name box's own padding: "+" in the left, the caret in
   the right, so the box carries its controls at either end and the .roll
   column below is left to the roll button alone.

   Three gestures, one box: "+" makes a list, typing renames it, the caret
   switches between them. Anchored to #dice-list-bar, which is already
   position: relative for the status overlay.

   Each one claims its whole end of the box rather than just the glyph. A 16px
   character is a small thing to hit, especially on a phone, and the corners
   either side of it were dead space that looked clickable and was not. Now the
   button is the full height of the box and 32px wide, so anywhere in that end
   works; the glyph is centred inside it and is the only part you can see. */
.dl-affix {
    position: absolute;
    top: 0;
    bottom: 0;
    width: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    background: none;
    line-height: 1;
    color: var(--text-secondary, #666);
    cursor: pointer;
    /* Inside a 15px-radius pill, so the hit area follows the corner it sits in
       rather than poking a square through it. */
    border-radius: 15px;
}

.dl-affix:hover {
    color: var(--theme-primary, #cc0000);
}

/* Weighted to read as a peer of the caret rather than a text character that
   happens to sit there. */
.dl-add {
    left: 0;
    font-size: 1em;
    font-weight: 700;
}

.dl-caret {
    right: 0;
    font-size: 0.7em;
}

.dl-caret-on {
    color: var(--theme-primary, #cc0000);
}

.dl-menu {
    position: absolute;
    left: 0;
    top: 34px;              /* the 30px box plus the row's own 4px breathing space */
    z-index: 20;            /* over the dice lines it covers */
    width: 100%;
    box-sizing: border-box;
    margin: 0;
    padding: 4px 0;
    list-style: none;
    border: var(--theme-primary, #cc0000) solid 2px;
    border-radius: 12px;
    background-color: var(--bg-button, #efefde);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.18);
}

/* Specific enough to beat `#dice-roller li` in diceroller.css, which lays the
   dice lines out as inline-flex rows at width 100%. The menu sits inside
   #dice-roller, so without this its options inherit that and run off to the
   right in a single row instead of stacking. */
#dice-roller .dl-menu .dl-opt {
    display: block;
    box-sizing: border-box;
    width: 100%;
    padding: 5px 12px;
    font-size: 0.8em;
    color: var(--text-primary, #000);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    cursor: pointer;
}

/* Both modifiers have to carry the same weight as the rule above or they lose
   the cascade to it on `color`. */

/* Highlight follows the pointer as well as the arrow keys, so mouse and
   keyboard never show two different "current" rows. */
#dice-roller .dl-menu .dl-opt-active {
    background-color: var(--bg-secondary, #ffffff);
}

/* The list you are on. Marked by weight rather than a tick, because a tick
   needs a gutter and the centred text has no room for one. */
#dice-roller .dl-menu .dl-opt-on {
    font-weight: 700;
    color: var(--theme-primary, #cc0000);
}

/* Signed out this is the same box, carrying the one thing worth saying in it.
   Same box signed in or out, so signing in fills it rather than replacing it. */
.dl-signin {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.78em;
    font-weight: 600;
    color: var(--text-primary, #000);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
}

.dl-signin b {
    font-weight: 700;
    color: var(--theme-primary, #cc0000);
    text-decoration: underline;
    text-underline-offset: 2px;
    margin-right: 4px;
}

.dl-signin:hover {
    background-color: var(--bg-secondary, #ffffff);
}

/* `hidden` must win over the display rules above. */
#dice-list-bar [hidden],
#dice-list-actions [hidden] {
    display: none !important;
}

/* Errors only now. Laid over the name rather than given a column of its own,
   because the row has no spare width and covering the name for a moment is
   self-explanatory. :empty keeps it out of the way the rest of the time.

   Inset by the width of the two controls instead of spanning the whole box.
   At width: 100% it covered them, so pressing "+" made the "+" itself vanish
   under the message it had just triggered — which looked like the button had
   been swallowed rather than like something being reported. */
.dl-status {
    position: absolute;
    left: 32px;
    right: 32px;
    /* Inside the box's 2px border, not over it, so the red outline stays
       unbroken across the row while the message sits within it. */
    top: 2px;
    bottom: 2px;
    /* Block rather than flex, and centred by line-height. As a flex container
       the message was one anonymous item, which text-overflow cannot ellipsize
       — so anything longer than the gap between the two controls was clipped
       at both ends instead of trailing off at one. The full text is on the
       title attribute, because this space cannot hold a sentence. */
    display: block;
    line-height: 26px;
    text-align: center;
    box-sizing: border-box;
    padding: 0 4px;
    font-size: 0.74em;
    color: var(--text-secondary, #666);
    background-color: var(--bg-button, #efefde);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.dl-status:empty {
    display: none;
}

/* A confirmation that fades out on its own. Drops where the menu drops, so it
   reads as belonging to this control, but sized to its own text rather than
   the 192px column — the column is a layout constraint on the row, not on
   something floating over the lines for two seconds.

   pointer-events: none because it covers the first dice line while it is up,
   and a message has no business swallowing a click meant for the roller. */
.dl-toast {
    position: absolute;
    top: 34px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 25;            /* over the menu's 20, though the two never coexist */
    padding: 5px 12px;
    font-size: 0.76em;
    white-space: nowrap;
    color: var(--text-primary, #000);
    background-color: var(--bg-button, #efefde);
    border: var(--theme-primary, #cc0000) solid 2px;
    border-radius: 12px;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.18);
    pointer-events: none;
    opacity: 0;
    /* visibility rather than the hidden attribute, and driven purely by CSS.
       Fading in on the next animation frame meant nothing happened at all
       when the tab was not visible, because requestAnimationFrame does not
       run in a background tab — the message would be created and expire
       without ever being shown. This has no such dependency.

       visibility flips only once the fade has finished, so the text is not
       pulled out from under the transition. */
    visibility: hidden;
    transition: opacity 200ms ease, visibility 0s linear 200ms;
}

.dl-toast.dl-toast-on {
    opacity: 1;
    visibility: visible;
    transition: opacity 200ms ease, visibility 0s;
}

/* Someone who has asked not to see motion gets the message without the fade,
   rather than a message that appears to do nothing for 200ms. */
@media (prefers-reduced-motion: reduce) {
    .dl-toast { transition: none; }
}

.dl-status.dl-error {
    color: var(--theme-primary, #cc0000);
    font-weight: 700;
}

/* On a phone the row is tight, so the transient status drops out rather than
   squeezing the name box. */
/* The row is narrower on a phone but the columns still track the dice line,
   so nothing needs repositioning. The status overlay stays: it is the only
   feedback that a save happened. */
@media screen and (max-width: 640px) {
    /* Only the text shrinks. The hit areas keep their full 32px ends, because
       a finger is less accurate than a mouse, not more — pulling them in here
       would make the controls hardest to hit exactly where they are hardest to
       hit already. */
    .dl-name { font-size: 0.78em; padding: 0 32px; }
}
