﻿/*
 * Modern UI -- admin theme for YOURLS, light and dark.
 *
 * Loaded after core's style.css, so plain selectors already win the cascade.
 * !important is used only where core sets an inline-ish rule we cannot outrank.
 *
 * Deliberately does NOT touch `display` on #new_url_form, .edit-row, .sharebox
 * or #delete-confirm-dialog: those are toggled by YOURLS' own JS and forcing a
 * value here would break adding, editing and sharing links.
 */

/*
 * Inter, self-hosted. No CDN or Google Fonts request: this admin runs on an
 * internal network and should not depend on reaching the public internet to
 * render its own text.
 *
 * latin-ext is not optional here -- ı, ğ, ş and İ live in that range, so Turkish
 * would silently fall back to a different face mid-word without it.
 *
 * The files sit in user/plugins/shared-assets/fonts/ because the visitor-facing
 * pages in secure-redirector use them too -- see the README there.
 *
 * Gotham Pro was tried in this slot and reverted: the licensed webfont we were
 * given had been re-generated through FontForge without a gasp table, so Windows
 * grid-fit it inconsistently and every size below 15px rendered badly.
 */
@font-face {
    font-family: 'InterVariable';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../../shared-assets/fonts/inter-latin-ext-wght-normal.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
                   U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
                   U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: 'InterVariable';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../../shared-assets/fonts/inter-latin-wght-normal.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                   U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC,
                   U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/*
 * Colour comes entirely from these tokens, so light and dark are the same
 * stylesheet with a different palette -- nothing below this block hardcodes a
 * colour.
 *
 * Three states, in this order:
 *   1. :root                      -> light, the default
 *   2. prefers-color-scheme: dark -> dark, unless the user explicitly chose light
 *   3. [data-theme="dark"]        -> dark, chosen explicitly, beats the OS
 *
 * The :not([data-theme="light"]) guard in (2) is what lets someone on a dark OS
 * force light; without it the media query would keep winning.
 */
/*
 * Built on the corporate palette:
 *   #002554  Pantone 655 C -- the corporate navy, for text and primary actions
 *   #81cdff  the sky blue the guide names as the auxiliary colour for digital
 *
 * Greys are tints of the navy rather than neutral grey, so surfaces sit in the
 * same colour family instead of looking washed out next to it.
 *
 * Light uses navy as the accent; sky blue is far too pale on white to carry a
 * link (about 1.9:1). Dark inverts that -- sky blue on navy reads at 10.3:1, and
 * a sky-blue button takes navy text, which is both brand colours at once.
 */
:root {
    --bg:            #f0f2f5;   /* navy at 6% */
    --surface:       #ffffff;
    --surface-2:     #e6e9ee;   /* navy at 10% */
    --surface-3:     #d8dee7;   /* hover fill */
    --border:        #dde2ea;
    --border-strong: #bcc6d5;

    /* Content text is pure black in light / white in dark by request -- maximum
       readability everywhere the two tokens below are used (table cells, form
       labels, panel pages, body copy). The old navy/grey values are kept in the
       comments in case a softer hierarchy is ever wanted back. --text-faint stays
       muted on purpose: it paints placeholders and tertiary hints, which should
       not look like real text. */
    --text:          #000;      /* was #1a3a63 (navy 90%) */
    --text-dim:      #000;      /* was #5a6b85 (grey) */
    --text-faint:    #8593a8;
    --nav-text:      #000;      /* sidebar menu labels: pure black in light,
                                   white in dark -- the dim/faint tokens read
                                   too light in the side rail */

    --accent:        #002554;   /* corporate navy, exact */
    --accent-hover:  #0d4a8c;
    --accent-quiet:  rgba(0, 37, 84, .09);
    --on-accent:     #ffffff;

    --stripe:        rgba(0, 37, 84, .022);
    --code-text:     #334b6b;

    --warn:          #b04840;   /* warning: a lighter shade of the error red, 4.9:1 */
    --danger:        #9c2f28;   /* 6.6:1 -- the previous #c8443c sat at 4.3:1, below AA */
    --success:       #2e8b57;

    --radius:        6px;
    --radius-lg:     10px;

    /* Shared height for the top bar and the sidebar's logo band, so their bottom
       borders land on exactly the same line. Not theme-specific. */
    --topbar-h:      64px;
}

/* Dark values live in two places because CSS has no way to share a declaration
   block between selectors -- keep the two lists in step. */
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --bg:            #06182f;
        --surface:       #0d2444;
        --surface-2:     #143054;
        --surface-3:     #1b3c65;
        --border:        #1e3f6b;
        --border-strong: #2d5183;

        --text:          #fff;      /* was #b0c8e4 */
        --text-dim:      #fff;      /* was #8299b8 */
        --text-faint:    #64789a;
        --nav-text:      #fff;

        --accent:        #81cdff;
        --accent-hover:  #a5dcff;
        --accent-quiet:  rgba(129, 205, 255, .15);
        --on-accent:     #002554;

        --stripe:        rgba(129, 205, 255, .03);
        --code-text:     #cfe0f2;

        --warn:          #ffb0a9;   /* warning: a lighter shade of the error red */
        --danger:        #ff8a80;
        --success:       #6fd695;
    }
}

:root[data-theme="dark"] {
    --bg:            #06182f;
    --surface:       #0d2444;
    --surface-2:     #143054;
    --surface-3:     #1b3c65;
    --border:        #1e3f6b;
    --border-strong: #2d5183;

    --text:          #fff;      /* was #b0c8e4 */
    --text-dim:      #fff;      /* was #8299b8 */
    --text-faint:    #64789a;
    --nav-text:      #fff;

    --accent:        #81cdff;
    --accent-hover:  #a5dcff;
    --accent-quiet:  rgba(129, 205, 255, .15);
    --on-accent:     #002554;

    --stripe:        rgba(129, 205, 255, .03);
    --code-text:     #cfe0f2;

    --warn:          #ffb0a9;   /* warning: a lighter shade of the error red */
    --danger:        #ff8a80;
    --success:       #6fd695;
}

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

html {
    background: var(--bg);
    /* Always reserve the scrollbar gutter. #wrap is centred, so a page long
       enough to need a scrollbar loses ~15px of viewport and every centred
       element jumps sideways -- very visible when moving between a short page
       (Tools) and a long one (the link list). Reserving the space keeps the
       layout still whether the bar is there or not. */
    scrollbar-gutter: stable;
}

body {
    background: var(--bg);
    color: var(--text);
    /* Core centres the whole document (`body { text-align:center }`) as a legacy
       centring trick; #wrap resets it, but anything outside #wrap inherits it. */
    text-align: left;
    font-family: 'InterVariable', -apple-system, BlinkMacSystemFont, "Segoe UI",
                 Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 14px;
    line-height: 1.55;
    letter-spacing: -.005em;
    /*
     * No -webkit-font-smoothing: antialiased here on purpose. It is a macOS fix;
     * on Windows it switches ClearType's subpixel antialiasing off in favour of
     * greyscale, and subpixel rendering is exactly what small text relies on.
     */
    /* Inter's tabular numerals keep click counts and dates from jittering
       between rows, and its contextual alternates fix the default 'ti'/'fi'. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'cv05' 1, 'ss03' 1;
}

/*
 * Setting the family on <body> alone is not enough here.
 *
 * Core carries `div, p, td { font-family: Verdana, Arial }` (style.css:25) and
 * tablesorter.css repeats it for the table. Those are rules applied *directly*
 * to the elements, and a direct declaration always beats an inherited value no
 * matter how specific the ancestor's rule was -- inheritance only fills in where
 * nothing else matched. So every div, paragraph and cell on the page stayed
 * Verdana while <body> quietly used Inter.
 *
 * Listing the same elements at equal specificity, later in the cascade, is what
 * actually hands them the font.
 */
body, div, p, td, th, li, span, a, label, legend, caption,
h1, h2, h3, h4, h5, h6,
input, select, textarea, button,
table, table.tblSorter, .jquery-notify-bar,
td.actions .button, td.actions a {
    font-family: 'InterVariable', -apple-system, BlinkMacSystemFont, "Segoe UI",
                 Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* Core's `Input.text` (0,1,1) sets Verdana and outranks the bare `input` (0,0,1)
   in the rule above, so every URL field (add-URL, short link, search) fell back
   to Verdana. Re-assert Inter at matching specificity. */
input.text {
    font-family: 'InterVariable', -apple-system, BlinkMacSystemFont, "Segoe UI",
                 Roboto, "Helvetica Neue", Arial, sans-serif;
}

#wrap {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 24px 64px;
    background: none;
    border: 0;
}

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); text-decoration: underline; }

p { color: var(--text); }
small, .text-secondary { color: var(--text-dim); }
hr { border: 0; border-top: 1px solid var(--border); margin: 24px 0; }

::selection { background: var(--accent-quiet); }

/* -------------------------------------------------------------- header --- */
/*
 * Core does `h1 { float:right }` and `h1 a { float:right; text-align:right }`,
 * which is why the title lands in the top-right corner. Unfloat both, or the
 * heading escapes the flow and the nav wraps around it.
 */

