/* ============================================================================
   settings.css -- Settings drawer (gear button + slide-in panel) and the
   theme / theater / cursor options it controls. Pairs with js/settings.js.

   Why a new file instead of appending to main.css: main.css is the bought
   theme (78KB) and has ZERO custom properties -- every colour in it is a
   literal hex. This file introduces the token layer the theme never had
   (--ubg-*) and keeps all the light-mode work in one place that can be
   reverted or diffed on its own.

   Applied entirely through attributes on <html>, set by the inline snippet
   in each page's <head> (see settings.js header for why it must be inline):
       data-theme         = "dark" | "light"
       data-theater       = "off" | "on"
       data-cursor        = "sword" | "dot" | "system"
       data-cursor-color  = one of the 6 dot hexes
       --cursor-color     = same hex, for the swatch rings / focus glows
   ========================================================================= */


/* ---------------------------------------------------------------------------
   1. TOKEN LAYER -- dark (the site's existing look, unchanged)
   Values lifted verbatim from main.css so dark mode renders exactly as before.
   ------------------------------------------------------------------------ */
:root {
    --ubg-bg: #100d28;          /* main.css:153  body background-color        */
    --ubg-bg-2: #1a1240;        /* main.css:183  body::before gradient stop   */
    --ubg-bg-3: #241659;
    --ubg-surface: #171c38;     /* main.css:2331 .parent_frame / .infor-first */
    --ubg-surface-2: #0f1428;
    --ubg-card: #27292a;        /* main.css:886  .most-popular .item          */
    --ubg-card-2: #1f2122;
    --ubg-panel: #12141c;       /* search.css:16 dropdown                     */
    --ubg-border: rgba(255, 255, 255, 0.10);
    --ubg-border-strong: rgba(255, 255, 255, 0.18);
    --ubg-fill: rgba(255, 255, 255, 0.05);
    --ubg-fill-2: rgba(255, 255, 255, 0.09);
    --ubg-text: #ffffff;
    --ubg-text-dim: #c9ccdd;    /* 11.86:1 on --ubg-bg */
    --ubg-text-mute: rgba(255, 255, 255, 0.45);
    --ubg-shadow: rgba(0, 0, 0, 0.45);
    --ubg-scrim: rgba(4, 4, 14, 0.62);
    --ubg-accent: #ec6090;      --ubg-accent-2: #e6306e;     /* 6.0:1 on bg */
    /* accent for TEXT sitting on a subtle fill rather than on the page --
       the light value is darker than --ubg-accent because a comment card is
       #ebebed, not white, and the plain accent only reached 4.14:1 there */
    --ubg-accent-strong: #ec6090;
    --ubg-accent-soft: rgba(236, 96, 144, .16);
    --ubg-accent-ink: #0b0d1a;
}

/* --ubg-accent-2 is the second stop of the filled-button gradient, so the
   site keeps the gradient buttons it has always had rather than going flat.
   It is NOT just "accent, darker": the original button
   (linear-gradient(135deg,#ec6090,#b5417d) with white text) could not pass at
   both ends -- white measures 3.16:1 on the bright stop and 5.23:1 on the
   dark one, and black is the other way round. So each second stop is the
   DARKEST variant of its hue that still keeps --ubg-accent-ink at >= 4.5:1,
   which makes the whole sweep legible instead of only half of it.

   --ubg-accent-ink is the text/icon colour that goes ON a filled accent chip.
   Black wins on every bright dark-theme accent (white is only 1.4-3.2:1
   there); white wins on the darkened light-theme accent. */


/* ---------------------------------------------------------------------------
   2. TOKEN LAYER -- light
   ------------------------------------------------------------------------ */
:root[data-theme="light"] {
    --ubg-bg: #f4f5fa;          --ubg-bg-2: #e9ebf5;        --ubg-bg-3: #e2e5f2;
    --ubg-surface: #ffffff;     --ubg-surface-2: #f0f1f7;
    --ubg-card: #ffffff;        --ubg-card-2: #f0f1f7;      --ubg-panel: #ffffff;
    --ubg-border: rgba(16, 18, 40, 0.12);
    --ubg-border-strong: rgba(16, 18, 40, 0.22);
    --ubg-fill: rgba(16, 18, 40, 0.045);
    --ubg-fill-2: rgba(16, 18, 40, 0.085);
    --ubg-text: #14162b;                                 /* 16.35:1 on bg */
    --ubg-text-dim: #4b4f63;                             /*  7.42:1 on bg */
    --ubg-text-mute: rgba(20, 22, 43, 0.55);
    --ubg-shadow: rgba(16, 18, 40, 0.14);
    --ubg-scrim: rgba(20, 22, 43, 0.42);
    /* Darkened until it measured >= 4.5:1 against the page background
       #f4f5fa -- the worst case here; a card is #fff and scores higher. */
    --ubg-accent: #db1559;      --ubg-accent-2: #af1147;    /* 4.52:1 on bg */
    --ubg-accent-strong: #c4174f;                           /* 4.92:1 on a card */
    --ubg-accent-soft: rgba(219, 21, 89, .10);
    --ubg-accent-ink: #ffffff;
}


/* ---------------------------------------------------------------------------
   3. GEAR BUTTON (injected into nav.main-nav by settings.js)
   ------------------------------------------------------------------------ */
.ubg-settings-btn {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    margin-left: 12px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Deliberately stronger than the panel's other chrome. At
       --ubg-border / --ubg-fill it was a barely-there grey ring that the
       user could not pick out of the header, in light mode especially. */
    border: 1.5px solid var(--ubg-border-strong);
    border-radius: 50%;
    background: var(--ubg-fill-2);
    color: var(--ubg-text);
    padding: 0;
    transition: background .18s ease, border-color .18s ease, transform .18s ease, color .18s ease;
}

.ubg-settings-btn svg {
    width: 21px;
    height: 21px;
    display: block;
    /* main.css:236 sets "img { width:100% }" -- this is an <svg>, not an
       <img>, so it is unaffected, but the explicit size keeps it stable if
       the flex parent ever shrinks. */
}

.ubg-settings-btn:hover,
.ubg-settings-btn:focus-visible {
    background: var(--ubg-accent-soft);
    border-color: var(--ubg-accent);
    color: var(--ubg-accent);
}

.ubg-settings-btn:focus-visible {
    outline: 2px solid var(--ubg-accent);
    outline-offset: 2px;
}

.ubg-settings-btn[aria-expanded="true"] {
    background: var(--ubg-accent-soft);
    border-color: var(--ubg-accent);
    color: var(--ubg-accent);
    transform: rotate(35deg);
}

/* Order inside nav.main-nav (a flex row): logo, search, GEAR, nav links,
   hamburger. The gear is appended by JS, so its position comes from here.

   It deliberately does NOT use `margin-left: auto` to sit at the far right:
   main.css:483 gives .main-nav `width: 100vw` while its .container parent is
   inset by the Bootstrap gutter, so the row's right edge is already off
   screen (body's overflow-x:hidden hides the spill). Anything flushed to
   that edge is clipped -- the gear was half off the viewport. Sitting it in
   the gap after the search box keeps it inside the visible area at every
   width. */
.header-area .main-nav .ubg-settings-btn { order: 2; }
.header-area .main-nav .nav              { order: 3; }
.header-area .main-nav .menu-trigger     { order: 4; }

@media (max-width: 1300px) {
    .header-area .main-nav .ubg-settings-btn {
        width: 40px;
        height: 40px;
        margin-left: 8px;
        margin-right: 6px;
    }
}


/* ---------------------------------------------------------------------------
   4. DRAWER
   ------------------------------------------------------------------------ */
.ubg-settings-overlay {
    position: fixed;
    inset: 0;
    background: var(--ubg-scrim);
    /* The blur is attached to .is-open, not here. A backdrop-filter on a
       closed, invisible overlay still promotes the whole viewport into a
       compositing layer and was measurably tinting what rendered underneath
       it -- the search dropdown came out around 77% opaque with the page
       showing through, on every page, in both themes. Nothing that is not
       on screen should be filtering the backdrop. */
    opacity: 0;
    visibility: hidden;
    /* Above .cmt-notif-stack (comment-notify.css:10, z-index 99999) so a
       toast cannot land on top of a modal dialog. */
    z-index: 100000;
    transition: opacity .22s ease, visibility 0s linear .22s;
}

.ubg-settings-overlay.is-open {
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
    opacity: 1;
    visibility: visible;
    transition: opacity .22s ease, visibility 0s linear 0s;
}

.ubg-settings-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: 340px;
    max-width: 100vw;
    z-index: 100001;
    display: flex;
    flex-direction: column;
    background: var(--ubg-panel);
    border-left: 1px solid var(--ubg-border);
    box-shadow: -18px 0 50px var(--ubg-shadow);
    color: var(--ubg-text);
    font-family: 'Poppins', sans-serif;
    transform: translateX(100%);
    visibility: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    transition: transform .26s cubic-bezier(.22, .61, .36, 1), visibility 0s linear .26s;
}

.ubg-settings-panel.is-open {
    transform: translateX(0);
    visibility: visible;
    transition: transform .26s cubic-bezier(.22, .61, .36, 1), visibility 0s linear 0s;
}

