html, body {
    margin: 0;
    padding: 0;
    font-family: 'Segoe UI', sans-serif;
    background-color: var(--bg-base);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    /* App-wide: text is not selectable. The chess UI has no copy/paste use
       case, and disabling selection avoids accidental highlights on tap/drag. */
    user-select: none;
    -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
}

/*
 * Override Bootstrap's `:root { scroll-behavior: smooth }` (specificity
 * (0,1,0), wins against `html`). The app has no in-page anchor links
 * that benefit from smooth scrolling, and the smooth behavior animates
 * the natural scroll-clamp that happens when enhanced-nav lands on a
 * page shorter than the viewport — making the on-load scroll-to-top
 * look gradual instead of instant.
 *
 * scrollbar-gutter: stable reserves the scrollbar gutter even on
 * pages that don't need a scrollbar, so the content width stays
 * identical between short pages (no scrollbar) and long pages
 * (scrollbar visible). Without it, navigating between, say, /privacy
 * and /about would re-flow the centered layout horizontally as the
 * scrollbar appears/disappears.
 *
 * scrollbar-width: thin + a muted scrollbar-color give Chrome/Edge
 * the same understated look Firefox has by default — a slim
 * dark-theme thumb that doesn't draw attention away from the chess
 * board. The track is transparent so the page background shows
 * through (matches the gutter on short pages, where stable reserves
 * the same width but never paints a track).
 */
:root {
    scroll-behavior: auto;
    scrollbar-gutter: stable;
    scrollbar-width: thin;
    scrollbar-color: var(--border-subtle) transparent;
}

/*
 * ---------- Full-screen app loader ----------
 *
 * Covers the entire viewport from the moment <body> paints until the
 * piece SVGs have finished loading + rasterizing. The theme bootstrap
 * script in App.razor's <head> applies `.theme-{name}` to <html> before
 * <body> paints, so `--bg-base` and `--accent-rgb` already resolve to
 * the user's chosen theme on first frame — no flash of unstyled loader.
 *
 * Hidden by adding `app-loaded` to <html> (documentElement, not body —
 * Blazor's enhanced-nav DOM patch can resync body's attributes from the
 * server-rendered response, which doesn't know about client-side state
 * and would briefly strip the class, flashing the loader during route
 * transitions on mobile). BoardRenderer triggers this
 * from three places:
 *   1. happy path — pieces loaded + rasterized
 *   2. error path — fetch failed; user gets a piece-less board instead
 *      of being stranded behind the loader
 *   3. safety-net timeout — defensive against fetches that neither
 *      resolve nor reject (rare browser hang on slow links)
 *
 * z-index 9999 keeps it above .board-container (with its frame halo),
 * the move-history panel, and the toggle button — every interactive
 * element is gated behind a piece-ready board.
 */
#app-loader {
    position: fixed;
    top: 0;
    /* `scrollbar-gutter: stable` on :root shrinks the initial containing
       block, so 100% / 100vw / 100dvw / 100lvw / 100svw all resolve to
       viewport-minus-gutter — none of them cover the full viewport.
       On the board page on mobile, the board's frame-halo glow leaks
       through that uncovered strip and flashes at the right edge.
       Overdraw 10 px each side via calc + negative left so the loader
       always covers the full viewport, gutter or no gutter. */
    left: -10px;
    width: calc(100vw + 20px);
    height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 28px;
    background: var(--bg-base);
    z-index: 9999;
    /* Defensive: even if a parent or browser quirk briefly produces an
       inline-block-style natural-flow layout before fixed positioning
       resolves, force the loader to clip to its declared box rather
       than letting overflowing content (the orb's huge glow shadow)
       appear at the edges of the viewport. */
    overflow: hidden;
    opacity: 1;
    transition: opacity 0.4s ease-out;
    pointer-events: auto;
}

.app-loader-text {
    color: var(--text-muted);
    font-size: 14px;
    letter-spacing: 0.06em;
    text-shadow: 0 0 12px rgba(var(--accent-rgb), 0.25);
}