/* The heading sits inside <header role="banner">, not directly under #wrap --
   a `#wrap > h1` selector matches nothing, which is why the logo stayed floated
   into the top-right corner over the nav. */
header[role=banner] h1,
header[role=banner] h1 a {
    float: none;
    text-align: left;
    max-width: none;
}

header[role=banner] {
    padding: 18px 0 14px;
    border-bottom: 1px solid var(--border);
}

/* On admin pages the logo lives inside the toolbar (see .modern-ui-brand), so the
   standalone header above it would just be a duplicate. Hide it only where the
   menu exists -- the login screen has no #admin_menu, so it keeps its header logo.
   :has() is supported by the Chromium this admin runs in; browsers without it fall
   back to showing both, which is harmless. */
body:has(#admin_menu) header[role=banner] { display: none; }

header[role=banner] h1 {
    margin: 0;
    line-height: 0;
}

/* The anchor holds "YOURLS: Your Own URL Shortener" as loose text nodes plus a
   <br> plus the logo. Collapsing the font size drops the tagline (and the line
   break) while leaving the <img> untouched -- the logo already carries the name. */
header[role=banner] h1 a { font-size: 0; display: inline-block; }

#yourls-logo {
    height: 26px;
    width: auto;
    max-width: none;
    display: block;
    opacity: .92;
}

h2 {
    font-size: 20px;
    font-weight: 600;
    letter-spacing: -.01em;
    color: var(--text);
    margin: 28px 0 6px;
}

h3 {
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    margin: 24px 0 8px;
}

/* ---------------------------------------------------------------- menu --- */

/*
 * Selectors are written as `ul#admin_menu` to match core's own specificity --
 * a bare `#admin_menu` loses to it, which is how the 100px of dead space in the
 * header survived the first attempt.
 *
 * The markup is also not what it looks like: YOURLS never closes its <li> tags
 * and nests the plugin-page <ul> *inside* the "Manage Plugins" <li>. So the
 * sublinks are a child list, not siblings, and they need their own flex row or
 * they stack vertically and blow the header apart.
 */
ul#admin_menu {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 4px;
    min-height: 0;
    list-style: none;
    margin: 0;
    padding: 8px 0;
    font-size: 14px;
    border-bottom: 1px solid var(--border);
    background: none;
}

ul#admin_menu li {
    float: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 4px;
    margin: 0;
    padding: 0;
    color: inherit;
    background: none;
    border: 0;
    list-style: none;
}

/* Core swaps in a square bullet on hover; on a flex row it just nudges things. */
ul#admin_menu li:hover { list-style-type: none; color: inherit; }

/* The nested plugin-page list. */
ul#admin_menu ul {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 4px;
    list-style: none;
    margin: 0;
    padding: 0 0 0 4px;
    border-left: 1px solid var(--border);
}

ul#admin_menu a {
    display: inline-block;
    padding: 6px 11px;
    border-radius: var(--radius);
    color: var(--nav-text);
    font-weight: 500;
    white-space: nowrap;
    transition: background .12s ease, color .12s ease;
}

ul#admin_menu a:hover {
    background: var(--surface-2);
    color: var(--nav-text);
    text-decoration: none;
}

/* Plugin pages are the sub-level, but still black/white for readability (was
   --text-faint, which the user found too light in the side rail); the smaller
   font size already sets them apart from the main sections. */
ul#admin_menu .admin_menu_sublevel a {
    font-size: 13px;
    color: var(--nav-text);
    padding: 5px 9px;
}
ul#admin_menu .admin_menu_sublevel a:hover { color: var(--nav-text); }

/* YOURLS emits the help <li> whether or not the 'help_link' filter returned
   anything, so emptying it leaves a stray flex gap behind. */
ul#admin_menu li#admin_menu_help_link:empty { display: none; }

/* Theme switch, appended to the menu by the 'admin_menu' action. */
ul#admin_menu li.modern-ui-theme-item { margin-left: 8px; }

.modern-ui-theme-btn {
    height: 28px;
    padding: 0 10px;
    /* The label swaps between "Koyu tema" and "Açık tema", which do not render at
       the same width. This button sits at the end of a right-aligned row, so any
       change in its size nudges the whole menu sideways on every toggle. Fixing
       the width keeps the row still. */
    min-width: 92px;
    text-align: center;
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text-dim);
    font-family: inherit;
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
    cursor: pointer;
    white-space: nowrap;
}
.modern-ui-theme-btn:hover { background: var(--surface-3); color: var(--text); }

/* "Hello <user> [role] (Logout)" sits apart, at the end of the row. */
ul#admin_menu li#admin_menu_logout_link {
    margin-left: auto;
    color: var(--text-faint);
    font-size: 13px;
    padding: 0 2px;
    gap: 4px;
}
ul#admin_menu li#admin_menu_logout_link strong { color: var(--text-dim); font-weight: 600; }
ul#admin_menu li#admin_menu_logout_link a { padding: 4px 8px; font-size: 13px; }

/* Corporate logo, injected as the last <li> but pulled to the front of the flex
   row. Single-colour wordmark painted with the same mask-recolour trick as the tn
   placeholder: the SVG gives only the silhouette, background-color gives the colour,
   one explicit value per theme -- navy on light, plain white on dark. The <a> is
   otherwise empty; its accessible name is the aria-label. */
ul#admin_menu li.modern-ui-brand {
    order: -1;              /* leftmost, ahead of every section link */
    margin-right: 14px;
    padding: 0;
}
ul#admin_menu li.modern-ui-brand a {
    display: block;
    width: 116px;
    height: 32px;
    padding: 0;
    /* Navy is the mark's own colour. The accent token is deliberately not used:
       in dark it is sky blue, and the logo should read plain white there. No
       :hover recolour -- a logo is not a control, and shifting it on hover reads
       as a glitch. Per-theme values follow the theme's own three-state pattern. */
    background-color: #002554;
    -webkit-mask: url('logo.svg') no-repeat left center / contain;
            mask: url('logo.svg') no-repeat left center / contain;
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) ul#admin_menu li.modern-ui-brand a { background-color: #ffffff; }
}
:root[data-theme="dark"]  ul#admin_menu li.modern-ui-brand a { background-color: #ffffff; }
:root[data-theme="light"] ul#admin_menu li.modern-ui-brand a { background-color: #002554; }

/* ============================================================== sidebar === */
/*
 * The toolbar is re-laid as a fixed left rail. Everything here is guarded on
 * body:has(#admin_menu) so it only touches admin pages -- the login screen has
 * no menu, keeps its centred header logo, and stays full-width. :has() is
 * supported by the Chromium this admin runs in.
 *
 * DOM is untouched: the <nav> is lifted out of flow with position:fixed and the
 * body gets a left gutter the exact width of the rail, so #wrap keeps centring
 * in the space that remains instead of sliding under the panel.
 */
/* Kill any horizontal page scrollbar on admin pages. Applied to BOTH the root and
   body: hidden on html alone left body with overflow-x:visible and a scrollWidth
   past the viewport, which still produced the bar. `clip` (not hidden) trims the
   stray overflow without turning either into a scroll container or disturbing
   vertical scrolling. The link table keeps its own inner scroll (.mui-table-scroll),
   so no column is lost -- only the ~40px of empty overhang past the sidebar is cut. */