.ubg-settings-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 20px 20px 16px;
    border-bottom: 1px solid var(--ubg-border);
    position: sticky;
    top: 0;
    background: var(--ubg-panel);
    z-index: 1;
}

.ubg-settings-title {
    font-size: 17px;
    font-weight: 600;
    margin: 0;
    /* main.css:216 sets "h1..h6 { color:#fff }" at 0,0,1 with no !important,
       so one class is enough to win. */
    color: var(--ubg-text);
}

.ubg-settings-close {
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--ubg-border);
    border-radius: 50%;
    background: transparent;
    color: var(--ubg-text-dim);
    font-size: 17px;
    line-height: 1;
    padding: 0;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.ubg-settings-close:hover,
.ubg-settings-close:focus-visible {
    background: var(--ubg-fill-2);
    color: var(--ubg-text);
    border-color: var(--ubg-border-strong);
}

.ubg-settings-close:focus-visible {
    outline: 2px solid var(--ubg-accent);
    outline-offset: 2px;
}

.ubg-settings-body {
    padding: 6px 20px 26px;
}

.ubg-set-group[hidden] {
    display: none;
}

.ubg-set-label {
    display: block;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: .085em;
    text-transform: uppercase;
    color: var(--ubg-text-mute);
    margin: 20px 0 9px;
}

.ubg-set-hint {
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--ubg-text-mute);
    margin: 9px 0 0;
}

/* --- segmented control --- */
.ubg-seg {
    display: flex;
    gap: 4px;
    padding: 4px;
    border: 1px solid var(--ubg-border);
    border-radius: 12px;
    background: var(--ubg-fill);
}

.ubg-seg button {
    flex: 1 1 0;
    min-width: 0;
    padding: 9px 6px;
    border: none;
    border-radius: 9px;
    background: transparent;
    color: var(--ubg-text-dim);
    font-family: inherit;
    font-size: 13.5px;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background .15s ease, color .15s ease;
}

.ubg-seg button:hover {
    background: var(--ubg-fill-2);
    color: var(--ubg-text);
}

.ubg-seg button:focus-visible {
    outline: 2px solid var(--ubg-accent);
    outline-offset: -2px;
}

.ubg-seg button[aria-pressed="true"] {
    background: var(--ubg-accent);
    color: var(--ubg-accent-ink);
    font-weight: 600;
}

/* --- colour swatches --- */
.ubg-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

.ubg-swatches button {
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
    padding: 0;
    border: 2px solid var(--ubg-border);
    border-radius: 50%;
    background: var(--ubg-sw);
    transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease;
}

.ubg-swatches button:hover {
    transform: scale(1.1);
}

.ubg-swatches button:focus-visible {
    outline: 2px solid var(--ubg-text);
    outline-offset: 3px;
}

.ubg-swatches button[aria-pressed="true"] {
    border-color: var(--ubg-panel);
    box-shadow: 0 0 0 2px var(--ubg-text);
}

/* Mobile: full width */
@media (max-width: 480px) {
    .ubg-settings-panel {
        width: 100vw;
        border-left: none;
    }
}

/* Scroll lock, set on <html> by settings.js while the drawer is open. */
:root.ubg-no-scroll,
:root.ubg-no-scroll body {
    /* overrides main.css:1754 "body { overflow-x: hidden }" */
    overflow: hidden !important;
}

@media (prefers-reduced-motion: reduce) {
    .ubg-settings-panel,
    .ubg-settings-overlay,
    .ubg-settings-btn,
    .ubg-settings-close,
    .ubg-seg button,
    .ubg-swatches button {
        transition: none !important;
    }
    .ubg-settings-btn[aria-expanded="true"],
    .ubg-swatches button:hover {
        transform: none;
    }
}


/* ---------------------------------------------------------------------------
   5. LIGHT MODE -- hunting the hard-coded darks
   Every rule below is prefixed with :root[data-theme="light"], which adds
   0,2,0 of specificity, so it beats the theme's own class selectors without
   needing !important.
   ------------------------------------------------------------------------ */

/* 5.1 page canvas ------------------------------------------------------- */
:root[data-theme="light"] {
    color-scheme: light;    /* also set inline by the head snippet */
}

:root[data-theme="light"] body {
    background-color: var(--ubg-bg);
    color: var(--ubg-text);
}

/* The decorative dark gradient (main.css:178) is position:fixed;inset:0 and
   covers the whole viewport, so leaving it alone would keep the page dark no
   matter what body's background-color says. */
:root[data-theme="light"] body::before {
    background: linear-gradient(-45deg, var(--ubg-bg), var(--ubg-bg-2), var(--ubg-bg-3), var(--ubg-bg-2), var(--ubg-bg));
}

/* 5.2 text -------------------------------------------------------------- */
:root[data-theme="light"] h1,
:root[data-theme="light"] h2,
:root[data-theme="light"] h3,
:root[data-theme="light"] h4,
:root[data-theme="light"] h5,
:root[data-theme="light"] h6 {
    color: var(--ubg-text);     /* main.css:216 "color: #fff" */
}

:root[data-theme="light"] p,
:root[data-theme="light"] li,
:root[data-theme="light"] strong,
:root[data-theme="light"] em {
    color: var(--ubg-text);     /* main.css:231 "p { color: #fff }" */
}

:root[data-theme="light"] a {
    color: var(--ubg-text-dim); /* main.css:202 "a { color: #CCC }" */
}

:root[data-theme="light"] a:hover {
    color: var(--ubg-accent);   /* main.css:206 "a:hover { color: #F99 }" */
}

/* 5.3 header ------------------------------------------------------------ */
/* Two different values, exactly as warned: .header-area is transparent
   (main.css:464) and the sticky state is #1a1a1a (main.css:1810, which sits
   inside a max-width media query -- the 0,3,0 prefix here wins regardless of
   source order). */
:root[data-theme="light"] .background-header {
    background-color: var(--ubg-surface);
    box-shadow: 0 2px 14px var(--ubg-shadow);
}

/* The nav pills are set twice: main.css:578 `background-color: #27292a` and
   again at :2149 with the `background` SHORTHAND, which also plants a
   `background-image: linear-gradient(45deg,#27292a,#1f2122)`. A
   higher-specificity `background-color` does NOT remove that image -- the
   gradient just keeps painting on top of it. The shorthand has to be
   answered with the shorthand. (Caught by a computed-style dump: the pills
   stayed dark in light mode while background-color reported #fff.) */
:root[data-theme="light"] .header-area .main-nav .nav li a {
    background: linear-gradient(45deg, var(--ubg-surface), var(--ubg-surface-2));
    color: var(--ubg-text);
    border: 2px solid var(--ubg-border);
    /* main.css:2157 glows these in neon cyan, which is invisible on white. */
    box-shadow: 0 1px 3px var(--ubg-shadow);
}

:root[data-theme="light"] .header-area .main-nav .nav li a:hover {
    background: var(--ubg-accent);
    border-color: var(--ubg-accent);
    /* !important overrides main.css:2163 `color: #fff !important` -- that rule
       forces white text under a neon-cyan hover gradient, which on a light
       page is white-on-near-white. */
    color: var(--ubg-accent-ink) !important;
    box-shadow: 0 2px 10px var(--ubg-shadow);
}

/* Related-game link pills inside the description (main.css:2377). Same trap:
   `color: #fff !important` over a `background:` shorthand gradient of
   #00f2fe -> #4facfe. White on cyan measures 1.09:1 against a light page. */
:root[data-theme="light"] .infor-first p a {
    background: var(--ubg-accent);
    color: var(--ubg-accent-ink) !important;   /* overrides main.css:2383 */
    box-shadow: 0 2px 10px var(--ubg-shadow);
}

:root[data-theme="light"] .infor-first p a:hover {
    color: var(--ubg-accent-ink) !important;   /* overrides main.css:2392 */
    box-shadow: 0 4px 16px var(--ubg-shadow);
}

/* Action-bar buttons: main.css:2436 gives them `color: #ddd` on
   `rgba(255,255,255,.06)` -- light grey on a light card, 1.25:1. */
:root[data-theme="light"] .poki-btn {
    background: var(--ubg-fill);
    border-color: var(--ubg-border);
    color: var(--ubg-text-dim);
}

:root[data-theme="light"] .poki-btn:hover {
    background: var(--ubg-accent-soft);
    border-color: var(--ubg-accent);
    color: var(--ubg-accent);
    box-shadow: none;
}

/* Hamburger bars: main.css:670-701 draws them in the theme's pink.
   The :not(.active) is load-bearing. main.css:730 turns the MIDDLE bar
   transparent when the menu is open, which is what forms the X out of the
   remaining two bars -- and that rule is only 0,4,1. The first version of
   this override was 0,5,1 and carried no .active qualifier, so it won and
   painted the middle bar back in: the close button rendered as an X with a
   horizontal line through it. The open state is handled separately below. */
:root[data-theme="light"] .header-area .main-nav .menu-trigger:not(.active) span,
:root[data-theme="light"] .header-area .main-nav .menu-trigger:not(.active) span:before,
:root[data-theme="light"] .header-area .main-nav .menu-trigger:not(.active) span:after,
:root[data-theme="light"] .background-header .main-nav .menu-trigger:not(.active) span,
:root[data-theme="light"] .background-header .main-nav .menu-trigger:not(.active) span:before,
:root[data-theme="light"] .background-header .main-nav .menu-trigger:not(.active) span:after {
    background-color: var(--ubg-text);
}