html.app-loaded #app-loader {
    opacity: 0;
    pointer-events: none;
}

.app-loader-orb {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: radial-gradient(circle at 35% 35%,
                                var(--accent) 0%,
                                rgba(var(--accent-rgb), 0.45) 55%,
                                transparent 78%);
    box-shadow:
        0 0 16px 4px rgba(var(--accent-rgb), 0.65),
        0 0 48px 12px rgba(var(--accent-rgb), 0.35),
        0 0 96px 24px rgba(var(--accent-rgb), 0.18);
    animation: app-loader-pulse 1.4s ease-in-out infinite;
}

@keyframes app-loader-pulse {
    0%, 100% { transform: scale(1);    opacity: 0.72; }
    50%      { transform: scale(1.18); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .app-loader-orb { animation: none; opacity: 0.9; }
}

/*
 * ---------- Theme palettes ----------
 *
 * Every CSS variable consumed below this comment is generated from the
 * C# ITheme implementations (see src/Oxbow.Chess.Web/Theming/). The
 * .theme-classic and .theme-neon rule blocks are emitted by
 * ThemeCssRenderer and inlined into the page <head> by App.razor — the
 * single source of truth lives in C#, not here.
 *
 * The active theme is set by a class on <html> (theme-classic or
 * theme-neon) by the inline script in App.razor (reading from
 * localStorage 'proZero.theme', defaulting to 'classic').
 *
 * Token taxonomy:
 *   bg-*               — surface backgrounds
 *   accent[-bright/-deep/-halo] — accent shades + alpha-mixed halo
 *   text-*             — typographic shades
 *   border-*           — subtle dividers and hairlines
 *   sq-{light|dark}-*  — board-square state vars (read by boardRenderer.js)
 *   mv-{light|dark}-*  — last-move overlay per square
 *   frame-*            — board frame chrome
 *   backdrop / glow-* / brand-* / logo-filter / panel-shadow — page chrome
 */

.board-container {
    display: inline-block;
    position: relative;
    border-radius: 2px;
    /* Frame chrome (atmospheric halo + drop shadow + any solid spread
       rings) comes from --frame-box-shadow, emitted per theme by C#. */
    box-shadow: var(--frame-box-shadow);
    /* Hidden until JS sizes the canvas. `visibility` (not display)
       prevents the 0×0 starting canvas from leaking its frame-halo
       box-shadow as a tiny ring before sizing completes — at 0×0 the
       shadow would render at viewport center. Layered on top is a
       0→1 opacity transition that gives the board its own fade-in
       once `.ready` lands, so it joins the page entrance instead of
       snapping in after .game-area's fade has already settled. */
    visibility: hidden;
    opacity: 0;
    transition: opacity 0.4s ease-in;
}

.board-container.ready {
    visibility: visible;
    opacity: 1;
}

/* Per-theme straddle border drawn by ::before. inset: -0.5px positions
   the pseudo's outer edge 0.5 px outside the container; the border then
   renders from the outer edge inward, ending 0.5 px inside — same
   straddling geometry as the per-cell accent ring. Width / colour come
   from C# (--frame-border-*); themes that don't want a straddle line
   set width to 0 (classic does, since its frame is entirely the
   box-shadow stack). */
.board-container::before {
    content: '';
    position: absolute;
    inset: -0.5px;
    border: var(--frame-border-width) solid var(--frame-border-color);
    border-radius: 2px;
    pointer-events: none;
}

/* ============================================================
   Game-area grid — see docs/README_layout_concept.md for the layout cases.
   See also boardRenderer.js _layout / _recalculateSize for the
   matching JS thresholds.
   ============================================================ */

.game-area {
    /*
     * 3-column grid: the left spacer mirrors the right side-panel so the
     * board stays centered regardless of panel visibility (Case 1).
     *
     * --side-width default = 228 px = panel (192) + gap (9) + toggle (22)
     * + 5 px column slack. The slack is intentional: in clip-overflow mode
     * (Case 3/4) it combines with the reduced main padding-right (4 px) to
     * land the toggle 9 px from the viewport-right edge — matching the
     * visual board↔panel and panel↔toggle gap rhythm.
     */
    display: grid;
    grid-template-columns: var(--side-width) auto var(--side-width);
    align-items: stretch;
    gap: 12px;
    outline: none;
    --side-width: 228px;
}

/* .side-spacer has no styles of its own — it's an empty grid cell mirroring
   the right panel's width so the board stays centered. */

/* Panel hidden: shrink mirrors to the toggle's footprint so the board still
   centers (Case 1/2/3/4 closed). */
.game-area.panel-hidden {
    --side-width: 8px;
}

/* Compact mode (panel visible + viewport too narrow for Case 1): drop the
   left spacer so the board sits adjacent to the panel. */
.game-area.compact {
    grid-template-columns: auto var(--side-width);
}

    .game-area.compact .side-spacer {
        display: none;
    }

/* ============================================================
   Optical-centering corrections
   The mathematical center of the grid isn't always the visual
   center, because trailing toggle space and column slack read
   as empty padding. These two rules fix the per-case offsets.
   ============================================================ */

/*
 * Case 2 — compact mode without clip-overflow: shrink the right column to
 * the panel's outer width (192 px) so the side-panel's trailing gap+toggle
 * overflows the column instead of consuming centering space. The grid's
 * CSS box now equals the visual mass (board + gap + panel), so flex-centering
 * it puts the visual mass at viewport center; the toggle hangs off-right.
 */
body:not(.clip-overflow) .game-area.compact {
    grid-template-columns: auto 192px;
}

/*
 * Case 3/4 — anchor the layout to viewport-right and trim main's right
 * padding so the toggle ends up 9 px from the viewport-right edge:
 *   5 px column slack + 4 px main padding-right = 9 px.
 * Matches the visual board↔panel gap (gridGap 12 − 3 px gold-ring overhang
 * = 9) and the panel↔toggle gap (sidePanelGap 9), so the button reads as
 * optically symmetric within the trailing margin.
 *
 * Scoped via :has(.game-area) so this rule applies only on the game page.
 * Without the scope, body.clip-overflow lingering from a prior game session
 * would anchor static pages (Impressum / Privacy / Contact) to the right
 * edge of main and break their centered max-width layout.
 */
body.clip-overflow main:has(.game-area) {
    justify-content: flex-end;
    padding-right: 4px;
}

/*
 * Narrow-viewport mode (Case 4): opening the panel would visually clip
 * the toggle. Pin the history-toggle to viewport-right so [+] (panel
 * closed) and [-] (panel open) share the same X — same gesture target,
 * same screen position regardless of panel state.
 *
 * `right: 15px` is fixed; both states use this pinned offset so toggling
 * never moves the button. (The natural compact-open offset is 9 px — see
 * the clip-overflow rule above — but in narrow-viewport mode we always
 * render the pinned position, so the divergence is never visible.)
 *
 * `top` reads --board-top, set by JS from board-container's rect each
 * resize so the toggle vertically tracks the board across viewport-height
 * changes (and across panel toggles, where the layout shifts).
 */
body.narrow-viewport .history-toggle {
    position: fixed;
    right: 15px;
    top: var(--board-top, 0);
    z-index: 5;
}

/*
 * Left-edge content fade — a band of body-color along the left viewport
 * edge. The gradient color matches the body background exactly, so the
 * band itself is invisible against an empty background; what's visible is
 * its effect on content passing under it.
 *
 * Width is page-type specific:
 *   · game page (body:has(.game-area)) — 32 px, the original mask for
 *     board clipping in Case 3/4. A narrow band keeps the fade close to
 *     the edge so it stays mostly clear of the visible board (board's
 *     gold ring sits ~10–25 px from the viewport edge depending on case).
 *   · static pages (body:has(.content-page)) — 80 px, wider so the tail
 *     of the gradient overlaps the leading characters of text and softens
 *     them into the body color.
 *
 * Pointer-events: none keeps clicks passing through.
 */
body::before {
    content: '';
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
    background: linear-gradient(to right, var(--bg-base) 0%, rgba(var(--bg-base-rgb), 0.85) 40%, transparent 100%);
    pointer-events: none;
    z-index: 10;
}

body:has(.game-area)::before {
    width: 32px;
}

body:has(.content-page)::before {
    width: 88px;
}

.side-panel {
    display: flex;
    align-items: stretch;
    /* 9px so the visual gap panel→[-] matches the board→[+] gap. The
       board has a 3px gold box-shadow ring that "eats" into its 12px
       grid gap; the history panel has only a 1px border, so it needs
       a 3px-smaller flex gap to read the same. */
    gap: 9px;
    justify-self: start;
}

.history-toggle {
    width: 22px;
    height: 22px;
    padding: 0;
    margin: 0;
    align-self: flex-start;
    background: transparent;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    line-height: 1;
    transition: color 0.15s ease, transform 0.15s ease;
    /* Center the inline SVG icon. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

    .history-toggle:hover {
        color: var(--accent);
        transform: scale(1.2);
    }

    .history-toggle:focus {
        outline: none;
    }

canvas {
    display: block;
    /* Reserve horizontal gestures for our swipe-to-toggle-history; let the
       browser keep vertical page scroll. */
    touch-action: pan-y;
    /* Placeholder dimensions, set from --board-size by the inline script in
       App.razor. Reserves the grid column's final width before paint so JS
       init doesn't trigger a 0×0 → full-size reflow. boardRenderer overrides
       these with the exact pixel size via inline style.width/height once
       _recalculateSize runs (inline style wins over this rule). */
    width: var(--board-size, 360px);
    height: var(--board-size, 360px);
}

/* ============================================================
   Phone (touch-primary, narrow viewport) — the chess board IS
   the content; side panel + toggle just steal horizontal space.
   Hide them when the panel is closed so the board can fill the
   viewport. Swipe (window-level) still toggles the panel.

   The (pointer: coarse) and (hover: none) clauses are what
   distinguishes a real phone from a PC window resized < 600 px
   — touch-primary devices have a coarse pointer and no hover;
   mouse-driven devices match neither. On a narrow PC window the
   regular layout (with toggle) keeps applying.
   ============================================================ */

@media (max-width: 600px) and (pointer: coarse) and (hover: none) {
    .history-toggle {
        display: none;
    }

    /* Panel hidden: side spacer + side-panel CSS-hidden, single column. */
    .game-area.panel-hidden > .side-spacer,
    .game-area.panel-hidden > .side-panel {
        display: none;
    }

    .game-area.panel-hidden {
        grid-template-columns: 1fr;
    }

    /* Panel open: same Case-3 behavior as desktop — compact 2-col grid,
       clip-overflow anchors right, board clips left, panel visible at the
       right edge. The JS _computeBoardSize phone branch fires regardless
       of panel state, so the board keeps its panel-hidden size when the
       panel opens (footer Y stays put). */

    /* Horizontal inset so the board (and its gold ring) keeps ~10 px
       breathing room from the viewport edge. 0.75rem = 12 px each side; the
       JS width calc in _computeBoardSize uses the matching 12 px. Square-
       size flooring steps in 4 px-per-side jumps, so 12 px main padding
       lands the visible ring-to-edge gap at ~12 px on a 375 px phone. */
    main {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
    }
}

/* ---------- Page fade-in (enhanced navigation only) ----------

   CSS animation on the page wrappers so each user-initiated navigation
   plays a fresh fade-in. Gated behind `.nav-fade`, which is applied by
   App.razor's `enhancedload` listener AFTER Blazor's enhanced-nav DOM
   patch — never on initial load and never on the circuit-hydration
   remount. Without that gate, the animation would also run when
   Blazor's interactive-server takeover re-mounts the prerendered
   <Routes> subtree, and the user sees a visible second fade-in on
   non-board pages right after the loader reveals the (already
   fully-opaque) page. */

.game-area.nav-fade, .content-page.nav-fade {
    animation: page-fade-in 0.4s ease-in;
}

@keyframes page-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

/* ---------- Static content pages (Impressum / Privacy / Contact) ---------- */

.content-page {
    max-width: 640px;
    margin: 0 auto;
    /* Horizontal padding sits text inside the tail of the 88 px left-edge
       fade band: text starts at main-pad (8) + 42 = 50 px, leaving ~38 px
       of overlap with the fade so the leading characters still dissolve
       softly into the body color. */
    padding: 1rem 1.5rem 1rem 2.625rem;
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.6;
}

    /* Back-to-the-board hint above the page title. Plain centered text
       link — no background, no padding, just muted type that shifts to
       accent on hover.
       Negative left margin compensates for the .content-page's asymmetric
       padding (2.625 rem left vs 1.5 rem right, to overlap the left-edge
       fade band), so the link sits on the article's true horizontal
       centre rather than the off-centre text column.
       Negative top margin tightens the gap to the header: header bottom-
       padding (1.5 rem) + main top-padding (1.5 rem) = 3 rem of intrinsic
       space; pulling the link up by 2 rem leaves ~1 rem visible, enough
       to read as separation from the copyright line without the prior
       4-rem chasm. */
    .content-page .back-link {
        margin: -2rem 0 1.5rem -1.125rem;
        text-align: center;
        font-size: 0.85rem;
    }

        .content-page .back-link a {
            color: var(--text-muted);
            text-decoration: none;
            transition: color 0.2s ease;
        }

            .content-page .back-link a:hover {
                color: var(--accent);
                text-decoration: none;
            }

    .content-page h1 {
        margin: 0 0 1rem;
        color: var(--accent);
        font-size: 2rem;
    }

    .content-page h2 {
        margin: 1.6rem 0 0.4rem;
        color: var(--accent);
        font-size: 1.1rem;
        font-weight: 600;
        letter-spacing: 0.02em;
    }

    .content-page p {
        margin: 0 0 0.8rem;
    }

    .content-page a {
        color: var(--accent);
        text-decoration: none;
    }

        .content-page a:hover {
            text-decoration: underline;
        }

/* ---------- Settings page (theme picker) ----------

   Two click-targets sit side-by-side, each previewing the theme it
   represents (board-square swatch + name). The currently-active theme
   gets a glowing cyan/gold border so the choice is obvious. */

.theme-picker {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 0.6rem;
}

.theme-option {
    background: var(--bg-card);
    border: 1px solid var(--border-subtle);
    border-radius: 6px;
    padding: 0.7rem 0.9rem 0.7rem 0.7rem;
    color: var(--text-primary);
    font-family: inherit;
    font-size: 0.95rem;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 0.7rem;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

    .theme-option:hover {
        border-color: var(--accent);
    }

    .theme-option.active {
        border-color: var(--accent);
        box-shadow:
            0 0 0 1px var(--accent),
            0 0 18px rgba(var(--accent-rgb), 0.45);
    }

    .theme-option:focus-visible {
        outline: none;
        border-color: var(--accent);
    }

    /* Non-active option fades to greyscale + dimmed text so the page's
       active theme is the only colour story on screen — without this the
       inactive swatch's hues mix with the page chrome (warm wood next to
       the neon chrome, or cool blue next to the classic chrome). Hover
       restores full colour as a "preview" of what picking it would do. */
    .theme-option:not(.active) .swatch {
        filter: grayscale(1);
        opacity: 0.55;
        transition: filter 0.15s ease, opacity 0.15s ease;
    }

    .theme-option:not(.active) .theme-name {
        color: var(--text-muted);
        transition: color 0.15s ease;
    }

    .theme-option:not(.active):hover .swatch,
    .theme-option:not(.active):focus-visible .swatch {
        filter: grayscale(0);
        opacity: 1;
    }

    .theme-option:not(.active):hover .theme-name,
    .theme-option:not(.active):focus-visible .theme-name {
        color: var(--text-primary);
    }

/* Swatch — a 2-square mini-board preview using the theme's actual
   square colours (literal hex; CSS vars on the option element follow
   the *page* theme, but each swatch wants to show its own theme). */
.swatch {
    display: inline-grid;
    grid-template-columns: 18px 18px;
    grid-template-rows: 18px;
    border-radius: 3px;
    overflow: hidden;
    flex-shrink: 0;
}

    .swatch .swatch-light,
    .swatch .swatch-dark {
        display: block;
    }

    /* Per-theme swatch background colours are emitted from C# (see
       ThemeCssRenderer.AppendTheme) so adding a theme picks up its
       preview colours automatically. */

/* ---------- Resume / Reset dialog ----------

   Modal overlay shown when ChessBoard restores a snapshot older than its
   ResumePromptThreshold. Sits inside .game-area (position:fixed so it
   covers the viewport regardless of .game-area's grid layout). The board
   keeps rendering underneath so the user can see what they're choosing
   between. */

.resume-dialog-backdrop {
    position: fixed;
    inset: 0;
    background: var(--backdrop);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
    animation: resume-dialog-fade-in 0.18s ease-out;
}

.resume-dialog {
    /* Clean card: thin gold top stripe as the only chrome, soft rounded
       corners, deep ambient shadow for elevation. Drops the board-frame
       echo in favour of a calmer, more modern modal silhouette. */
    background: var(--bg-card-modal);
    border: 1px solid var(--border-subtle);
    border-top: 2px solid var(--accent);
    border-radius: 8px;
    box-shadow:
        0 0 0 1px rgba(var(--accent-rgb), 0.18),
        0 0 32px rgba(var(--accent-rgb), 0.25),
        0 12px 32px rgba(var(--overlay-shadow-rgb), 0.6);
    padding: 1.5rem 1.75rem 1.3rem;
    max-width: 380px;
    width: calc(100% - 2rem);
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.55;
}

    .resume-dialog h2 {
        margin: 0 0 0.6rem;
        color: var(--accent);
        font-size: 1.05rem;
        font-weight: 600;
        letter-spacing: 0.02em;
    }

    .resume-dialog p {
        margin: 0 0 1.1rem;
    }

.resume-dialog-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
}

.resume-dialog-button {
    border: 1px solid transparent;
    border-radius: 4px;
    padding: 0.4rem 0.9rem;
    font-size: 0.85rem;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}

    .resume-dialog-button.primary {
        background: var(--accent);
        color: var(--bg-base);
        font-weight: 600;
        box-shadow: 0 0 12px rgba(var(--accent-rgb), 0.55);
    }

        .resume-dialog-button.primary:hover {
            background: var(--accent-bright);
            box-shadow: 0 0 18px rgba(var(--accent-bright-rgb), 0.75);
        }

    .resume-dialog-button.secondary {
        background: transparent;
        color: var(--text-secondary);
        border-color: rgba(var(--text-secondary-rgb), 0.4);
    }

        .resume-dialog-button.secondary:hover {
            color: var(--text-primary);
            border-color: rgba(var(--text-secondary-rgb), 0.65);
        }

    /* Focus indicator: darken instead of an outline ring. Keyboard users
       still get a visible cue, the dialog stays clean of extra chrome. */
    .resume-dialog-button:focus,
    .resume-dialog-button:focus-visible {
        outline: none;
    }

        .resume-dialog-button.primary:focus-visible {
            background: var(--accent-deep);
        }

        .resume-dialog-button.secondary:focus-visible {
            background: rgba(var(--focus-background-rgb), 0.06);
            color: var(--text-primary);
            border-color: rgba(var(--text-secondary-rgb), 0.65);
        }

@keyframes resume-dialog-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}

#blazor-error-ui {
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(var(--overlay-shadow-rgb), 0.2);
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