html:has(#admin_menu),
html:has(#admin_menu) body { overflow-x: clip; }

body:has(#admin_menu) { padding-left: 232px; }
/* Base breathing room on every admin page; the extra clearance for the fixed
   add-URL bar applies only where that bar exists (#new_url), so pages without it
   -- the stats page -- do not get a big empty gap under the sidebar top. */
body:has(#admin_menu) #wrap { padding-top: 24px; }
body:has(#new_url) #wrap { padding-top: calc(var(--topbar-h) + 22px); }

body:has(#admin_menu) nav[role=navigation] {
    position: fixed;
    top: 0; left: 0; bottom: 0;
    width: 232px;
    background: var(--surface);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    z-index: 100;
}

/* Column, at least full height, so the bottom group can sink with margin:auto. */
body:has(#admin_menu) nav[role=navigation] ul#admin_menu {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 2px;
    min-height: 100%;
    box-sizing: border-box;
    /* No top padding: the brand li owns the full --topbar-h band from the top so
       its divider aligns with the bar. */
    padding: 0 12px 20px;
    border-bottom: 0;
}

/* Full-width rows; anchors fill the rail so the hover fill is a full bar. */
body:has(#admin_menu) ul#admin_menu a {
    display: block;
    width: 100%;
    box-sizing: border-box;
}

/* Top-level items open a column so the nested plugin list stacks underneath
   rather than trailing off to the side. */
body:has(#admin_menu) ul#admin_menu li.admin_menu_toplevel {
    flex-direction: column;
    align-items: stretch;
}
body:has(#admin_menu) ul#admin_menu ul {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    padding: 2px 0 2px 10px;
    margin-top: 2px;
    border-left: 1px solid var(--border);
}

/* Brand band: logo on the left, collapse toggle pinned to the RIGHT end (the empty
   space beside the wordmark). space-between opens a wide gap between the two so the
   button never crowds the logo, and the toggle keeps a small right margin so it is
   not jammed against the rail edge (that read as "odd" in an earlier pass). */
body:has(#admin_menu) ul#admin_menu li.modern-ui-brand {
    order: -1;
    /* Occupy exactly the top bar's height from the top of the rail; the bottom
       border falls on --topbar-h -- the same line the bar's bottom border sits on. */
    height: var(--topbar-h);
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin: 0 2px 12px;
    padding: 0;
    border-bottom: 1px solid var(--border);
}
body:has(#admin_menu) ul#admin_menu li.modern-ui-brand a {
    flex: 0 0 auto;
    width: 116px;
    height: 34px;
    /* logo.svg's ink fills its 216x60 viewBox to all four edges, so `contain`
       (from the base rule) fits it flush to this box's right edge and subpixel-
       clips the bottom-right of the last glyph. Mask always clips to the element
       box (padding can't help), so shrink the mask a touch below the box and keep
       it left-aligned -- ~8px of right/bottom breathing room, no visible clip. */
    -webkit-mask-size: 108px auto;
            mask-size: 108px auto;
    -webkit-mask-position: left center;
            mask-position: left center;
}
body:has(#admin_menu) ul#admin_menu li.modern-ui-brand .modern-ui-rail-toggle {
    flex: 0 0 auto;
    margin-right: 2px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 30px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--nav-text);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
}
body:has(#admin_menu) ul#admin_menu li.modern-ui-brand .modern-ui-rail-toggle:hover {
    background: var(--surface-2);
}

/* Smooth the width/gutter change when the rail collapses or expands. */
body:has(#admin_menu) { transition: padding-left .2s ease; }
body:has(#admin_menu) nav[role=navigation] { transition: width .2s ease; }

/* --- Collapsed rail: a narrow strip showing only the toggle ---------------- */
html.mui-rail-collapsed body:has(#admin_menu) { padding-left: 60px; }
html.mui-rail-collapsed body:has(#admin_menu) nav[role=navigation] { width: 60px; }
/* Hide every menu row (sections, plugin sublists, theme, language) and the tn
   stray <img> -- only the brand band (now just its toggle) stays. */
html.mui-rail-collapsed body:has(#admin_menu) ul#admin_menu > li:not(.modern-ui-brand),
html.mui-rail-collapsed body:has(#admin_menu) ul#admin_menu > img { display: none; }
/* The logout row has its own 3-ID rule (li#admin_menu_logout_link) that out-
   specifies the :not() hide above, so it needs an explicit collapsed override. */
html.mui-rail-collapsed body:has(#admin_menu) ul#admin_menu li#admin_menu_logout_link { display: none; }
/* In the strip, drop the wordmark and centre the toggle; the band no longer needs
   its full height or bottom divider. */
html.mui-rail-collapsed body:has(#admin_menu) ul#admin_menu li.modern-ui-brand {
    justify-content: center;
    height: auto;
    margin: 8px 0 12px;
    border-bottom: 0;
}
html.mui-rail-collapsed body:has(#admin_menu) ul#admin_menu li.modern-ui-brand a { display: none; }
html.mui-rail-collapsed body:has(#admin_menu) ul#admin_menu li.modern-ui-brand .modern-ui-rail-toggle { margin-right: 0; }

/* The other things pinned to the right of the rail must track its width too, or a
   gap opens between the 60px strip and their old 232px left edge. The add-URL top
   bar, the notify banner (its left is !important, so this override must be too),
   and the footer (its own rule lives further down) all follow. */
html.mui-rail-collapsed body:has(#admin_menu) #new_url { left: 60px; }
html.mui-rail-collapsed body:has(#admin_menu) #jquery-notify-bar,
html.mui-rail-collapsed body:has(#admin_menu) .jquery-notify-bar,
html.mui-rail-collapsed body:has(#admin_menu) #__notifyBar { left: 60px !important; }

/* Bottom group: logout, then the theme toggle, sunk to the foot of the rail.
   margin-top:auto on the first of them eats the leftover vertical space. */
body:has(#admin_menu) ul#admin_menu li#admin_menu_logout_link {
    order: 1;
    margin: auto 0 0;
    padding-top: 12px;
    border-top: 1px solid var(--border);
    /* Plain text flow, not a flex row: in the rail the username, role badge and
       "(Logout)" must read as one wrapping sentence instead of each fragment
       breaking onto its own line. */
    display: block;
    line-height: 1.7;
}
/* The generic "every menu anchor is a full-width block" rule would drop "Logout"
   onto its own line inside that sentence -- keep this one inline. */
body:has(#admin_menu) ul#admin_menu li#admin_menu_logout_link a {
    display: inline;
    width: auto;
    padding: 0;
}
body:has(#admin_menu) ul#admin_menu li.modern-ui-theme-item {
    order: 2;
    margin: 8px 0 0;
}
body:has(#admin_menu) ul#admin_menu li.modern-ui-theme-item .modern-ui-theme-btn {
    width: 100%;
}
/* Language switch, directly under the theme switch. */
body:has(#admin_menu) ul#admin_menu li.modern-ui-lang-item {
    order: 3;
    margin: 8px 0 0;
}
body:has(#admin_menu) ul#admin_menu li.modern-ui-lang-item .modern-ui-theme-btn {
    width: 100%;
}

/* The tn plugin hooks admin_menu to echo a raw <img> URL-preview straight into
   the menu on the stats page. With no thumbnail key and localhost URLs it always
   falls back to the placeholder logo, so in the rail it is just a second stray
   logo -- hide it. (It is a direct child <img>, not wrapped in an <li>.) */
body:has(#admin_menu) ul#admin_menu > img { display: none; }

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

/* `input.button` is 0,1,1 in core and sets Verdana 10px bold -- a bare `.button`
   here loses to it, which left every button rendering in the old face. */
.button,
input.button,
input.primary,
input[type=submit],
input[type=button],
button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    height: 34px;
    padding: 0 14px;
    background: var(--surface-2);
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    font-size: 13px;
    font-weight: 500;
    font-family: inherit;
    line-height: 1;
    cursor: pointer;
    transition: background .12s ease, border-color .12s ease;
}

.button:hover,
input.button:hover,
input[type=submit]:hover,
button:hover {
    background: var(--surface-3);
    border-color: var(--border-strong);
    color: var(--text);
    text-decoration: none;
}

.button:active, input.button:active, input[type=submit]:active, button:active {
    transform: translateY(1px);
}

.button:focus-visible,
input.button:focus-visible,
input[type=submit]:focus-visible,
button:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* The one solid call to action per screen, like the dashboard's "+ Add". */
.button.primary,
input.button.primary,
input.primary,
#add-button {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
    font-weight: 600;
}
.button.primary:hover,
input.button.primary:hover,
input.primary:hover,
#add-button:hover {
    background: var(--accent-hover);
    border-color: var(--accent-hover);
}

/* -------------------------------------------------------------- inputs --- */

input[type=text],
input[type=url],
input[type=password],
input[type=search],
input[type=number],
input.text,
textarea,
select {
    height: 34px;
    padding: 0 10px;
    /* Border-box so a width:100% field (e.g. #copylink) does not overflow its panel
       once padding and border are added. */
    box-sizing: border-box;
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    font-family: inherit;
    font-size: 13px;
    /* Without this the browser paints the open <select>'s highlighted option and
       checkmark -- plus checkboxes and radios -- in the OS accent colour, which
       reads gold on this machine. Pin it to the corporate navy so the popup
       matches every other element. */
    accent-color: var(--accent);
    transition: border-color .12s ease, box-shadow .12s ease;
}

textarea { height: auto; padding: 8px 10px; line-height: 1.5; }

input::placeholder, textarea::placeholder { color: var(--text-faint); }

input[type=text]:focus,
input[type=url]:focus,
input[type=password]:focus,
input[type=search]:focus,
input.text:focus,
textarea:focus,
select:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-quiet);
    outline: none;
}

/* When a <select> is open, the browser highlights its current value with the OS
   grey selection colour, which looks foreign against the dark navy popup. Recolour
   the selected row to a palette blue -- accent-quiet is a navy wash in dark and a
   faint navy tint in light. Chromium honours this; browsers that fully own the
   popup ignore it without harm. */
option:checked {
    background: var(--accent-quiet);
    color: var(--text);
}

label { color: var(--text-dim); font-size: 13px; }

/* --------------------------------------------------------- add new URL --- */

#new_url {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 18px 20px;
    margin: 24px 0;
    text-align: left; /* core centres this box */
}

#new_url h2 { margin-top: 0; }

#new_url_form p { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

#add-url { flex: 1 1 320px; min-width: 220px; }
#add-keyword { flex: 0 1 180px; }

#charcount { color: var(--text-faint); font-size: 12px; }

/* ------------------------------------------------- add-URL top bar --- */
/*
 * On admin pages the "shorten a URL" form is lifted into a bar fixed across the
 * top of the content area, level with the logo at the top of the rail -- the
 * horizontal counterpart to the sidebar. #new_url is pulled out of the flow with
 * position:fixed and #wrap gets a matching top padding (above) so the table clears
 * it. Guarded on :has(#admin_menu) so the login page (no menu) keeps the card.
 */
body:has(#admin_menu) #new_url {
    position: fixed;
    top: 0;
    left: 232px;              /* start where the rail ends (60px when collapsed) */
    right: 0;                 /* to the right edge; respects the scrollbar gutter,
                                 unlike 100vw which overshoots by the scrollbar width
                                 and produces its own horizontal scrollbar */
    z-index: 90;
    transition: left .2s ease;  /* follow the rail as it collapses/expands */
    /* Same height as the rail's logo band (both --topbar-h), so the bar's bottom
       border and the sidebar's logo divider land on exactly the same line and the
       logo and the form centre at the same height. */
    height: var(--topbar-h);
    box-sizing: border-box;
    display: flex;
    align-items: center;
    margin: 0;
    padding: 0;
    background: var(--surface);
    border: 0;
    border-bottom: 1px solid var(--border);
    border-radius: 0;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .05);
    /* Never let the add-URL form's content push past the bar and give the page a
       horizontal scrollbar; clip (not hidden) so it doesn't force overflow-y. The
       form is made to shrink below (min-width:0 + smaller mins) so nothing real is
       actually cut. */
    overflow-x: clip;
}
/* Inner wrapper centred to the same 1180px column as #wrap so the form lines up
   with the table below it on wide screens. */
body:has(#admin_menu) #new_url > div {
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 14px;
    background: none;
}
/* The inputs sit in a <div> inside the form (not a <p>); lay them out as one row. */
body:has(#admin_menu) #new_url_form > div {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 8px;
    min-width: 0;              /* let the flex children shrink below content on a narrow bar */
}
body:has(#admin_menu) #new_url_form label { white-space: nowrap; }
body:has(#admin_menu) #add-url { flex: 1 1 auto; min-width: 70px; }
body:has(#admin_menu) #add-keyword { flex: 0 1 150px; min-width: 60px; }
body:has(#admin_menu) #add-button { flex: 0 0 auto; }

/* The result banner drops below the bar as an overlay rather than growing it and
   pushing the fixed height out from under #wrap's top padding. */
body:has(#admin_menu) #new_url #feedback {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    margin: 0;
    padding: 10px 24px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    box-shadow: 0 6px 10px rgba(0, 0, 0, .06);
}

/* --------------------------------------------------------------- table --- */

#main_table {
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    margin: 8px 0 20px;
}

/* Horizontal-scroll box the head JS wraps around #main_table: when the many-column
   table cannot fit a small viewport, it scrolls here instead of widening the page
   (no <body> horizontal scrollbar). Full-width, so on a roomy screen it does
   nothing.
   The frame (border + rounded corners + surface) moves from the table to the box:
   when the table is wider than the box, its own right rounded corner sits past the
   box edge and reads as square. On the box, both corners stay rounded and clip the
   scrolling table. margin moves here too so the scroll area hugs it. */
.mui-table-scroll {
    overflow-x: auto;
    margin: 8px 0 20px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
}
.mui-table-scroll #main_table {
    margin: 0;
    border: 0;
    border-radius: 0;
}

/* Actions column, 2026-08-25: on a 1280-1366px laptop the ten-column table
   made "İşlemler" unreachable -- table-layout:auto computed a near-ZERO
   intrinsic width for this column. Core's row-action links are float:left,
   and floated children are excluded from the shrink-to-fit pass some
   browsers use to size an auto-layout table column, so instead of
   overflowing (which .mui-table-scroll could handle) the whole column got
   crushed to a sliver. overflow:hidden -- the classic clearfix trick --
   establishes a block formatting context that correctly encloses the floats
   for width purposes, so the column sizes to its real content; min-width is
   kept as a floor regardless.
   Tried display:flex first: it also fixes the width, but setting `display`
   itself on a <td> blockifies it out of the table-cell layout model, so
   vertical-align:middle stopped applying and the cell no longer stretched
   to the row's height -- it rendered ~11px short and top-anchored, looking
   like it was "floating" inside a taller row. overflow:hidden changes no
   layout-model property, so the cell still behaves like every other column.
   (position:sticky to pin this column to the scroll box's right edge was
   also tried and reverted -- Chromium does not reliably stick a table
   cell's right edge the way it does a sticky top header row.) */
#main_table th#main_table_head_actions,
#main_table td.actions {
    overflow: hidden;
    /* 4 buttons * (22px + 5px margin-right) + 20px cell padding = 128px in
       theory; table auto-layout doesn't always honour min-width exactly (it
       rendered ~124px in practice, 4px short), so ask for more headroom than
       the arithmetic strictly needs -- otherwise the buttons wrap to a
       second line and the row grows tall again. */
    min-width: 160px;
}

#main_table thead th {
    background: var(--surface-2);
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 600;
    text-align: left;
    padding: 11px 10px;
    border: 0;
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}

#main_table thead th a { color: inherit; }

/* Sort indicator. Core paints it as an SVG background on the header (bg/asc/
   desc.svg), but the solid `background` above wipes that out -- and the artwork is
   dark, so it would be invisible on the dark theme anyway. Redraw it as a CSS
   caret from theme tokens: an accent triangle on the active column (up = asc,
   down = desc) and a faint one on hover for the other sortable columns.
   tablesorter tags the active header .tablesorter-headerAsc/Desc; non-sortable
   ones carry .sorter-false. */
#main_table thead th.tablesorter-header:not(.sorter-false) {
    cursor: pointer;
    position: relative;
    padding-right: 24px;
}
#main_table thead th.tablesorter-header::after {
    content: "";
    position: absolute;
    right: 12px;
    top: 50%;
    margin-top: -2px;
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    opacity: 0;
    transition: opacity .12s ease;
}
/* Faint hint on hover of a sortable column that is not the active one. */
#main_table thead th.tablesorter-header:not(.sorter-false):not(.tablesorter-headerAsc):not(.tablesorter-headerDesc):hover::after {
    border-top: 5px solid var(--text-faint);
    opacity: 1;
}
/* Active column: solid accent caret. */
#main_table thead th.tablesorter-headerAsc::after {
    border-bottom: 5px solid var(--accent);
    opacity: 1;
}
#main_table thead th.tablesorter-headerDesc::after {
    border-top: 5px solid var(--accent);
    opacity: 1;
}

/* Preview and Actions are not sortable: tablesorte.js flags them sorter:false, so
   they carry .sorter-false and are already excluded from the caret rules above.
   No extra CSS needed now that the column indices are resolved correctly. */

#main_table tbody td {
    padding: 12px 10px;
    border: 0;
    border-bottom: 1px solid var(--border);
    color: var(--text);
    vertical-align: middle;
    background: none;
}

#main_table tbody tr:last-child td { border-bottom: 0; }

#main_table tbody tr:hover td { background: var(--surface-2); }

/* Core alternates row colours with a light grey that glows on a dark page. */
#main_table tbody tr.odd td,
#main_table tbody tr.even td { background: none; }
#main_table tbody tr.odd:hover td,
#main_table tbody tr.even:hover td { background: var(--surface-2); }

#main_table .timestamp { color: var(--text-dim); font-size: 12px; white-space: nowrap; }
#main_table .url a { word-break: break-all; }
#main_table .keyword a { font-weight: 600; }

/* Row action links: quiet until you are actually on the row. */
#main_table .actions a {
    color: var(--text-faint);
    padding: 2px 5px;
    border-radius: 4px;
}
#main_table tr:hover .actions a { color: var(--text-dim); }
#main_table .actions a:hover { color: var(--accent); background: var(--accent-quiet); text-decoration: none; }

/* Cleaner action icons. Core paints each button with a fixed-colour background SVG
   (chart_bar/share/pencil/delete.svg); swap in a Feather-style line icon masked on
   a ::before so it takes the link's own colour (quiet → text-dim on row hover →
   accent on the button itself) and stays crisp in both themes. The button text is
   already hidden by core's text-indent, so the ::before is the only glyph. */
#main_table td.actions .button {
    position: relative;
    background-image: none;
    /* Core's `.button { width:22px }` is a content-box size, but this cell's
       own padding (2px 5px) and border (1px) rules (below) also apply here
       and land ON TOP of that -- the button actually renders at ~32px, not
       22px. box-sizing:border-box makes `width` the true rendered size, so
       the min-width math on the cell (below) can rely on it. */
    box-sizing: border-box;
}
#main_table td.actions .button::before {
    content: "";
    position: absolute;
    inset: 0;
    background-color: currentColor;
    -webkit-mask: no-repeat center / 15px;
            mask: no-repeat center / 15px;
}
#main_table td.actions .button_stats::before  { -webkit-mask-image: url('icons/stats.svg');  mask-image: url('icons/stats.svg'); }
#main_table td.actions .button_share::before  { -webkit-mask-image: url('icons/share.svg');  mask-image: url('icons/share.svg'); }
#main_table td.actions .button_edit::before   { -webkit-mask-image: url('icons/edit.svg');   mask-image: url('icons/edit.svg'); }
#main_table td.actions .button_delete::before { -webkit-mask-image: url('icons/delete.svg'); mask-image: url('icons/delete.svg'); }

#nourl_found td { color: var(--text-faint); text-align: center; padding: 28px 14px; }

/* Inline edit row -- display is left to YOURLS' JS.
   Core uses `tr.edit-row td { background:#e3f3ff !important }` (0,1,2), so this
   has to match that specificity as well as carry !important, or the row stays
   pale blue. */
#main_table tr.edit-row td,
tr.edit-row td { background: var(--surface-2) !important; }

/* -------------------------------------------------- filters / counters --- */

/*
 * Not a card. The link table directly above is already a large filled surface,
 * and stacking a second one right under it made the two read as one muddy slab
 * with a seam. A rule and some breathing room separate them far more cleanly.
 */
/* The filter form is rendered inside the main table's <tfoot> as one
   th colspan="6". With the tn "Preview" column the table is 7 columns wide, so
   that th no longer spans the row -- the uncovered 7th column showed as a stray
   pale cell -- and the themed grey tfoot background turned the whole footer into a
   broken two-tone slab. Strip the tfoot's own background and borders so the footer
   is one flat surface with the table body; #filter_form's top border is the only
   separator the form needs. */
#main_table tfoot,
#main_table tfoot tr,
#main_table tfoot th {
    background: none;
    border: 0;
}
#main_table tfoot th { padding: 0; }

#filter_form {
    background: none;
    border: 0;
    border-top: 1px solid var(--border);
    border-radius: 0;
    padding: 18px 4px 4px;
    margin: 24px 0 0;
    /* Core (tablesorter.css) sets `float:left; max-width:69%` here, which pins the
       whole thing to the left and leaves nothing to centre within -- undo both.
       Then flex-centre the form as one block; its content stays left-aligned
       inside, so it reads as a tidy panel in the middle of the row. The JS colspan
       fix makes the footer cell span the whole table, so "middle" is the real one. */
    float: none;
    max-width: none;
    display: flex;
    justify-content: center;
}
#filter_form > form { max-width: 680px; }
#filter_options { line-height: 2.4; }