/* Open state: only the two diagonals are painted, the middle bar stays
   transparent so the X has no bar through it. */
:root[data-theme="light"] .header-area .main-nav .menu-trigger.active span:before,
:root[data-theme="light"] .header-area .main-nav .menu-trigger.active span:after,
:root[data-theme="light"] .background-header .main-nav .menu-trigger.active span:before,
:root[data-theme="light"] .background-header .main-nav .menu-trigger.active span:after {
    background-color: var(--ubg-text);
}

/* The mobile dropdown is rebuilt wholesale in section 11. */

/* 5.4 inputs -- background, text AND placeholder ------------------------ */
/* The live rule is main.css:2194 (`rgba(39,41,42,.9)` + #fff + a 2px cyan
   border and a cyan glow), NOT the `burlywood` one at main.css:496 -- that
   earlier rule is dead code, overridden by :2194 at equal specificity and
   later source order. The dark field measures 14.62:1 and is left alone.
   What does need answering here is the neon glow: a cyan box-shadow reads as
   a smear on a light page, and the cyan border drops to ~1.5:1 on white. */
:root[data-theme="light"] .header-area .main-nav #search input {
    background-color: var(--ubg-surface);
    color: var(--ubg-text);
    border: 1px solid var(--ubg-border);
    box-shadow: 0 1px 3px var(--ubg-shadow);   /* replaces main.css:2203 cyan glow */
}

:root[data-theme="light"] .header-area .main-nav #search input:focus {
    border-color: var(--ubg-accent);           /* main.css:2210 #4facfe */
    box-shadow: 0 0 0 3px var(--ubg-accent-soft);
    background: var(--ubg-surface);
}

:root[data-theme="light"] .header-area .main-nav #search input::placeholder {
    color: var(--ubg-text-mute);
}

:root[data-theme="light"] .header-area .main-nav #search i,
:root[data-theme="light"] .header-area .main-nav #search input:focus + i,
:root[data-theme="light"] .header-area .main-nav #search:hover i {
    color: var(--ubg-text-dim);                /* main.css:2216/2229 cyan */
}

:root[data-theme="light"] .comment-form input,
:root[data-theme="light"] .comment-form textarea {
    background: var(--ubg-fill);            /* comment.css:68 rgba(255,255,255,.05) */
    border-color: var(--ubg-border);
    color: var(--ubg-text);
}

:root[data-theme="light"] .comment-form input::placeholder,
:root[data-theme="light"] .comment-form textarea::placeholder {
    color: var(--ubg-text-mute);            /* comment.css:91 rgba(255,255,255,.4) */
}

:root[data-theme="light"] .comment-form input:focus,
:root[data-theme="light"] .comment-form textarea:focus {
    border-color: var(--ubg-accent);
    background: var(--ubg-fill-2);
}

/* 5.5 game page surfaces ----------------------------------------------- */
:root[data-theme="light"] .parent_frame,
:root[data-theme="light"] .poki-actionbar,
:root[data-theme="light"] .main_game .header-text .infor-first {
    background: linear-gradient(180deg, var(--ubg-surface), var(--ubg-surface-2));
    box-shadow: 0 10px 30px var(--ubg-shadow);
}

:root[data-theme="light"] .poki-share-menu {
    background: var(--ubg-surface);
    border-color: var(--ubg-border);
}

:root[data-theme="light"] .poki-btn[data-tooltip]::after {
    background: var(--ubg-text);
    color: var(--ubg-bg);
}

:root[data-theme="light"] .most-popular .item {
    background-color: var(--ubg-card);      /* main.css:886 #27292a */
    border: 1px solid var(--ubg-border);
}

/* Ghost / white-filled buttons: .directlink is #27292a with white text, and
   its :hover flips to a WHITE background with dark text (main.css:1903) --
   on a light page that is white-on-white. Both states get flipped. */
:root[data-theme="light"] .directlink {
    background-color: var(--ubg-card);
    color: var(--ubg-text);
    border: 1px solid var(--ubg-border);
}

:root[data-theme="light"] .directlink:hover {
    background-color: var(--ubg-accent);
    color: var(--ubg-accent-ink);
}

:root[data-theme="light"] .directlink:hover p,
:root[data-theme="light"] .directlink:hover i {
    color: var(--ubg-accent-ink);
}

/* 5.6 search dropdown (search.css) ------------------------------------- */
:root[data-theme="light"] .search-input .result_search.search-panel {
    background: var(--ubg-panel);           /* search.css:16 #12141c */
    border-color: var(--ubg-border);
    box-shadow: 0 24px 60px var(--ubg-shadow);
}

:root[data-theme="light"] .search-input .result_search.search-panel::-webkit-scrollbar-thumb {
    background: var(--ubg-fill-2);
    border-color: var(--ubg-panel);
}

/* 5.7 comments (comment.css) ------------------------------------------- */
:root[data-theme="light"] .comment-section {
    background: var(--ubg-surface);         /* comment.css:12 rgba(20,22,40,.72) */
    border: 1px solid var(--ubg-border);
}

:root[data-theme="light"] .comment-item,
:root[data-theme="light"] .cmt-reply-box {
    background: var(--ubg-fill);
}

/* The :not()s matter. Without them this rule (0,3,0) outranks the accent
   rules in section 6 (0,1,0) and repaints the ink of anything sitting on a
   coloured chip with the body text colour. Three separate things were caught
   this way, each only by a computed-style dump rather than by eye:
     .comment-count-badge   dark navy on pink          3.62:1
     .comment-pinned-tag    dark navy on pink          3.62:1
     .comment-avatar        dark navy on a hsl circle  2.07:1
   All three want their own ink, so all three are excluded here. */
:root[data-theme="light"] .comment-section,
:root[data-theme="light"] .comment-section p,
:root[data-theme="light"] .comment-section span:not(.comment-count-badge):not(.comment-pinned-tag),
:root[data-theme="light"] .comment-section div:not(.comment-avatar) {
    color: var(--ubg-text);
}

/* 5.8 toasts ----------------------------------------------------------- */
:root[data-theme="light"] .ubg-fav-toast,
:root[data-theme="light"] .cmt-notif {
    background: var(--ubg-surface);         /* main.css:2696 gradient #1d1533 */
    color: var(--ubg-text);
    border-color: var(--ubg-border);
    box-shadow: 0 14px 34px var(--ubg-shadow);
}

/* 5.9 footer ----------------------------------------------------------- */
:root[data-theme="light"] footer,
:root[data-theme="light"] .copyright p {
    color: var(--ubg-text);
}

/* The footer link chips are `background-color: lightcoral` (main.css:1921)
   in BOTH themes, and main.css:202 paints links on them in near-white --
   2.59:1, which is why they are hard to read on the live site today. This is
   the one fix here that is not theme-scoped: the chip colour is the same in
   dark and light, so the ink has to be too. The coral is left alone; only
   the text flips, which takes it to 7.46:1. */
.information_website .information_name a {
    color: #0b0d1a;
}

.information_website .information_name a:hover {
    color: #000000;                     /* 8.10:1 */
}

:root[data-theme="light"] .copyright {
    border-top-color: var(--ubg-border);
}

/* 5.10 preloader ------------------------------------------------------- */
:root[data-theme="light"] .js-preloader {
    background-color: rgba(244, 245, 250, 0.99);  /* main.css:361 rgba(0,0,0,.99) */
}


/* ---------------------------------------------------------------------------
   6. ACCENT -- route the hard-coded pink/cyan spots through the token
   These run in BOTH themes (that is the point of the option), so they are
   NOT prefixed with data-theme.
   ------------------------------------------------------------------------ */
/* Gradient, not flat: comment.css:104 already shipped these as a
   135deg gradient and losing it flattened the look of the whole comment
   box. --ubg-accent-2 keeps the sweep while staying legible at both ends
   (see the token comment in section 1). */
.btn-submit-comment,
.btn-cmt-save,
.btn-reply-post {
    /* comment.css:104 gradient #ec6090->#b5417d, :346 #ec6090, :574 #00c2d1 */
    background: linear-gradient(135deg, var(--ubg-accent), var(--ubg-accent-2));
    color: var(--ubg-accent-ink);
}

.comment-count-badge {
    background: var(--ubg-accent);          /* comment.css:46, flat by design */
    color: var(--ubg-accent-ink);
}

.btn-submit-comment:hover,
.btn-cmt-save:hover,
.btn-reply-post:hover {
    background: linear-gradient(135deg, var(--ubg-accent), var(--ubg-accent-2));
    filter: brightness(1.12);
}

.main_game .header-text .infor-first,
.parent_frame,
.poki-actionbar {
    border-color: var(--ubg-accent-soft);   /* main.css:2361 rgba(0,242,254,.18) */
}