/* Core floats these to the right; keep them in flow so they sit under the fields
   inside the centred block. */
#filter_buttons { float: none; display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 14px; }

#overall_tracking {
    color: var(--text-dim);
    font-size: 13px;
    margin: 12px 0;
}
#overall_tracking strong, .increment { color: var(--text); font-weight: 600; }

/* ---------------------------------------------------------- pagination --- */

#pagination { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 16px 0; }

#pagination .nav_link {
    display: inline-block;
    padding: 5px 10px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    color: var(--text-dim);
    font-size: 13px;
}
#pagination .nav_link:hover { background: var(--surface-2); color: var(--text); text-decoration: none; }
#pagination .nav_current {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--on-accent);
}
#nav_total, .nav_total { color: var(--text-faint); font-size: 13px; }

/* ------------------------------------------------- notices / feedback ---- */

.feedback, .notice, .error, .warning, .success {
    border: 1px solid var(--border);
    border-left-width: 3px;
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--text);
    padding: 11px 14px;
    margin: 14px 0;
}
.error, .error-message { border-left-color: var(--danger); }
.warning { border-left-color: var(--warn); }
.success { border-left-color: var(--success); }
.notice, .feedback { border-left-color: var(--accent); }

/*
 * These class names are not only banners. YOURLS also hangs them on small inline
 * markers -- <span class="warning"> is the ★ it puts beside a URL that does not
 * look like a normal link (functions-html.php:646), and upgrade.php uses
 * <span class="success"> the same way. Given the block treatment above, each of
 * those turned into a padded, bordered box sitting in the middle of a sentence.
 *
 * Inline elements get the colour and nothing else.
 */
span.error, span.warning, span.success, span.notice, span.feedback,
small.error, small.warning, small.success,
em.error, em.warning, em.success {
    display: inline;
    background: none;
    border: 0;
    border-radius: 0;
    padding: 0;
    margin: 0;
}
span.warning, small.warning, em.warning { color: var(--warn); }
span.error,   small.error,   em.error   { color: var(--danger); }
span.success, small.success, em.success { color: var(--success); }

/* jQuery notifybar, used for AJAX results. It is prepended to <body> and pinned to
   the very top, which on this layout means straight over the sidebar and the fixed
   add-URL bar. On admin pages push it into the content area, just below the bar, so
   it never covers either. */
#jquery-notify-bar, .jquery-notify-bar {
    background: var(--surface-2) !important;
    color: var(--text) !important;
    border-bottom: 1px solid var(--border) !important;
}
body:has(#admin_menu) #jquery-notify-bar,
body:has(#admin_menu) .jquery-notify-bar,
body:has(#admin_menu) #__notifyBar {
    position: fixed !important;
    top: var(--topbar-h) !important;   /* just below the fixed add-URL bar */
    left: 232px !important;            /* right of the sidebar */
    right: 0 !important;
    width: auto !important;
    z-index: 95 !important;            /* above the bar (90), below the sidebar (100) */
    text-align: center;
}

/* ------------------------------------------------------ share / dialog --- */

#sharebox, .sharebox, #delete-confirm-dialog {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    color: var(--text);
    padding: 16px 18px;
}

#copybox input, #copylink { width: 100%; }

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

#footer {
    margin-top: 36px;
    padding-top: 18px;
    border-top: 1px solid var(--border);
    color: var(--text-faint);
    font-size: 12px;
    background: none;
    text-align: left;
}

/* Core wraps the credit line in a white, blue-bordered, heavily rounded <p>
   (`#footer p`) and gives the link a white background plus a favicon sprite --
   both of which show up as bright blocks on a dark page. */
#footer p {
    background: none;
    border: 0;
    border-radius: 0;
    padding: 0;
    margin: 0;
    max-width: none;
}
#footer a, #footer p a {
    background: none;
    padding-left: 0;
    color: var(--text-dim);
}
#footer a:hover, #footer p a:hover { color: var(--accent); }

/* On admin pages the footer is pinned to the bottom of the main content area so
   it is always visible without scrolling. It stays a normal footer (bottom of the
   content column, to the right of the sidebar -- not in the rail); it just no
   longer trails behind the page. The stats page is the reason: its fixed full-
   height sidebar and short tab content leave the in-flow footer sitting below the
   fold on a tall screen, so reaching a one-line credit needed a scroll. Left edge
   clears the rail (and follows it when the rail collapses). #wrap reserves matching
   bottom padding so no content hides behind it. Scoped to admin pages -- login
   keeps its centred-with-the-card footer (body.login below). */