/* ---------------------------------------------------------------------------
   7. CURSOR MODES
   The site does NOT have a two-layer JS cursor -- it paints a single 32x32
   PNG (images/cursor.png) through `cursor: url(...)`. The base rule is
   main.css:97, which lists ~50 bare tag names and ends in !important:
       html, body, div, span, iframe, h1..h6, p, a, ul, li, header, nav,
       footer, ... { cursor: url(cursor.png) 0 0, auto !important }
   Specificity there is 0,0,1. `:root[data-cursor="..."]` is 0,2,0, so the
   rules below outrank it -- but !important is still REQUIRED, because a
   declaration without it always loses to one with it regardless of
   specificity. Every !important in this section is overriding that rule,
   plus main.css:647 (.menu-trigger), :930, :1899 (.directlink) and :2456
   (.poki-actionbar .poki-btn), which set the same PNG without !important.

   "sword" deliberately emits NOTHING, so the theme's own cursor -- including
   its per-element hover variants -- is left completely untouched.
   ------------------------------------------------------------------------ */

/* --- system: hand the OS cursor back. Nothing in this codebase sets
       `cursor: none` (checked), so only the PNG has to be undone. --- */
:root[data-cursor="system"],
:root[data-cursor="system"] * {
    cursor: auto !important;    /* overrides main.css:97, which is !important */
}

:root[data-cursor="system"] a,
:root[data-cursor="system"] button,
:root[data-cursor="system"] [role="button"],
:root[data-cursor="system"] .menu-trigger,
:root[data-cursor="system"] .poki-btn,
:root[data-cursor="system"] .most-popular .item,
:root[data-cursor="system"] input[type="submit"],
:root[data-cursor="system"] label {
    cursor: pointer !important; /* overrides main.css:97 and :2456 */
}

:root[data-cursor="system"] input[type="text"],
:root[data-cursor="system"] textarea {
    cursor: text !important;    /* overrides main.css:97 */
}

/* --- dot: a small filled circle. `cursor: url()` cannot read a CSS variable
       (the data-URI is a separate document), so rather than generating it in
       JS -- which would flash the sword cursor until the script ran -- there
       is one rule per palette colour, matched on the data-cursor-color
       attribute the <head> snippet already sets. Pure CSS, correct from the
       first paint.
       Each dot is drawn twice: a faint black outer ring so it stays visible
       on a light background, and a white inner ring so it stays visible on a
       dark one. Hotspot is 8 8 (the centre). --- */
:root[data-cursor="dot"][data-cursor-color="#ec6090"],
:root[data-cursor="dot"][data-cursor-color="#ec6090"] * {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='5.8' fill='none' stroke='%23000' stroke-opacity='.45' stroke-width='1'/%3E%3Ccircle cx='8' cy='8' r='4.4' fill='%23ec6090' stroke='%23fff' stroke-width='1.4'/%3E%3C/svg%3E") 8 8, auto !important;
}

:root[data-cursor="dot"][data-cursor-color="#00f2fe"],
:root[data-cursor="dot"][data-cursor-color="#00f2fe"] * {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='5.8' fill='none' stroke='%23000' stroke-opacity='.45' stroke-width='1'/%3E%3Ccircle cx='8' cy='8' r='4.4' fill='%2300f2fe' stroke='%23fff' stroke-width='1.4'/%3E%3C/svg%3E") 8 8, auto !important;
}

:root[data-cursor="dot"][data-cursor-color="#a77bff"],
:root[data-cursor="dot"][data-cursor-color="#a77bff"] * {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='5.8' fill='none' stroke='%23000' stroke-opacity='.45' stroke-width='1'/%3E%3Ccircle cx='8' cy='8' r='4.4' fill='%23a77bff' stroke='%23fff' stroke-width='1.4'/%3E%3C/svg%3E") 8 8, auto !important;
}

:root[data-cursor="dot"][data-cursor-color="#4ecca3"],
:root[data-cursor="dot"][data-cursor-color="#4ecca3"] * {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='5.8' fill='none' stroke='%23000' stroke-opacity='.45' stroke-width='1'/%3E%3Ccircle cx='8' cy='8' r='4.4' fill='%234ecca3' stroke='%23fff' stroke-width='1.4'/%3E%3C/svg%3E") 8 8, auto !important;
}

:root[data-cursor="dot"][data-cursor-color="#ffbb33"],
:root[data-cursor="dot"][data-cursor-color="#ffbb33"] * {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='5.8' fill='none' stroke='%23000' stroke-opacity='.45' stroke-width='1'/%3E%3Ccircle cx='8' cy='8' r='4.4' fill='%23ffbb33' stroke='%23fff' stroke-width='1.4'/%3E%3C/svg%3E") 8 8, auto !important;
}

:root[data-cursor="dot"][data-cursor-color="#ffffff"],
:root[data-cursor="dot"][data-cursor-color="#ffffff"] * {
    cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Ccircle cx='8' cy='8' r='5.8' fill='none' stroke='%23000' stroke-opacity='.55' stroke-width='1.2'/%3E%3Ccircle cx='8' cy='8' r='4.4' fill='%23ffffff' stroke='%23000' stroke-opacity='.35' stroke-width='1'/%3E%3C/svg%3E") 8 8, auto !important;
}

/* Keep the I-beam on text fields in dot mode -- a dot sitting on the caret
   makes a field genuinely hard to type in, and sword mode already gets this
   for free (main.css:97 lists no form elements).

   The redundant-looking `[data-cursor-color]` is load-bearing. The dot rules
   above match on TWO attributes, so they score 0,3,0; a plain
   `:root[data-cursor="dot"] textarea` is only 0,2,1 and loses, !important on
   both or not. Matching the same two attributes brings these to 0,3,1.
   (The first attempt here omitted it and the dot still won -- caught by a
   getComputedStyle dump, not by eye.) */
:root[data-cursor="dot"][data-cursor-color] input,
:root[data-cursor="dot"][data-cursor-color] textarea {
    cursor: text !important;
}

:root[data-cursor="dot"][data-cursor-color] input[type="submit"],
:root[data-cursor="dot"][data-cursor-color] input[type="button"],
:root[data-cursor="dot"][data-cursor-color] input[type="checkbox"],
:root[data-cursor="dot"][data-cursor-color] input[type="radio"],
:root[data-cursor="dot"][data-cursor-color] select {
    cursor: pointer !important;
}

/* The panel's own controls are <button>s, which main.css:97 does not list.
   Bootstrap's "button:not(:disabled) { cursor: pointer }" is 0,2,0 (the
   :not() counts), so a single class would lose -- these selectors are 0,2,0
   and 0,1,0-plus-descendant, and come later in the cascade. */
.ubg-settings-panel button,
.ubg-settings-overlay {
    cursor: url("https://unblockedgames88.gitlab.io/assets/images/cursor.png"), pointer;
}

:root[data-cursor="system"] .ubg-settings-panel button,
:root[data-cursor="system"] .ubg-settings-btn,
:root[data-cursor="system"] .ubg-settings-overlay {
    cursor: pointer !important;
}


/* ---------------------------------------------------------------------------
   8. THEATER MODE  (data-theater="on")
   Dims the page around the game instead of raising the game above an overlay.
   An overlay would need .parent_frame lifted out of the z-order, and it sits
   six levels deep inside Bootstrap rows/columns -- any ancestor that ever
   gains a transform, filter or opacity creates a stacking context and traps
   it. Dimming the known siblings has no such failure mode.

   Every rule is gated on :has(.main_game .parent_frame) -- "this page has a
   game in it". Without that gate the setting is stored globally but the
   styling applied everywhere: turning theater on inside a game and then
   going back to the homepage left it near-black with a dimmed header and
   footer, on a page with nothing to put in the spotlight. Checked across the
   whole site: 493 pages carry .main_game + .parent_frame and no page outside
   /game/ carries either, so the test is exact.

   The toggle itself is shown on every page (settings.js no longer hides it),
   because the visitor has to be able to switch this off from wherever they
   ended up -- which was the other half of the same bug.

   :has() rather than a class added by settings.js: that script runs at the
   end of <body>, so keying on it would paint the page dark first and undo it
   after, which is the flash this whole feature is built to avoid.
   ------------------------------------------------------------------------ */

:root[data-theater="on"]:has(.main_game .parent_frame) body {
    background-color: #05060d;
}

:root[data-theater="on"]:has(.main_game .parent_frame) body::before {
    /* Flatten the decorative gradient (main.css:178) -- in theater mode any
       colour behind the game is a distraction. */
    background: #05060d;
}

/* The header's CONTENTS are dimmed, not .header-area itself. opacity on a
   parent caps every child, so dimming the bar as a whole dragged the gear
   button down with it -- and the gear is the one control you need to get
   back OUT of theater mode, so it has to stay readable. */
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area .logo,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area .search-input,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area .nav,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area .menu-trigger,
:root[data-theater="on"]:has(.main_game .parent_frame) .name-game,
:root[data-theater="on"]:has(.main_game .parent_frame) .gamezone .ads,
:root[data-theater="on"]:has(.main_game .parent_frame) .main_game .header-text,
:root[data-theater="on"]:has(.main_game .parent_frame) .most-popular,
:root[data-theater="on"]:has(.main_game .parent_frame) footer {
    opacity: 0.16;
    transition: opacity 0.28s ease;
}