body:has(#admin_menu) #footer {
    position: fixed;
    left: 232px;
    right: 0;
    bottom: 0;
    margin: 0;
    padding: 9px 24px;
    background: var(--bg);
    border-top: 1px solid var(--border);
    z-index: 50;
    transition: left .2s ease;  /* follow the rail as it collapses/expands */
}
body:has(#admin_menu) #wrap { padding-bottom: 52px; }
/* Fold the 24px side padding INTO the width: #wrap is content-box by default, so
   its padding sat on top of the width and pushed the column ~48px past the space
   left of the sidebar. That overhang was the real source of the page overflow and
   the clipped (square) right edge on the table's scroll box. border-box keeps
   #wrap within its parent, so the scroll box's rounded right corner stays visible. */
body:has(#admin_menu) #wrap { box-sizing: border-box; }
/* Backstop: even if some future child overflows, clip it here rather than scroll
   the page. clip constrains #wrap without forcing overflow-y like hidden would. */
body:has(#admin_menu) #wrap { overflow-x: clip; }
html.mui-rail-collapsed body:has(#admin_menu) #footer { left: 60px; }

/* --------------------------------------------------------- login page --- */

/* Vertically centre the whole login group (logo + card + footer) in the
   viewport, the way secure-redirector's password page centres its card --
   an 8vh top push instead of real centring left it sitting too high on
   anything taller than a short window. #footer is a sibling of #wrap, not a
   child (core closes </div><!-- wrap --> before printing it), so both need
   to be flex children of body for `justify-content:center` to bracket them
   as one centred block instead of just #wrap. */
body.login {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
body.login #wrap { max-width: 400px; padding-top: 0; }

body.login #login {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    padding: 26px 24px;
}
body.login #login p { margin: 0 0 14px; }
body.login #login input[type=text],
body.login #login input[type=password] { width: 100%; }
body.login #login input[type=submit] { width: 100%; }

/* -------------------------------------------------------------- tables --- */
/* Plugin pages and the stats page use plain tables; keep them consistent. */

table:not(#main_table) th {
    color: var(--text-dim);
    font-weight: 600;
    text-align: left;
    padding: 9px 12px;
    border-bottom: 1px solid var(--border);
}
table:not(#main_table) td {
    padding: 9px 12px;
    border-bottom: 1px solid var(--border);
    color: var(--text);
}

code, pre, tt {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 1px 5px;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 12.5px;
    color: var(--code-text);
}
pre { padding: 12px 14px; overflow-x: auto; }

/* ------------------------------------ remaining light surfaces (core) --- */
/*
 * Everything below repeats a selector from core's stylesheets that paints a
 * white or pale-blue background. They are all in <head> ahead of this file, so
 * matching their specificity is enough -- no !important needed.
 *
 * Found by sweeping style.css / share.css / infos.css / tablesorter.css /
 * cal.css for background declarations, rather than chasing them one screenshot
 * at a time.
 */

/* Row action buttons (Edit / Delete / Stats) -- 0,2,1 in core, so a bare
   `.button` rule never reached them. */
td.actions .button {
    background-color: var(--surface-2);
    color: var(--text);
    border-color: var(--border-strong);
}
td.actions .button:hover { background-color: var(--surface-3); }

/* Share boxes: "Short link", "Quick Share" and the QR panel are all div.share
   (share.css). Core floats them, pins each to height:140px and pads only left and
   right, so headings jam against the top edge and the columns never line up. Lay
   them out as a flex row instead -- equal height, even gaps, padding on all sides
   -- and drop the fixed pixel widths for proportional columns. */
#shareboxes {
    display: flex;
    flex-wrap: wrap;
    /* Natural heights, not stretch: the short-link panel has less content than the
       quick-share one, and stretching it left an empty gap under its links. */
    align-items: flex-start;
    gap: 16px;
    margin-top: 20px;
    overflow: visible;   /* core set overflow:hidden only to clear the floats */
}

div.share {
    float: none;
    height: auto;
    margin: 0;
    padding: 16px 18px;
    box-sizing: border-box;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    color: var(--text);
}

/* Proportional columns replacing core's fixed 250/500px; the QR panel is only as
   wide as it needs to be. flex-wrap lets them stack cleanly when the rail narrows
   the page. */
/* Closer proportions -- the old 1:2 left "Short link" cramped next to a very wide
   "Quick Share". The QR panel is a fixed, comfortable width so it reads as an
   intentional card rather than a tiny orphan when it wraps to its own row. */
#copybox  { width: auto; flex: 1 1 280px; }
#sharebox { width: auto; flex: 1.4 1 340px; }
#qrcode {
    width: auto;
    flex: 0 0 200px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

/* One heading size across the three panels reads as a set, not three sizes. */
div.share h2, div.share h3 {
    color: var(--text);
    font-size: 15px;
    font-weight: 600;
    margin: 0 0 12px;
}

/* Core fixes the tweet box at 450px and floats it -- overflow the flex column. */
#tweet_body { float: none; width: 100%; box-sizing: border-box; }

/* The char count sat on its own line above the textarea, pushing it lower than the
   short-link field in the other panel. Tuck it into the heading row's corner so the
   textarea starts right under the heading, level with that field. */
#sharebox { position: relative; }
#sharebox #charcount { position: absolute; top: 18px; right: 18px; margin: 0; }

/* Extra share buttons (modern-ui's share_links hook). Core's #share_links a gives
   them the 18px left slot for an icon; fill it, matching the built-in Twitter/
   Facebook. WhatsApp keeps its brand green, e-mail a neutral envelope. */
#share_wa,
#share_email {
    background-repeat: no-repeat;
    background-position: left center;
    background-size: 15px 15px;
}
#share_wa    { background-image: url('icons/whatsapp.svg'); }
#share_email { background-image: url('icons/mail.svg'); }

/* Centre the QR image in whatever height the tallest panel sets. The PNG has
   black modules on a transparent ground, so on the navy panel it reads as low
   contrast and barely scans -- a white tile behind it restores black-on-white,
   and the padding doubles as the quiet zone scanners need. */
#qrcode img {
    margin: auto;
    background: #fff;
    padding: 8px;
    border-radius: 6px;
}

/* Short-link panel internals. Core paints a light-theme copy.svg into the field at
   an odd off-edge position, and clips the long link to a fixed 183px -- clean both
   up and tidy the label/link lines. Click-to-copy still works (share.js), the
   pointer cursor hints it. */
#copybox #copylink {
    background-image: none;
    cursor: pointer;
    color: var(--text);
    /* Same size as the quick-share textarea (both fall back to the 34px / 13px
       input defaults) so the two panels' fields read as a matched pair. */
}
#copybox p:first-of-type { margin: 0 0 14px; }
#copybox p { margin: 0 0 10px; }
#copybox p:last-child { margin-bottom: 0; }
#copybox small { color: var(--text-dim); font-size: 12px; line-height: 1.9; }
#copybox #origlink,
#copybox #statlink { color: var(--accent); }
#copybox #origlink {
    width: auto;
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    vertical-align: bottom;
}

/* Delete confirmation dialog. */
#delete-confirm-dialog {
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
}
#delete-confirm-dialog > div[name="dialog_title"] {
    background-color: var(--surface-2);
    color: var(--text);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
#delete-confirm-dialog div.confirm-message { background-color: var(--surface); color: var(--text); }
#delete-confirm-dialog div.button-group { background-color: var(--surface-2); }

/* Stats page tabs: flat underline tabs, not the old folder-tab look. Both the
   main tabs (#headers) and the sub-tabs (#stats_lines) get the same treatment --
   no borders or rounded corners, a coloured active label on an accent underline
   that overlaps the container's bottom rule. */
#tabs ul#headers,
ul#stats_lines {
    display: flex;
    flex-wrap: wrap;
    gap: 2px;
    float: none;
    margin: 0;
    padding: 0;
    border-bottom: 1px solid var(--border);
}
#tabs ul#headers li,
ul#stats_lines li { margin: 0; display: inline-block; }

#tabs ul#headers li a,
#stats_lines li a {
    display: inline-block;
    background: none;
    border: 0;
    border-radius: 0;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;              /* underline sits on the container rule */
    color: var(--text-dim);
    font-weight: 500;
}
#tabs ul#headers li a { padding: 9px 14px; }
#stats_lines li a    { padding: 7px 12px; font-size: 13px; }
/* The main tab labels are wrapped in <h2>; tame them to tab size. */
#tabs ul#headers li a h2 {
    display: inline;
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: inherit;
    letter-spacing: 0;
}

#tabs ul#headers li a:hover,
#stats_lines li a:hover {
    background: none;
    color: var(--text);
    text-decoration: none;
    border-bottom-color: var(--border-strong);
}
#tabs ul#headers li a.selected,
#tabs ul#headers li a.selected:hover,
#stats_lines li a.selected,
#stats_lines li a.selected:hover {
    background: none;
    color: var(--accent);
    /* Core's .selected sets a full 1px border (the box on the sub-tabs); reset it
       and keep only the accent underline. */
    border: 0;
    border-bottom: 2px solid var(--accent);
}

/* Stats page header (yourls-infos.php): a loose h2 + two h3 rows carrying big
   default heading margins. Tighten them into one compact, aligned block. */
h2#informations { margin: 0 0 16px; font-size: 22px; }
#informations + h3,
h3#longurl {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 8px;
    font-size: 14px;
    font-weight: 500;
    color: var(--text);
}
#informations + h3 .label,
h3#longurl .label {
    color: var(--text-dim);
    font-weight: 600;
    min-width: 120px;
    flex: 0 0 auto;
}
#informations + h3 img,
h3#longurl img { width: 16px; height: 16px; flex: 0 0 auto; }
#tabs { margin-top: 24px; }

/* The pale blue slab inside the "Enter the URL" panel. */
#new_url div { background: none; padding: 0; }

/* jQuery tablesorter is used by plugin tables as well as the main one.
   Its header rule also draws white 1px borders between cells. */
table.tblSorter { background-color: var(--surface); }
table.tblSorter tbody td { background-color: transparent; color: var(--text); }
table.tblSorter thead tr th,
table.tblSorter tfoot tr th,
table.tblSorter th.header {
    background-color: var(--surface-2);
    color: var(--text-dim);
    border: 1px solid var(--border);
}

/* No row-fill on hover: only the time-range link is clickable (it gets its own
   colour on hover), so filling the whole row just read as an unwanted glow. Core
   forces `#C7E7FF !important` here (infos.css), so beating it needs !important. */
#historical_clicks li:hover { background: transparent !important; }
#historical_clicks .historical_link a:hover { color: var(--accent-hover); text-decoration: underline; }

/* infos.js stripes #historical_clicks with an inline light-blue (#E3F3FF) that
   glares on the dark theme. Override it (an inline style needs !important) with the
   theme's subtle stripe. jQuery :odd targets the even nth-child rows. */
#historical_clicks li:nth-child(even) { background: var(--stripe) !important; }
#historical_clicks li { border-radius: 4px; padding: 4px 8px; }