/* Still reachable: hovering or tabbing into a dimmed block brings it back,
   so theater mode never locks anyone out of the search box or the menu. */
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area:hover .logo,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area:hover .search-input,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area:hover .nav,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area:hover .menu-trigger,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area:focus-within .logo,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area:focus-within .search-input,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area:focus-within .nav,
:root[data-theater="on"]:has(.main_game .parent_frame) .header-area:focus-within .menu-trigger,
:root[data-theater="on"]:has(.main_game .parent_frame) .name-game:hover,
:root[data-theater="on"]:has(.main_game .parent_frame) .main_game .header-text:hover,
:root[data-theater="on"]:has(.main_game .parent_frame) .main_game .header-text:focus-within,
:root[data-theater="on"]:has(.main_game .parent_frame) .most-popular:hover,
:root[data-theater="on"]:has(.main_game .parent_frame) footer:hover {
    opacity: 1;
}

/* Theater mode paints a near-black backdrop in BOTH themes -- it is meant to
   be a dark room. That means the light theme's chrome tokens (dark ink
   #14162b on a dark border) are exactly wrong for anything left undimmed:
   the gear button vanished into the backdrop, which is worse than the
   dimming it was exempted from in the first place. Anything that stays at
   full opacity in here has to be styled for a dark surface regardless of
   which theme is active. */
:root[data-theater="on"]:has(.main_game .parent_frame) .ubg-settings-btn {
    border-color: rgba(255, 255, 255, 0.30);
    background: rgba(255, 255, 255, 0.13);
    color: #ffffff;                     /* 15.9:1 on the #05060d backdrop */
}

:root[data-theater="on"]:has(.main_game .parent_frame) .ubg-settings-btn:hover,
:root[data-theater="on"]:has(.main_game .parent_frame) .ubg-settings-btn:focus-visible,
:root[data-theater="on"]:has(.main_game .parent_frame) .ubg-settings-btn[aria-expanded="true"] {
    background: var(--ubg-accent-soft);
    border-color: var(--ubg-accent);
    color: var(--ubg-accent);
}

/* The game itself gets a little more presence. */
:root[data-theater="on"]:has(.main_game .parent_frame) .parent_frame,
:root[data-theater="on"]:has(.main_game .parent_frame) .poki-actionbar {
    box-shadow: 0 0 0 1px var(--ubg-accent-soft), 0 24px 70px rgba(0, 0, 0, 0.75);
}

@media (prefers-reduced-motion: reduce) {
    :root[data-theater="on"]:has(.main_game .parent_frame) .header-area .logo,
    :root[data-theater="on"]:has(.main_game .parent_frame) .header-area .search-input,
    :root[data-theater="on"]:has(.main_game .parent_frame) .header-area .nav,
    :root[data-theater="on"]:has(.main_game .parent_frame) .header-area .menu-trigger,
    :root[data-theater="on"]:has(.main_game .parent_frame) .name-game,
    :root[data-theater="on"]:has(.main_game .parent_frame) .gamezone .ads,
    :root[data-theater="on"]:has(.main_game .parent_frame) .main_game .header-text,
    :root[data-theater="on"]:has(.main_game .parent_frame) .most-popular,
    :root[data-theater="on"]:has(.main_game .parent_frame) footer {
        transition: none;
    }
}


/* ---------------------------------------------------------------------------
   9. SESSION TIMER (row at the bottom of the panel)
   ------------------------------------------------------------------------ */
.ubg-session {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px;
    border-radius: 16px;
    border: 1px solid var(--ubg-border);
    background: var(--ubg-fill);
}

/* ---- the clock ----------------------------------------------------------
   An analogue face, not a progress bar. The hands show how long this sitting
   has run; the ring around the outside is progress through the current
   5-minute cycle, which is what the line under the figure counts down to.
   The SVG is a 100x100 viewBox so every coordinate is a percentage of the
   dial -- changing the size below is the only thing needed to rescale it. */
.ubg-clock {
    flex: 0 0 76px;
    width: 76px;
    height: 76px;
}

.ubg-clock svg {
    width: 100%;
    height: 100%;
    display: block;
    overflow: visible;
}

.ubg-clock-ring-track,
.ubg-clock-ring {
    fill: none;
    stroke-width: 5;
}

.ubg-clock-ring-track {
    stroke: var(--ubg-border-strong);
}

.ubg-clock-ring {
    stroke: var(--ubg-accent);
    stroke-linecap: round;
    /* drawn from 12 o'clock; dasharray/offset come from settings.js */
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
    transition: stroke-dashoffset .5s linear;
    filter: drop-shadow(0 0 4px var(--ubg-accent-soft));
}

.ubg-clock-face {
    fill: var(--ubg-surface-2);
    stroke: var(--ubg-border);
    stroke-width: 1;
}

.ubg-tick {
    stroke: var(--ubg-text-mute);
    stroke-width: 1;
    stroke-linecap: round;
}

.ubg-tick-major {
    stroke: var(--ubg-text-dim);
    stroke-width: 2.2;
}

.ubg-hand {
    stroke: var(--ubg-text);
    stroke-linecap: round;
    /* NO transform-origin here. settings.js sets the SVG attribute
       `rotate(deg 50 50)`, which already carries the pivot. A CSS
       transform-origin on top of that is applied as well, so the pivot lands
       at twice the offset and the hands swing right out of the dial -- the
       minute hand measured 43px outside the face. The ring below is a
       different case: it uses a two-argument rotate() and needs its origin. */
}

.ubg-hand-h { stroke-width: 4.5; }
.ubg-hand-m { stroke-width: 3; }

.ubg-hand-s {
    stroke: var(--ubg-accent);
    stroke-width: 1.4;
    /* the only thing that visibly moves each second, so it is what makes the
       panel read as running rather than as a static figure */
    transition: transform .18s cubic-bezier(.4, 2.2, .6, 1);
}

.ubg-clock-pin {
    fill: var(--ubg-accent);
    stroke: var(--ubg-surface-2);
    stroke-width: 1.5;
}

/* ---- the figures ------------------------------------------------------ */
.ubg-session-meta {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
}

.ubg-session-label {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--ubg-text-mute);
}

.ubg-session-value {
    /* Tabular figures, or the row jitters every second as the digits change. */
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 28px;
    line-height: 1.1;
    letter-spacing: -.01em;
    color: var(--ubg-text);
}

.ubg-session-next {
    font-variant-numeric: tabular-nums;
    font-size: 12px;
    font-weight: 600;
    color: var(--ubg-accent);
}

@media (prefers-reduced-motion: reduce) {
    .ubg-clock-ring,
    .ubg-hand-s {
        transition: none;
    }
}

/* The drawer is 340px and goes full width under 480px; at the narrow end the
   76px dial plus a 28px figure would push the countdown line into a wrap. */
@media (max-width: 360px) {
    .ubg-clock { flex-basis: 64px; width: 64px; height: 64px; }
    .ubg-session-value { font-size: 25px; }
    .ubg-session-next { font-size: 11.5px; }
}


/* ---------------------------------------------------------------------------
   10. THE 5-MINUTE SUGGESTION CARD
   Deliberately NOT a modal: it can appear mid-match, and an overlay there
   would steal pointer lock from the game. It sits in the corner, blocks
   nothing, and traps no focus.
   ------------------------------------------------------------------------ */
.ubg-suggest {
    position: fixed;
    right: 20px;
    bottom: 20px;
    width: 330px;
    max-width: calc(100vw - 32px);
    padding: 18px 18px 16px;
    border: 1px solid var(--ubg-border);
    border-radius: 16px;
    background: var(--ubg-panel);
    box-shadow: 0 18px 50px var(--ubg-shadow);
    color: var(--ubg-text);
    font-family: "Poppins", sans-serif;
    /* Under .cmt-notif-stack (comment-notify.css:10, 99999) and under the
       settings drawer, so neither ever ends up behind this. */
    z-index: 99998;
    opacity: 0;
    transform: translateY(14px);
    transition: opacity 0.28s ease, transform 0.28s ease;
}

.ubg-suggest.is-open {
    opacity: 1;
    transform: translateY(0);
    /* A glow that runs three times and stops. The point is to catch the eye
       of someone mid-game without leaving a light pulsing beside the screen
       for as long as they ignore the card -- settings.js adds .is-settled
       after the run so the animation cannot restart. */
    animation: ubgSuggestGlow 0.9s ease-out 3;
}

.ubg-suggest.is-settled {
    animation: none;
    box-shadow: 0 18px 50px var(--ubg-shadow);
}

@keyframes ubgSuggestGlow {
    0%, 100% { box-shadow: 0 18px 50px var(--ubg-shadow), 0 0 0 0 var(--ubg-accent-soft); }
    50%      { box-shadow: 0 18px 50px var(--ubg-shadow), 0 0 0 6px var(--ubg-accent-soft); }
}

.ubg-suggest-close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--ubg-text-mute);
    font-size: 13px;
    line-height: 1;
}

.ubg-suggest-close:hover {
    background: var(--ubg-fill-2);
    color: var(--ubg-text);
}

.ubg-suggest-title {
    display: flex;
    align-items: center;
    gap: 7px;
    margin: 0 26px 2px 0;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.35;
    color: var(--ubg-text);
}

.ubg-suggest-arrow {
    width: 17px;
    height: 17px;
    flex: 0 0 auto;
    color: var(--ubg-accent);
    animation: ubgArrowNudge 1.5s ease-in-out infinite;
}

@keyframes ubgArrowNudge {
    0%, 100% { transform: translateX(0); }
    50%      { transform: translateX(4px); }
}

.ubg-suggest-sub {
    margin: 0 0 12px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--ubg-text-mute);
}

.ubg-suggest-games {
    display: flex;
    gap: 10px;
    margin-bottom: 14px;
}

.ubg-suggest-game {
    flex: 1 1 0;
    min-width: 0;
    display: block;
    text-align: center;
    color: var(--ubg-text-dim);
    font-size: 11.5px;
    line-height: 1.3;
}

.ubg-suggest-game img {
    width: 100%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 10px;
    margin-bottom: 6px;
    display: block;
    /* the "frame lights up" part: a ring in the theme accent, brighter on
       hover. box-shadow rather than border so it costs no layout space and
       cannot change the tile size at any viewport width. */
    box-shadow: 0 0 0 1.5px var(--ubg-accent-soft), 0 0 12px var(--ubg-accent-soft);
    transition: transform 0.16s ease, box-shadow 0.16s ease;
}

.ubg-suggest-game span {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ubg-suggest-game:hover {
    color: var(--ubg-accent);
}

.ubg-suggest-game:hover img {
    transform: scale(1.05);
    box-shadow: 0 0 0 2px var(--ubg-accent), 0 0 18px var(--ubg-accent-soft);
}

.ubg-suggest-discord {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 14px;
    border-radius: 10px;
    background: linear-gradient(135deg, var(--ubg-accent), var(--ubg-accent-2));
    /* !important overrides main.css:202 "a { color: #CCC }" */
    color: var(--ubg-accent-ink) !important;
    font-size: 13px;
    font-weight: 600;
}

.ubg-suggest-discord svg {
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
}

.ubg-suggest-discord:hover {
    filter: brightness(1.12);
}

/* Below the card's own width it spans the screen instead of sticking out.
   360px, not 480px: between 360 and 400 the fixed 330px card plus its 20px
   gutters already fits, and switching earlier left a needless 1-2px sliver. */
@media (max-width: 380px) {
    .ubg-suggest {
        right: 10px;
        left: 10px;
        bottom: 10px;
        width: auto;
        padding: 15px 15px 13px;
    }
    .ubg-suggest-games { gap: 8px; }
    .ubg-suggest-game { font-size: 10.5px; }
    .ubg-suggest-title { font-size: 14px; }
}

/* A short landscape window -- a phone turned sideways with the game open --
   has almost no vertical room. Drop the thumbnails there and keep the card to
   its title plus the Discord row rather than covering the game. */
@media (max-height: 460px) {
    .ubg-suggest {
        bottom: 10px;
        padding: 12px 14px 11px;
    }
    .ubg-suggest-games { display: none; }
    .ubg-suggest-sub { margin-bottom: 9px; }
}

@media (prefers-reduced-motion: reduce) {
    .ubg-suggest,
    .ubg-suggest-game img {
        transition: none !important;
    }
    .ubg-suggest.is-open,
    .ubg-suggest-arrow {
        animation: none !important;
    }
    .ubg-suggest-game:hover img {
        transform: none;
    }
}


/* ---------------------------------------------------------------------------
   11. MOBILE CATEGORY DROPDOWN  (<= 1300px)
   Rebuilt rather than patched. The theme's version is a full-bleed #1a1a1a
   slab of 44px rows with `color: #fff !important`, the category icons set to
   `display: none`, and the desktop pills' cyan neon box-shadow still glowing
   through underneath.

   Almost every declaration here needs !important, because main.css:2856-2866
   marks height, line-height, padding, border, background AND color as
   !important inside its own media query. That is also the light-mode bug the
   user hit: `color: #fff !important` beat an override that had none, so on
   the white panel every category name was white on white -- the rows looked
   empty. Each !important below is overriding that block.

   The breakpoint is 1300px, not 992px. main.css:2754 is where the header
   actually collapses to logo | search | hamburger and .nav becomes the
   absolutely-positioned dropdown -- a 992px override left everything between
   993px and 1300px showing the theme's original full-bleed black slab with
   right-aligned text and no icons, which is a window wide enough that people
   sit in it.

   jQuery drives this with slideToggle() (custom.js:154), which animates
   height and writes an inline `display`, so nothing here may set display on
   .nav itself.
   ------------------------------------------------------------------------ */

@media (max-width: 1300px) {

    /* --- the panel --- */
    .header-area .main-nav .nav {
        top: 64px;
        /* Inset with rounded corners instead of edge-to-edge: reads as a
           menu floating over the page rather than a slab welded to the
           header. */
        left: 10px;
        right: 10px;
        width: auto;
        padding: 8px;
        background-color: var(--ubg-panel);     /* main.css:2845 #1a1a1a */
        border: 1px solid var(--ubg-border);
        border-radius: 18px;
        box-shadow: 0 20px 48px var(--ubg-shadow), 0 2px 8px var(--ubg-shadow);
        backdrop-filter: blur(14px) saturate(140%);
        -webkit-backdrop-filter: blur(14px) saturate(140%);
        text-align: left;                       /* main.css:544 text-align: right */
    }

    .header-area .main-nav .nav li {
        width: 100%;
        display: block;
    }

    /* On a phone the panel spans the screen, but the breakpoint runs all the
       way to 1300px and a full-width sheet there leaves each row as an icon
       and two words stranded against a metre of empty space. Above phone
       width it becomes a real dropdown: capped, and anchored under the
       hamburger it was opened from. */
    @media (min-width: 620px) {
        .header-area .main-nav .nav {
            left: auto;
            right: 12px;
            width: 320px;
        }
    }

    /* --- the rows --- */
    .header-area .main-nav .nav li a {
        display: flex !important;
        /* The markup is "Action Games <img>", i.e. text first. row-reverse
           puts the icon on the left without touching 493 pages of HTML. */
        flex-direction: row-reverse;
        justify-content: flex-end;
        align-items: center;
        gap: 12px;
        height: 48px !important;
        line-height: 1 !important;
        padding: 0 14px !important;
        margin: 2px 0;
        border: none !important;
        border-radius: 12px;
        background: transparent !important;
        /* The fix for the white-on-white rows: main.css:2861 is #fff and
           !important, so this has to be too. */
        color: var(--ubg-text) !important;
        /* main.css:2157 puts a cyan neon glow on every .nav li a. Inside a
           panel that reads as smeared haze behind each row. */
        box-shadow: none !important;
        font-size: 13.5px;
        font-weight: 600;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        transition: background-color .16s ease, color .16s ease, padding-left .16s ease;
    }

    /* Icons back on. main.css:2871 hides them; they are the thing that makes
       the list scannable at a glance. main.css:236 sets "img { width: 100% }"
       globally, hence the explicit box. */
    .header-area .main-nav .nav li a img {
        display: block !important;
        width: 26px;
        height: 26px;
        min-width: 26px;
        object-fit: contain;
        border-radius: 6px;
    }

    .header-area .main-nav .nav li a:hover,
    .header-area .main-nav .nav li a:focus-visible {
        background-color: var(--ubg-fill-2) !important;   /* main.css:2867 */
        color: var(--ubg-accent) !important;
        padding-left: 18px !important;
    }

    .header-area .main-nav .nav li a:focus-visible {
        outline: 2px solid var(--ubg-accent);
        outline-offset: -2px;
    }

    /* Hairline between rows, skipped before the Discord button so it reads as
       a separate action rather than one more category. */
    .header-area .main-nav .nav li:not(:last-child):not(:nth-last-child(2))::after {
        content: "";
        display: block;
        height: 1px;
        margin: 0 14px;
        background: var(--ubg-border);
    }

    /* --- Discord --- */
    .header-area .main-nav .nav li:last-child {
        margin-top: 8px;
        padding-top: 8px;
        border-top: 1px solid var(--ubg-border);
    }

    .header-area .main-nav .nav li:last-child a {
        /* main.css:2172 gradient #7289da -> #a77bff plus a double neon glow.
           Discord's blurple is kept -- this row is a link to Discord, not a
           themed control -- but darkened to the shade where white passes
           across the WHOLE sweep, and the glow goes.
           The first attempt here used #5865f2 -> #7289da because white
           measures 4.61:1 on #5865f2; that is one stop, not the blend the
           text actually sits on. Over the gradient's midpoint it came out at
           3.94:1. Both stops now clear 4.5 on their own, so every point
           between them does too: 4.61 on #5865f2, 6.42 on #4752c4. */
        background: linear-gradient(135deg, #4752c4, #5865f2) !important;
        color: #ffffff !important;
        box-shadow: none !important;
        justify-content: center;
    }

    .header-area .main-nav .nav li:last-child a:hover {
        background: linear-gradient(135deg, #3c45a5, #4752c4) !important;  /* 6.42:1 */
        color: #ffffff !important;
        transform: none;                  /* main.css:2180 scale(1.07) */
        padding-left: 14px !important;
    }

    .header-area .main-nav .nav li:last-child::after {
        display: none;
    }

    /* The hamburger and the gear sit side by side; give them the same
       optical weight so neither disappears. */
    .header-area .main-nav .menu-trigger span,
    .header-area .main-nav .menu-trigger span:before,
    .header-area .main-nav .menu-trigger span:after {
        width: 24px;
    }
}

@media (max-width: 1300px) and (prefers-reduced-motion: reduce) {
    .header-area .main-nav .nav li a {
        transition: none !important;
    }
    .header-area .main-nav .nav li a:hover {
        padding-left: 14px !important;
    }
}


/* ---------------------------------------------------------------------------
   12. TEXT THAT WAS UNREADABLE IN THE DARK THEME TOO
   Found by compositing every element's real background (translucent layers
   and gradient midpoints included) and measuring, rather than by eye. Both
   of these are the theme's own colours, unrelated to the settings panel --
   they were simply never checked.
   ------------------------------------------------------------------------ */

/* Related-game link pills inside the description: main.css:2383 forces
   `color: #fff !important` over a #00f2fe -> #4facfe gradient. White on cyan
   is 1.83:1 at the midpoint and 1.39:1 at the bright end -- effectively
   invisible. The pill keeps its cyan; only the ink flips, which takes the
   worst point to 7.97:1. (Light mode already handled this in section 5, but
   dark never was.) */
.infor-first p a,
.infor-first p a:hover {
    color: #0b0d1a !important;      /* overrides main.css:2383 and :2392 */
}

/* "Join Discord" in the desktop nav: main.css:2172 puts white on a
   #7289da -> #a77bff gradient, 3.03-3.33:1 depending where you look. Same
   treatment as the mobile row -- blurple kept, darkened until white clears
   4.5 across the whole sweep. */
.header-area .main-nav .nav li:last-child a {
    background: linear-gradient(45deg, #4752c4, #5865f2);   /* worst 4.61:1 */
    border-color: #5865f2;
}

.header-area .main-nav .nav li:last-child a:hover {
    background: linear-gradient(45deg, #3c45a5, #4752c4);   /* worst 6.42:1 */
    border-color: #4752c4;
}


/* ---------------------------------------------------------------------------
   13. HOMEPAGE AND CATEGORY PAGES
   Everything below was found by compositing each element's real background --
   gradient midpoints included -- and measuring, on the homepage and on the
   category pages, in both themes. All but two of these are pre-existing
   problems in the site's own dark theme; they had simply never been checked.

   The four gradient headings keep their gradients untouched. For each one,
   darkening the background until white passed and flipping the ink to
   near-black were both tried: the ink flip scored higher in every case AND
   preserves the colours, which on these playful homepage blocks is the whole
   point. Figures below are the worst point across the whole sweep, not one
   stop.
   ------------------------------------------------------------------------ */

/* recently-played.css:38 -- white on #ff6600 -> #ffbb33 is 1.69:1. Orange is
   about the worst possible background for white text; this was effectively
   unreadable on the live site. */
#game-history-section .heading-section h4 {
    color: #1a0d00;                 /* 6.49:1 */
}

/* favorites.css:56 -- white on #ff4785 -> #b14bff, 3.23:1 */
.fav-head h4,
.fav-head h4 i {
    color: #1a0d00;                 /* 4.83:1 */
}

/* recently-played.css:98 -- white on #7289da -> #a77bff, 3.03:1 */
.heading-section.popular-games h4 {
    color: #1a0d00;                 /* 5.73:1 */
}

/* game-update.css:12 -- white on a three-stop #ff4757 / #e84393 / #7d5fff
   sweep, 3.34:1. Pure black rather than the near-black used above: the
   middle stop is bright enough that #1a0d00 did not clear 4.5. */
#game-news-btn,
#game-news-btn .game-news-btn-icon,
#game-news-btn .game-news-btn-text {
    color: #000000;                 /* 4.95:1 */
}

/* game-update.css:50 -- the unread badge, #e84393 on its own white pill. */
#game-news-badge {
    color: #c4176e;                 /* 5.68:1 on #fff */
}

/* main.css:2014 sets the About paragraphs to #3a5a95, a mid blue that was
   picked for a light page and never revisited: 2.77:1 on the dark theme.
   Kept blue, but a blue that works per theme. */
.content_homepage_main p {
    color: #9dbdf0;                 /* 9.88:1 on --ubg-bg */
}

:root[data-theme="light"] .content_homepage_main p {
    color: #334f83;                 /* 7.46:1 on --ubg-bg */
}

/* main.css:2291 -- the highlighted half of a category page's title
   ("Action Games on Unblocked Games 88") is neon cyan. Fine on the dark
   theme at 13.63:1, invisible on the light one at 1.27:1. Dark keeps the
   cyan and its glow; only light is changed. */
:root[data-theme="light"] .header-text .banner-title span {
    color: #00696f;                 /* 5.93:1 */
    text-shadow: none;              /* the cyan glow smears on a light page */
}

:root[data-theme="light"] .header-text .banner-title,
:root[data-theme="light"] .header-text .banner-subtitle {
    text-shadow: none;              /* main.css:2286 / :2299 orange glow */
}

/* The "Check New Games" popup and the favourites/history cards are panels in
   their own right; route them through the tokens so they follow the theme
   instead of staying dark on a light page. */
:root[data-theme="light"] #game-news-popup,
:root[data-theme="light"] .game-news-popup {
    background: var(--ubg-panel);
    border-color: var(--ubg-border);
    color: var(--ubg-text);
}

/* The ID is load-bearing: recently-played.css:138 is "#game-history-list
   .item" (1,1,0), so a 0,3,0 override loses no matter how many classes it
   stacks. The first attempt here used ".game-history-item .item" and left
   the cards dark -- which then put the newly-darkened title on a dark card
   at 1.22:1, worse than before. */
:root[data-theme="light"] #game-history-list .item {
    background-color: var(--ubg-card);
    border-color: var(--ubg-border);
    box-shadow: 0 2px 12px var(--ubg-shadow);
}

:root[data-theme="light"] .fav-card {
    background: var(--ubg-card);
    border-color: var(--ubg-border);
}

/* favorites.css:168 gives .fav-name a pale pink (#ffd9e6) that only works on
   the dark card behind it -- 1.29:1 once the card turns white. (The first
   version of this rule guessed ".fav-title", which does not exist, so it did
   nothing; the real class is .fav-name.) */
:root[data-theme="light"] .fav-card .fav-name,
:root[data-theme="light"] .fav-card:hover .fav-name,
:root[data-theme="light"] #game-history-list .recent-title {
    color: var(--ubg-text);
}