/* -------- Click-detail table (ip-click-detail plugin) --------
   A modern list, not a grid: one card with a rounded border, a quiet sticky
   header, and only horizontal rules between rows -- no per-cell borders. */
#click-detail-title { margin-top: 28px; }
#click-detail-wrap {
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--surface);
}
#click-detail {
    width: 100%;
    margin: 0;
    border: 0;
    border-collapse: collapse;
    font-size: 13px;
    background: none;
}
/* Quiet, uppercase header that stays put while the (up to 1000) rows scroll. */
#click-detail thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surface-2);
    color: var(--text-faint);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    text-align: left;
    padding: 10px 14px;
    border: 0;
    border-bottom: 1px solid var(--border);
}
#click-detail tbody td {
    padding: 11px 14px;
    border: 0;
    border-bottom: 1px solid var(--border);
    color: var(--text);
    vertical-align: top;
}
#click-detail tbody tr:last-child td { border-bottom: 0; }
/* No zebra: it made half the rows look pre-highlighted and fought the hover, so it
   was never clear which row the pointer was on. Clean rows + one clear hover. */
#click-detail tbody td { transition: background .1s ease; }
#click-detail tbody tr:hover td { background: var(--surface-2); }
/* Timestamp and ID: tabular figures, one line. */
#click-detail td:first-child { color: var(--text-dim); white-space: nowrap; font-variant-numeric: tabular-nums; }
#click-detail td:nth-child(2) { color: var(--text-faint); font-variant-numeric: tabular-nums; }
/* User agent is secondary detail; the referrer inside it dimmer still. */
#click-detail td.ua { font-size: 12px; line-height: 1.5; color: var(--text-dim); word-break: break-word; }
#click-detail td.ua .ref { color: var(--text-faint); }
/* "this is your ip" as a small pill rather than loose italic text. */
#click-detail tr.click-detail-me em {
    display: inline-block;
    font-style: normal;
    font-size: 11px;
    font-weight: 600;
    color: var(--accent);
    background: var(--accent-quiet);
    padding: 1px 7px;
    border-radius: 999px;
    margin-left: 4px;
    white-space: nowrap;
}

/* The line chart is transparent now; a touch of room around it. */
.stats_line { margin: 8px 0; }

/* Self-drawn SVG donut that replaces the Google Charts pies (modern_ui_render_donut).
   A clean ring plus a colour-dot legend with percentages. */
.mui-donut {
    display: flex;
    align-items: center;
    gap: 22px;
    flex-wrap: wrap;
    padding: 8px 0;
}
.mui-donut-svg { width: 150px; height: 150px; flex: 0 0 auto; }
.mui-donut-svg circle { transition: stroke-width .12s ease; }
.mui-donut-svg circle:hover { stroke-width: 25; }   /* subtle lift on hover */
.mui-donut-legend {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 7px;
    font-size: 13px;
    min-width: 130px;
    flex: 1;
}
.mui-donut-legend li { display: flex; align-items: center; gap: 9px; }
.mui-donut-legend .dot { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; }
.mui-donut-legend .lbl { color: var(--text); flex: 1; word-break: break-word; }
.mui-donut-legend .val { color: var(--text-dim); font-variant-numeric: tabular-nums; }

/* Google Charts HTML tooltips (isHtml:true on every chart) so the hover popup
   matches the dark theme instead of the default white box. The inner markup carries
   Google's own inline styles, so the text/font overrides need !important. */
.google-visualization-tooltip {
    /* pointer-events:none stops the tooltip -- which pops up under the cursor on
       the big donut slices -- from stealing the hover and flickering on/off. */
    pointer-events: none !important;
    background: var(--surface) !important;
    border: 1px solid var(--border-strong) !important;
    border-radius: var(--radius) !important;
    box-shadow: 0 6px 16px rgba(0, 0, 0, .4) !important;
    padding: 3px 8px !important;
    font-family: 'InterVariable', -apple-system, BlinkMacSystemFont, "Segoe UI",
                 Roboto, sans-serif !important;
    font-size: 12px !important;
}
.google-visualization-tooltip * {
    color: var(--text) !important;
    font-family: inherit !important;
    font-size: 12px !important;
    background: transparent !important;
}
/* Tighten Google's roomy default list spacing. */
.google-visualization-tooltip ul { margin: 0 !important; padding: 0 !important; list-style: none !important; }
.google-visualization-tooltip li { margin: 0 !important; padding: 1px 0 !important; }
/* The label half of each "Label: value" row reads as secondary. */
.google-visualization-tooltip .google-visualization-tooltip-item span:first-child {
    color: var(--text-dim) !important;
    font-weight: 600 !important;
}

/* Pagination when it is rendered outside #pagination. */
.navigation .nav_link a,
.navigation .nav_current {
    background: var(--surface-2);
    color: var(--text-dim);
    border-color: var(--border-strong);
}

/* Date picker (cal.css). */
.datepicker tbody td { background: var(--surface); border-color: var(--border); color: var(--text); }

/* ------------------------------------------ third-party plugin pages --- */
/*
 * Some plugins print their own <style> block inside the page body. That lands
 * after this file in the document, so ordering cannot win -- these overrides
 * are scoped under #wrap purely to outrank them on specificity.
 */

/* secure-redirector paints every row white/grey via `tr:nth-child(even|odd)`
   (0,1,1), which turns its whole table into a light slab on a dark page. */
#wrap tr:nth-child(even),
#wrap tr:nth-child(odd) { background-color: transparent; }

#wrap tbody tr:nth-child(even) { background-color: var(--stripe); }
/* No blanket row-hover: this `#wrap tbody tr` was for secure-redirector's table but
   also lit up the stats page's single-row layout table, so hovering the chart made
   the whole panel glow. Tables that want hover (#main_table, #click-detail) style
   it themselves. */

/* Its "password protected" highlight is a pale blue fill. */
#wrap .password-protected { background-color: var(--accent-quiet) !important; }

/* The Turnstile checkbox group is nudged with a hardcoded `margin-left:-60px`,
   tuned to the metrics of the original font. Any other face and it slides on top
   of the "Password" label next to it -- the flex row already spaces them. */
#wrap .cloudflare-turnstile-container { margin-left: 0; gap: 6px; }
#wrap .header-container { flex-wrap: wrap; gap: 4px 8px; }

/* Its two action dropdowns are sized as `width:70%` of a narrow right-hand
   column, with `box-sizing:border-box` on the select -- so the padding this
   theme adds comes straight out of the text area and clips "Select an action".
   Give the wrapper the full column and floor the select at a readable width. */
#wrap .default-redirection-select,
#wrap .bulk-redirection-select { width: 100%; }

#wrap .default-redirection-select select,
#wrap .bulk-redirection-select select {
    min-width: 190px;
    padding-right: 8px;
}

/* Search boxes sitting inside those table headers. */
#wrap #txt_search_short,
#wrap #txt_search_original {
    background: var(--surface-2);
    color: var(--text);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
}
#wrap #btn_search_short,
#wrap #btn_search_original { background: none; border: 0; height: auto; }

/* --------------------------------------------------------- responsive --- */

@media (max-width: 1400px) {
    /* Ten columns doesn't fit a 1280-1366px laptop even after the actions-
       column fix above -- no column gets dropped, everything just runs
       leaner: the preview thumbnail (by far the widest column, ~180px)
       shrinks to a small icon instead of a card, and every cell's padding
       tightens up. Together that reclaims roughly the same ~200px the
       overflow measured at 1280px, with all ten columns still on screen.
       Above 1400px there's room and the normal (tn.css) sizing applies. */
    #main_table td.preview img:not(.tn-placeholder) {
        max-width: 48px;
        border-radius: 3px;
    }
    #main_table thead th { padding: 9px 6px; }
    #main_table tbody td { padding: 8px 6px; }
    #main_table td.actions,
    #main_table th#main_table_head_actions { min-width: 130px; }
    #main_table td.actions .button { width: 20px; height: 20px; margin-right: 3px; }
}