/* --- Light theme: the homepage's own panels ------------------------------
   The audit above only measures TEXT, so these passed it -- the cards inside
   them had already been lightened and their labels darkened. They still read
   as dark slabs dropped onto a light page, which is the part you see rather
   than measure. --------------------------------------------------------- */

:root[data-theme="light"] #favorites-section {
    /* favorites.css:9 gradient #1b1233 -> #241436 -> #140f26 */
    background: linear-gradient(145deg, var(--ubg-surface) 0%, var(--ubg-surface-2) 55%, var(--ubg-surface) 100%);
    border-color: var(--ubg-border);
    box-shadow: 0 10px 30px var(--ubg-shadow);
}

:root[data-theme="light"] #favorites-section::before {
    /* favorites.css:31 -- a pink radial bloom sized for a dark panel. On a
       light one it is just a stain, so it is turned off rather than retinted
       (the same call the theme's own blur blobs got in main.css). */
    background: none;
}

:root[data-theme="light"] #game-history-section {
    /* recently-played.css:4 gradient #232526 -> #414345 */
    background: linear-gradient(120deg, var(--ubg-surface) 0%, var(--ubg-surface-2) 100%);
    border-color: var(--ubg-border);
    box-shadow: 0 4px 24px var(--ubg-shadow);
}

:root[data-theme="light"] .fav-thumb {
    background: var(--ubg-surface-2);       /* favorites.css:153 #0f0b1c */
}

:root[data-theme="light"] .fav-remove {
    background: rgba(255, 255, 255, .86);   /* favorites.css:204 rgba(12,9,24,.82) */
    color: var(--ubg-text);
}

:root[data-theme="light"] #game-news-popup {
    /* game-update.css:91 gradient #201f33 -> #16151f */
    background: linear-gradient(180deg, var(--ubg-surface), var(--ubg-surface-2));
    border-color: var(--ubg-border);
    color: var(--ubg-text);
}

:root[data-theme="light"] #game-news-popup a {
    background: var(--ubg-fill);            /* game-update.css:166 #262538 */
    color: var(--ubg-text);
}

:root[data-theme="light"] #game-news-popup a:hover {
    background: var(--ubg-fill-2);
    color: var(--ubg-text);
}

/* Exposed by lightening #favorites-section above: favorites.css:79 gives the
   "2/12" counter a pale pink that only reads against the dark panel. */
:root[data-theme="light"] .fav-count {
    color: var(--ubg-text);
    background: var(--ubg-fill-2);
    border-color: var(--ubg-border);
}

/* ---------------------------------------------------------------------------
   14. LIGHT THEME: the neon glows
   The theme puts a double neon box-shadow on every pill heading. On the dark
   background that reads as a tasteful halo; on a light one it is a coloured
   smear bleeding several centimetres across the page.

   Every !important here is overriding a CSS ANIMATION, not just a rule.
   pulseBlue / pulseOrange / pulsePurple / favPulse / inforLinkPulse all set
   box-shadow inside their keyframes, and keyframes beat normal declarations
   no matter how specific -- only !important outranks them. The bounce and
   scale halves of those same animations are on other properties, so they
   keep running; just the glow stops.
   ------------------------------------------------------------------------ */