@media (max-width: 720px) {
    #wrap { padding: 0 14px 48px; }
    #admin_menu { gap: 2px; }
    #admin_menu_logout_link { margin-left: 0 !important; width: 100%; order: -1; }
    #main_table { display: block; overflow-x: auto; }
    #new_url_form p { flex-direction: column; align-items: stretch; }
    /* Drop the fixed top bar back to an in-flow card on narrow screens. */
    body:has(#admin_menu) #new_url { position: static; left: auto; right: auto; box-shadow: none; }
    body:has(#admin_menu) #new_url_form > div { flex-wrap: wrap; }
    body:has(#admin_menu) #new_url #feedback { position: static; }
}

/* "All countries" sub-heading injected into the #details_countries list, plus a
   little breathing room for its rows. */
#details_countries .mui-details-title {
    list-style: none;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--text-faint);
    margin: 6px 0 8px;
    padding: 0;
}
#details_countries li { padding: 3px 0; color: var(--text); }
#details_countries li img { vertical-align: -2px; margin-right: 6px; }

/* Themed hover tooltip for the SVG donut segments (JS-driven). */
.mui-tip {
    position: fixed;
    z-index: 1000;
    pointer-events: none;
    display: none;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    box-shadow: 0 6px 16px rgba(0, 0, 0, .4);
    padding: 4px 9px;
    font-size: 12px;
    color: var(--text);
    white-space: nowrap;
}
.mui-tip .k { color: var(--text-dim); font-weight: 600; }

/* --- Self-drawn world map (replaces the Google GeoChart on the stats page) ------
   Land is a muted panel-adjacent fill; countries with hits are painted with a
   color-mix ramp whose endpoints are theme vars, so the intensity scale stays
   theme-aware. --t (0..1) per <path> is set server-side from the hit count. */
:root {
    --mui-map-land:   #d3dae5;
    --mui-map-stroke: rgba(0, 37, 84, .14);
    --mui-map-lo:     #a7c9ec;
    --mui-map-hi:     #1f669c;
}
:root:not([data-theme="light"]) {
    --mui-map-land:   #14315a;
    --mui-map-stroke: rgba(129, 205, 255, .10);
    --mui-map-lo:     #2f5d8f;
    --mui-map-hi:     #8fd0ff;
}
:root[data-theme="dark"] {
    --mui-map-land:   #14315a;
    --mui-map-stroke: rgba(129, 205, 255, .10);
    --mui-map-lo:     #2f5d8f;
    --mui-map-hi:     #8fd0ff;
}
.mui-worldmap { width: 100%; max-width: 900px; margin: 0 auto; }
.mui-worldmap svg { width: 100%; height: auto; display: block; }
.mui-worldmap path {
    fill: var(--mui-map-land);
    stroke: var(--mui-map-stroke);
    stroke-width: .6px;
    vector-effect: non-scaling-stroke;
    stroke-linejoin: round;
}
.mui-worldmap path.hit {
    fill: color-mix(in srgb, var(--mui-map-hi) calc(var(--t) * 100%), var(--mui-map-lo));
    transition: filter .12s ease;
}
.mui-worldmap path.hit:hover { filter: brightness(1.18); cursor: default; }

/* Traffic-location tab: core lays the Top
/* Traffic-location tab: core lays the "Top 5" donut and the world map in two
   <td> cells of one table, so the map is capped at ~half the panel. Stack the
   cells to blocks so the map spans the full panel width -- its own max-width
   (900px) then sets the real size. Scoped to this tab; the sources/referrers
   tab uses the same two-cell pattern but is left untouched. */
#stat_tab_location > table,
#stat_tab_location > table > tbody,
#stat_tab_location > table > tbody > tr,
#stat_tab_location > table > tbody > tr > td {
    display: block;
    width: 100%;
}
#stat_tab_location > table > tbody > tr > td { padding: 0; }
#stat_tab_location .mui-worldmap { margin-top: 6px; }

/* Stacking the location cells stretched core's per-cell separators into full-width
   rules that read as stray lines above/below the map. Drop the borders inside this
   tab, and on the stats page remove the footer's own rule + gap -- the big map
   already closes the section, so the extra line and whitespace are noise. */
#stat_tab_location > table,
#stat_tab_location > table td,
#stat_tab_location > table p { border: 0; background: none; }
body:has(#tabs) #footer { margin-top: 14px; padding-top: 0; border-top: 0; }

/* Traffic-sources tab: the left "Referrers" heading (an h3) and the right
   "Direct/Referrer traffic" lines (plain <p>) both follow an equal-height donut,
   but the h3's larger top margin dropped the left block ~11px lower. Give both the
   same top gap so the two columns' lower blocks start on the same line. */
#stat_tab_sources > table td > h3:nth-of-type(2),
#stat_tab_sources > table td > p:first-of-type { margin-top: 18px; }


/* Sticky footer on every admin page, not just the stats page: any short plugin
   page (tim-health, a nearly-empty tab, ...) left the footer floating mid-page,
   its border-top divider stranded under a slab of dead space -- disconnected
   from the sidebar, whose own divider (same border-top, above the theme/logout
   group) always sits snug against its last item because that group is sunk to
   the rail's foot with margin-top:auto. Body becomes a min-height column so
   #wrap grows and the footer sinks to match. width:100% on #wrap is required:
   its `margin:0 auto` is an auto cross-axis margin, which overrides
   align-items:stretch and would otherwise shrink #wrap to its content and centre
   it. With an explicit width it fills again (max-width:1180 + margin:auto still
   centre it). Tall pages keep scrolling normally (flex-grow only sets a floor). */
body:has(#admin_menu) { display: flex; flex-direction: column; min-height: 100vh; }
body:has(#admin_menu) > #wrap { flex: 1 0 auto; width: 100%; }

/* Delete-confirmation dialog. Core hardcodes a fixed 50em x 19em box (its content
   overflows -> the stray scroll bars) and styles the value <span>s with a light-
   blue border + #333 text that is invisible on the dark surface. Size the box to
   its content, wrap long URLs, and give the value chips readable theme colours. */
#delete-confirm-dialog {
    width: min(560px, 92vw);
    height: fit-content;
    max-height: 90vh;
    overflow: hidden;                    /* box now fits content; clip keeps corners clean */
}
#delete-confirm-dialog div.confirm-message {
    width: auto;
    height: auto;
    overflow: visible;
}
#delete-confirm-dialog div.confirm-message ul { border-left-color: var(--accent); list-style: none; }
#delete-confirm-dialog div.confirm-message ul li { overflow-wrap: anywhere; }
#delete-confirm-dialog div.confirm-message ul li span {
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text);
}
#delete-confirm-dialog div.button-group { width: auto; height: auto; }

/* Action-button loading/disabled state. While an action's AJAX runs (or the
   edit form is open) core paints the icon button #cc7 mustard-yellow (.loading) or
   #ccc grey (.disabled), both jarring on the dark theme. Keep them looking like a
   normal button -- the JS re-enables them, so no "dead grey" state. Specificity
   1,3,1 beats core's 0,3,1. */
#main_table td.actions .button.loading,
#main_table td.actions .button.disabled {
    background-color: var(--surface-2);
    background-image: none;
    border-color: var(--border-strong);
    color: var(--text);
}

/* "Sahip" (owner) column added by yourls-roles for admins/editors: secondary
   info, so dim and single-line, with an even quieter dash for unowned rows. */
#main_table td.owner { color: var(--text-dim); white-space: nowrap; }
#main_table td.owner .yroles-noowner { color: var(--text-faint); }

/* ============================================================ login page ===
   The admin sidebar -- with its corporate logo, theme button and language button
   -- doesn't exist on the login screen (no #admin_menu). Bring the same pieces
   here so the login page is branded, translatable and theme-toggleable too. */

/* Corporate logo instead of the YOURLS mark: hide the <img>, mask the anchor with
   the same logo.svg the sidebar uses, tinted navy (light) / white (dark). Sits
   right above the card, the way secure-redirector's password page places its
   own brand mark above its form -- no banner strip, no divider line, just the
   mark and a small gap. (Two overrides are needed, not just centring the
   header's own text-align: the general header[role=banner] h1 / h1 a rule
   above sets text-align:left *directly* on those elements, so it wins over
   inheriting the header's centred value -- and the general header rule's
   padding + border-bottom drew the divider/gap this replaces.) */
body.login header[role=banner] {
    text-align: center;
    padding: 0;
    margin-bottom: 20px;
    border-bottom: 0;
}
body.login #yourls-logo { display: none; }
body.login header[role=banner] h1,
body.login header[role=banner] h1 a { text-align: center; }
body.login header[role=banner] h1 { line-height: 0; margin: 0; }
body.login header[role=banner] h1 a {
    display: inline-block;
    width: 168px; height: 46px;
    background-color: #002554;
    -webkit-mask: url('logo.svg') no-repeat center / contain;
            mask: url('logo.svg') no-repeat center / contain;
}
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) body.login header[role=banner] h1 a { background-color: #ffffff; }
}
:root[data-theme="dark"]  body.login header[role=banner] h1 a { background-color: #ffffff; }
:root[data-theme="light"] body.login header[role=banner] h1 a { background-color: #002554; }

/* Core's #login rule (`margin: 200px auto 0 auto`) assumes a bare page with no
   card above it -- that whitespace was meant to vertically centre the form
   under a plain header. With the logo now sitting immediately above the card,
   it just pushed the card far below the mark (the gap seen before this fix). */
body.login #login { margin-top: 0; }

/* Theme + language buttons, injected by the head script on the login page. */
.modern-ui-login-controls {
    position: fixed; top: 16px; right: 16px; z-index: 20;
    display: flex; gap: 8px;
}
.modern-ui-login-controls .modern-ui-theme-btn { width: auto; }

/* Footer on the login screen: centre it and drop the full-width top rule so it
   reads as a quiet caption instead of a stray bar in the lower-left. */
body.login #footer { text-align: center; border-top: 0; margin-top: 40px; padding-top: 0; }