:root[data-theme="light"] .heading-section.category-games h4,
:root[data-theme="light"] .heading-section.new-games h4,
:root[data-theme="light"] .heading-section.popular-games h4,
:root[data-theme="light"] #game-history-section .heading-section h4,
:root[data-theme="light"] .fav-head h4 {
    /* main.css:2248, recently-played.css:69/99/40, favorites.css:59 */
    box-shadow: 0 4px 14px var(--ubg-shadow) !important;
}

:root[data-theme="light"] .infor-first p a,
:root[data-theme="light"] .infor-first p a:hover {
    /* main.css:2386 / :2394 / keyframes inforLinkPulse at :2404 */
    box-shadow: 0 2px 10px var(--ubg-shadow) !important;
}

:root[data-theme="light"] .header-area .main-nav .nav li:last-child a,
:root[data-theme="light"] .header-area .main-nav .nav li:last-child a:hover {
    box-shadow: 0 2px 10px var(--ubg-shadow) !important;   /* main.css:2175 / :2180 */
}

:root[data-theme="light"] .parent_frame,
:root[data-theme="light"] .poki-actionbar,
:root[data-theme="light"] .main_game .header-text .infor-first {
    box-shadow: 0 10px 30px var(--ubg-shadow) !important;  /* main.css:2335 cyan bloom */
}

/* ---------------------------------------------------------------------------
   15. LIGHT THEME: the search dropdown's contents
   Section 5.6 turned the panel itself white but stopped there, so everything
   inside kept the colours search.css picked for a dark panel: the game names
   are #e9eaf2 (1.1:1 on white -- the rows looked empty), the matched letters
   are neon cyan, and the category line and the "more results" footer are
   white at 40-50% alpha. Only the row under the cursor was readable, because
   main.css:206's generic a:hover happened to repaint it.
   ------------------------------------------------------------------------ */

:root[data-theme="light"] .result_search.search-panel a.search-item {
    color: var(--ubg-text);                     /* search.css:58 #e9eaf2 */
}

:root[data-theme="light"] .result_search.search-panel .search-item:hover,
:root[data-theme="light"] .result_search.search-panel .search-item.is-active {
    background: var(--ubg-fill-2);              /* search.css:73 white 8% */
    color: var(--ubg-text);
}

:root[data-theme="light"] .result_search.search-panel .search-item.is-active {
    box-shadow: inset 0 0 0 1px var(--ubg-accent);   /* search.css:77 cyan 40% */
}

:root[data-theme="light"] .result_search.search-panel .search-thumb {
    background: var(--ubg-fill);                /* search.css:85 white 6% */
}

:root[data-theme="light"] .search-name {
    color: var(--ubg-text);
}

:root[data-theme="light"] .search-name mark {
    /* search.css:110 #00f2fe -- 1.3:1 on white. The accent is the darkened
       pink in this theme, 4.93:1, and it is what marks a match everywhere
       else in the panel. */
    color: var(--ubg-accent);
    font-weight: 700;
}

:root[data-theme="light"] .search-cat {
    color: var(--ubg-text-mute);                /* search.css:118 white 40% */
}

:root[data-theme="light"] .search-msg,
:root[data-theme="light"] .search-more {
    color: var(--ubg-text-dim);                 /* search.css:127 white 50% */
}

:root[data-theme="light"] .search-more {
    border-top-color: var(--ubg-border);        /* search.css:132 white 7% */
}

/* ---------------------------------------------------------------------------
   16. GAME CARD LABELS + the search category line
   These only showed up once the grids were audited with real data in them.
   Earlier passes ran with Firebase stubbed out, so "New Games" and "Popular
   Games" rendered empty and there was nothing under the cards to measure --
   440 cards on a category page all carried the same invisible label.
   ------------------------------------------------------------------------ */

/* main.css:960 -- the "N Plays" badge is mint green, picked for the #27292a
   card. It scores 9.5:1 there and 1.54:1 once the card turns white. Dark
   keeps the mint; only light is darkened, and it stays green. */
:root[data-theme="light"] .most-popular .item span.playcount-badge {
    color: #17795a;                     /* 5.36:1 on the light card */
}

:root[data-theme="light"] .most-popular .item span.playcount-badge i {
    color: #17795a;                     /* main.css:968 #4ecca3 */
}

/* main.css:954 -- the card's secondary line ("Request", category names) is
   literally `burlywood`. 7.87:1 on the dark card, 1.86:1 on a white one.
   This is a DIFFERENT rule from the dead burlywood at main.css:497 that the
   comment in section 5.4 talks about; this one is live. */
:root[data-theme="light"] .most-popular .item span {
    color: #7a5c33;                     /* 6.17:1, same tan family */
}

/* search.css:118 -- the category line under each result is white at 40%,
   which is 3.83:1 on the dark dropdown and was never right there either.
   Fixed in BOTH themes rather than light only. */
.search-cat {
    color: rgba(255, 255, 255, 0.62);   /* 7.46:1 on the dark panel */
}

:root[data-theme="light"] .search-cat {
    color: rgba(20, 22, 43, 0.72);      /* 7.14:1 on the light panel */
}

/* The three tiles fade in when a card that was left open swaps its games at
   the next milestone. Without it the titles change between two blinks and
   look like a misread rather than an update. */
.ubg-suggest-games.is-swapped {
    animation: ubgSwapIn .32s ease-out;
}

@keyframes ubgSwapIn {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .ubg-suggest-games.is-swapped { animation: none; }
}

/* ---------------------------------------------------------------------------
   17. COMMENT CONTROLS
   comment.css colours every interactive element for a dark card: the reply /
   edit / delete / cancel buttons and the react counts are white at 45-70%
   alpha, which is 1.05-1.13:1 once the card is light -- the row of controls
   read as blank space. The blanket text rule in section 5.7 does not reach
   them because it only covers p / span / div, and these are <button>s.

   Two of these are wrong in BOTH themes and are fixed unprefixed: the time
   stamp (white 40% = 3.73:1 even on the dark card) and the Admin badge
   (white on the accent = 3.16:1).
   ------------------------------------------------------------------------ */

/* comment.css:119 -- 3.73:1 on the dark card, never checked. */
.comment-time {
    color: rgba(255, 255, 255, 0.62);       /* 7.46:1 */
}

:root[data-theme="light"] .comment-time,
:root[data-theme="light"] .comment-edited {
    color: var(--ubg-text-mute);
}

/* The badge sits on --ubg-accent, so it needs the accent's own ink. White was
   3.16:1 on the pink. */
.comment-badge {
    color: var(--ubg-accent-ink) !important;   /* overrides the inline style */
}

/* The pin control was --ubg-text-mute in both themes: 3.88:1 light,
   4.50:1 dark. Neither has any margin. */
.comment-pin {
    color: var(--ubg-text-dim);
}

/* ---- the light theme's text buttons ---- */
:root[data-theme="light"] .cmt-react-btn,
:root[data-theme="light"] .comment-reply-btn,
:root[data-theme="light"] .comment-edit,
:root[data-theme="light"] .btn-cmt-cancel,
:root[data-theme="light"] .cmt-cancel-name,
:root[data-theme="light"] .comment-empty,
:root[data-theme="light"] .cmt-name-msg {
    color: var(--ubg-text-dim);              /* 7.42:1 on the card */
}

:root[data-theme="light"] .cmt-react-btn:hover,
:root[data-theme="light"] .comment-edit:hover,
:root[data-theme="light"] .btn-cmt-cancel:hover {
    color: var(--ubg-text);
}

:root[data-theme="light"] .comment-reply-btn:hover,
:root[data-theme="light"] .comment-replies-toggle,
:root[data-theme="light"] .cmt-change-name {
    color: var(--ubg-accent-strong);         /* comment.css:110 / :578 neon cyan */
}

/* Delete keeps its warning red, darkened for a light card. */
:root[data-theme="light"] .comment-delete {
    color: #c62828;                          /* 5.04:1 */
}

:root[data-theme="light"] .comment-delete:hover,
:root[data-theme="light"] .cmt-name-msg.is-error {
    color: #a71c1c;                          /* 6.68:1 */
}

/* Liked / disliked keep their green and red; both were picked for a dark card
   and are 1.9-2.4:1 on a light one. */
:root[data-theme="light"] .cmt-react-btn.react-liked {
    color: #1b7a3d;                          /* 4.84:1 */
}

:root[data-theme="light"] .cmt-react-btn.react-disliked {
    color: #c62828;                          /* 5.04:1 */
}

/* ---- the edit and reply boxes ----
   Section 5.4 only reached .comment-form input/textarea. These two appear
   when Edit or Reply is pressed and kept white text on a light field. */
:root[data-theme="light"] .comment-edit-input,
:root[data-theme="light"] .comment-reply-input {
    background: var(--ubg-fill);
    border-color: var(--ubg-border);
    color: var(--ubg-text);
}

:root[data-theme="light"] .comment-edit-input::placeholder,
:root[data-theme="light"] .comment-reply-input::placeholder {
    color: var(--ubg-text-mute);
}

:root[data-theme="light"] .comment-edit-input:focus,
:root[data-theme="light"] .comment-reply-input:focus {
    border-color: var(--ubg-accent);
}
