/* =========================================
   IN-Vest — Consolidated Stylesheet
   ========================================= */

/* Base */
html {
    /* Keep anchored/section content clear of the floating navbar */
    scroll-padding-top: 5rem;
    scroll-behavior: smooth;
}
body {
    font-family: 'Inter', sans-serif;
    background-color: #f8fafc;
    overflow-x: hidden;
    min-height: 100vh;
}

/* View Toggling */
.view-section {
    display: none;
    animation: fadeIn 0.4s ease-in-out;
}
.view-section.active {
    display: block;
}

/* Animations */
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

@keyframes slideIn {
    from { opacity: 0; transform: translateX(100%); }
    to { opacity: 1; transform: translateX(0); }
}

.animate-fade-in {
    animation: fadeIn 0.3s ease-out;
}

.animate-slide-in {
    animation: slideIn 0.3s ease-out forwards;
}

/* =========================================
   Landing page hero background
   -----------------------------------------
   To change the landing page background image,
   drop your picture at:
     /public/landing-background.jpg
   (or /public/landing-background.png).
   Replace the file to swap the background.
   If the image file is missing, the navy
   fallback color below is used automatically.
   ========================================= */
.landing-hero {
    background-color: #0f172a; /* navy fallback (current blue) */
    background-image: url('/landing-background.jpg');
    background-size: cover;    /* proportional, never stretched */
    background-position: center;
    background-repeat: no-repeat;
}

/* Readability layer: a subtle navy scrim over the optional background
   photo keeps the landing hero text/buttons readable. It is invisible
   over the solid navy fallback, so the no-image case looks unchanged. */
.landing-hero::before {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(15, 23, 42, 0.6);
    pointer-events: none;
}

/* Custom Scrollbar */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: #f1f1f1; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }

/* Glass & Card Effects */
.glass-card {
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(226, 232, 240, 0.8);
}

.hover-lift {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.hover-lift:hover {
    transform: translateY(-4px);
    box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
}

/* Timeline */
.timeline-step {
    position: relative;
    padding-left: 2rem;
    border-left: 2px solid #0ea5e9;
    padding-bottom: 2rem;
}
.timeline-step::before {
    content: '';
    position: absolute;
    left: -9px;
    top: 0;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: #0ea5e9;
    border: 4px solid #fff;
}
.timeline-step:last-child {
    border-left-color: transparent;
}

/* Toast Notifications */
#toast-container {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 9999;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.toast {
    background: #1e293b;
    color: white;
    padding: 1rem;
    border-radius: 0.5rem;
    box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
    display: flex;
    align-items: center;
    gap: 12px;
    animation: slideIn 0.3s ease-out;
    max-width: 90vw;
}

/* Responsive tweaks below the sm/md Tailwind breakpoints.

   This block used to also carry a hard-coded 260px landing-hero logo, plus
   the hero's own copy sizes and button padding, in two copies of a
   max-width:480px query. All four declarations were !important, which is why
   they beat the --sc-hero-logo scale at the bottom of this file: at every
   width under 640px the hero logo was pinned to 260px, i.e. *larger* than the
   212px it uses on a 1440px desktop, so the logo grew as the screen shrank
   and pushed the slogan, description and buttons down a hero that has a
   fixed min-height.

   The hero's type and button padding already step responsively in the markup
   (text-sm sm:text-base md:text-lg, px-6 sm:px-8 / py-2 sm:py-3) and its logo
   is driven by the --sc-hero-logo scale, so none of it is declared here any
   more. One system, no !important, no duplicate query. */
@media (max-width: 640px) {
    .view-section {
        font-size: 16px;
    }

    .toast {
        right: 10px;
        left: 10px;
        bottom: 10px;
    }
    .glass-card input,
    .glass-card select {
        font-size: 16px;
    }
}

/* Long numeric values must wrap instead of overflowing small screens */
.break-all {
    word-break: break-all;
    overflow-wrap: anywhere;
}

/* Admin stat cards stack cleanly on small screens */
@media (max-width: 640px) {
    .grid-cols-2 > div {
        min-width: 0;
    }
}

/* Inputs with password-visibility toggles: prevent iOS auto-zoom on focus */
.relative input[type="password"],
.relative input[type="text"] {
    font-size: 16px;
}
@media (max-width: 640px) {
    .relative input {
        font-size: 16px;
    }
}

/* Floating navbar: tighten margins on very small screens so it never
   forces horizontal scrolling, and keep the hero clear of the bar. */
@media (max-width: 400px) {
    nav.sticky {
        border-radius: 0.75rem;
    }
    nav.sticky .max-w-7xl {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
    }
}

/* Quick Response Desk: comfortable mobile textareas */
#form-quick-response textarea {
    min-height: 7rem;
}

/* CVP figures can contain decimals (e.g. 7.5, 2.55) — allow wrapping */
#dash-cvp,
#cvp-ref-val,
#cvp-mine-val,
#cvp-signup-val,
#wallet-page-bal,
#dash-wallet {
    overflow-wrap: anywhere;
}

/* =========================================
   Dashboard carousel
   -----------------------------------------
   Plain CSS (no carousel library). The track
   is a flex row translated horizontally;
   the viewport clips it so the page can
   never scroll sideways.
   ========================================= */
.carousel {
    position: relative;
    width: 100%;
    max-width: 100%;
    min-width: 0;
}

.carousel-viewport {
    position: relative;
    width: 100%;
    overflow: hidden;
    border-radius: 1rem;
    background: #f1f5f9;
}

.carousel-track {
    display: flex;
    align-items: stretch;
    width: 100%;
    will-change: transform;
    transition: transform 0.45s ease;
}

.carousel-slide {
    flex: 0 0 100%;
    width: 100%;
    min-width: 0;
    position: relative;
    display: block;
    text-decoration: none;
    background: #f1f5f9;
}

/* 16:9 everywhere, a little wider on large screens. object-contain keeps the
   admin's artwork whole — never stretched, never cropped. */
.carousel-frame {
    position: relative;
    width: 100%;
    /* Fallback height for browsers without aspect-ratio support */
    min-height: 180px;
    aspect-ratio: 16 / 9;
    max-height: 60vh;
    background: #f1f5f9;
    display: block;
}

.carousel-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
    display: block;
    background: #f1f5f9;
}

.carousel-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 2.5rem 1rem 0.85rem;
    background: linear-gradient(to top, rgba(15, 23, 42, 0.88) 0%, rgba(15, 23, 42, 0.55) 55%, rgba(15, 23, 42, 0) 100%);
    pointer-events: none;
}

.carousel-caption-title {
    color: #fff;
    font-weight: 700;
    font-size: 0.95rem;
    line-height: 1.3;
    overflow-wrap: anywhere;
}

.carousel-caption-desc {
    color: rgba(226, 232, 240, 0.92);
    font-size: 0.75rem;
    line-height: 1.4;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Prev/next + dots sit above the slide link so taps never trigger a redirect */
.carousel-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
    width: 2.25rem;
    height: 2.25rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    background: rgba(15, 23, 42, 0.55);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, 0.35);
    transition: background 0.2s ease;
}

.carousel-btn:hover {
    background: rgba(15, 23, 42, 0.8);
}

.carousel-btn:focus-visible {
    outline: 2px solid #38bdf8;
    outline-offset: 2px;
}

.carousel-btn:disabled {
    opacity: 0.35;
    cursor: default;
}

.carousel-prev { left: 0.5rem; }
.carousel-next { right: 0.5rem; }

.carousel-dots {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0.5rem;
    z-index: 5;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.375rem;
    padding: 0 2rem;
    flex-wrap: wrap;
}

.carousel-dot {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 9999px;
    background: rgba(255, 255, 255, 0.55);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.5);
    transition: width 0.2s ease, background 0.2s ease;
}

.carousel-dot.active {
    width: 1.25rem;
    background: #38bdf8;
}

.carousel-dot:focus-visible {
    outline: 2px solid #38bdf8;
    outline-offset: 2px;
}

/* Slides that are not the active one are pulled out of the tab order */
.carousel-slide[data-active="false"] {
    visibility: hidden;
}

.carousel-track {
    min-width: 0;
}

@media (max-width: 640px) {
    .carousel-frame {
        min-height: 140px;
        aspect-ratio: 16 / 10;
    }
    .carousel-btn {
        width: 2rem;
        height: 2rem;
    }
    .carousel-caption {
        padding: 2rem 0.75rem 1.5rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .carousel-track {
        transition: none;
    }
}

/* =========================================
   Collapsible left sidebar
   -----------------------------------------
   Below 1024px nothing here applies: the
   floating top navbar and the hamburger
   menu behave exactly as before. From
   1024px the shell becomes a flex row, so
   the nav is a real sibling column and can
   never overlap the content.
   ========================================= */
.app-shell {
    --sb-w: 16rem;
    --sb-w-collapsed: 4.75rem;
}

@media (min-width: 1024px) {
    .app-shell {
        display: flex;
        align-items: flex-start;
        min-height: 100vh;
        flex-direction: row;
    }

    /* The rail width is declared in full, not just as a max-width:
       flex: 0 0 pins flex-basis and sets flex-shrink to 0, so a wide
       flex sibling can never squeeze the rail (which is what made labels
       wrap one glyph per line), and min-width keeps the pinned value even
       if a flex-basis is ever ignored. */
    .app-shell > nav {
        width: var(--sb-w);
        min-width: var(--sb-w);
        max-width: var(--sb-w);
        flex: 0 0 var(--sb-w);
        height: 100vh;
        position: sticky;
        top: 0;
        transition: width 0.25s ease, min-width 0.25s ease,
            max-width 0.25s ease, flex-basis 0.25s ease;
    }

    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell)> nav {
        width: var(--sb-w-collapsed);
        min-width: var(--sb-w-collapsed);
        max-width: var(--sb-w-collapsed);
        flex-basis: var(--sb-w-collapsed);
    }

    /* The rail is a column: brand on top, links underneath.
       #nav-row is a horizontal row for the tablet/mobile navbar, and at
       1024px it was still a row here - so the links were squeezed into
       whatever width was left beside the 144px brand (48px, i.e. a 24px
       content box after padding) and every label overflowed the rail.
       Turning the row into a column gives #nav-links the full rail width. */
    .app-shell #nav-row {
        flex-direction: column;
        align-items: stretch;
        justify-content: flex-start;
    }

    .app-shell #nav-brand {
        flex: 0 0 auto;
    }

    /* Sidebar links: icon + label in a row when expanded */
    .app-shell #nav-links a {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        padding: 0.625rem 0.75rem;
        border-radius: 0.5rem;
        border-left: 2px solid transparent;
        width: 100%;
        text-align: left;
        color: #cbd5e1;
    }

    .app-shell #nav-links a:hover {
        background: #1e293b;
        color: #38bdf8;
    }

    .app-shell #nav-links a:focus-visible {
        outline: 2px solid #38bdf8;
        outline-offset: 2px;
    }

    .app-shell #nav-links a[aria-current="page"] {
        background: rgba(56, 189, 248, 0.16);
        border-left-color: #38bdf8;
        color: #7dd3fc;
    }

    /* The guest "Register" call to action keeps its filled look */
    .app-shell #nav-links a.bg-sky-600 {
        background: #0284c7;
        color: #fff;
    }

    .app-shell #nav-links a.bg-sky-600:hover {
        background: #0ea5e9;
        color: #fff;
    }

    .app-shell #nav-links a.bg-sky-600[aria-current="page"] {
        background: #0ea5e9;
        color: #fff;
    }

    .app-shell #nav-links a > i {
        width: 1.25rem;
        flex: 0 0 1.25rem;
        text-align: center;
    }

    /* Anti-fragmentation guarantees for the rail.
       1) nowrap: a label can never break into vertical one-glyph strips
          no matter how narrow its box gets - the exact reported symptom.
       2) overflow: hidden auto replaces Tailwind's lg:overflow-y-auto.
          overflow-y:auto alone silently computes overflow-x to auto, which
          turned the list into a horizontal scroll container able to cut a
          label off mid-glyph. "hidden auto" keeps the vertical scroll and
          forbids horizontal scrolling.
       Specificity (1,2,0) / (1,1,0) beats the Tailwind utilities, and
       .app-shell.sb-public #nav-links still wins back overflow: visible
       for the auth top bar, so these rules apply to the rail only. */
    .app-shell #nav-links .sb-label {
        white-space: nowrap;
    }

    .app-shell #nav-links {
        overflow: hidden auto;
    }

    /* Collapsed: icons only, every link still reachable.
       The wrapper keeps Tailwind's lg:px-8 (2rem per side) which inside a
       4.75rem rail would leave only 12px of usable width - narrower than the
       36px logo and the 20px icons - spilling them over the content column.
       Dropping to 0.75rem restores a 52px content box. */
    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell)> nav > div {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
    }

    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) .sb-label {
        display: none;
    }

    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) #nav-links a {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }

    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) #nav-brand span:last-child {
        display: none;
    }

    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) .sb-collapse-icon {
        display: none;
    }

    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) #nav-brand {
        width: 100%;
        justify-content: center;
    }

    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) .sb-toggle-label {
        display: none;
    }

    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) #sidebar-toggle {
        justify-content: center;
        padding-left: 0;
        padding-right: 0;
    }

    :is(.app-shell:not(.sb-collapsed), html:not(.sb-pre) .app-shell) .sb-expand-icon {
        display: none;
    }

    /* The rail carries no vertical padding of its own, so the 66px brand
       logo and the collapse control sat flush against the viewport edges. */
    .app-shell > nav > div {
        padding-top: 1.25rem;
        padding-bottom: 1.25rem;
    }

    /* Collapsed: the brand logo is 66px, which is wider than the 52px
       content box of a 4.75rem rail. Scale it down so it centres inside
       the rail instead of spilling across the padding. Height only, for the
       same reason as every other logo - the width follows logo.png's ratio. */
    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) #lg-nav img {
        height: 2.25rem;
    }

    /* ---------- Public authentication layout ----------
       login / register / forgot / otp / reset get their own clean
       layout. The shell stops being a flex row and the single existing
       nav returns to the full-width top bar it already uses below
       1024px, so the auth card is centred in the whole viewport instead
       of being pushed aside by the 256px rail. Declared last so these
       rules win over the collapsed/rail rules above at equal specificity. */
    .app-shell.sb-public {
        display: flex;
        flex-direction: column;
    }
    
    @media (min-width: 1024px) {
        .app-shell.sb-public {
            flex-direction: row;
        }
    }

    .app-shell.sb-public > nav {
        width: 100%;
        max-width: none;
        height: auto;
        position: static;
        top: auto;
        margin: 0.5rem;
        border-radius: 1rem;
        flex: 0 0 auto;
    }

    .app-shell.sb-public > nav > div {
        max-width: 80rem;
        margin-left: auto;
        margin-right: auto;
        height: auto;
        flex-direction: row;
        align-items: center;
        padding-top: 0.5rem;
        padding-bottom: 0.5rem;
    }

    .app-shell.sb-public #nav-row {
        height: auto;
        flex: 1 1 auto;
        min-width: 0;
        /* the rail rule above makes this a column; the auth bar stays a
           wrapping row so brand-left / links-right is preserved */
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
        flex-wrap: wrap;
        row-gap: 0.25rem;
    }

    .app-shell.sb-public #nav-brand {
        align-self: center;
    }

    .app-shell.sb-public #nav-links {
        width: auto;
        flex: 0 1 auto;
        min-width: 0;
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        justify-content: flex-end;
        margin-top: 0;
        overflow: visible;
        gap: 0.25rem 1.5rem;
    }

    /* neutralise the rail's lg:space-x-0 child margins */
    .app-shell.sb-public #nav-links > * {
        margin-left: 0;
    }

    .app-shell.sb-public #nav-links a {
        width: auto;
        padding: 0.5rem 0.75rem;
    }

    .app-shell.sb-public .sb-label {
        display: inline;
    }

    .app-shell.sb-public #nav-brand span:last-child {
        display: inline;
    }

    /* no rail, no collapse control */
    .app-shell.sb-public #sidebar-toggle-wrap {
        display: none;
    }
}

/* Active route highlight for the mobile menu (aria-current is set by JS) */
#mobile-menu a[aria-current="page"] {
    background: rgba(56, 189, 248, 0.16);
    border-left: 2px solid #38bdf8;
    color: #7dd3fc;
}

@media (prefers-reduced-motion: reduce) {
    .app-shell > nav {
        transition: none;
    }
}

/* =========================================
   Landing page navbar (the `home` view only)
   =========================================
   The landing hero owns the background image, so on that one view the
   existing nav is genuinely transparent and overlays the top of the hero
   instead of sitting above it as a solid rounded box - otherwise white nav
   text would land on the page's white background and be unreadable.

   navigate() adds .sb-landing on `home` and nothing else, so the dashboard
   rail and every other view keep exactly the navbar they have today. The
   hero itself is untouched; it already reserves ~5rem of height for the
   nav, which is why it needs no size change once the nav leaves the flow.

   Declared last so these rules win over the equal-specificity .sb-public
   top-bar rules above, which supply the horizontal brand-left / links-right
   arrangement this reuses rather than redefines. */
.app-shell.sb-landing {
    /* anchors the absolutely positioned nav, so it cannot escape to the
       viewport and drift away from the hero */
    position: relative;
}

.app-shell.sb-landing > nav {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 40;
    width: auto;
    min-width: 0;
    max-width: none;
    height: auto;
    /* out of flow: no reserved gap above the hero */
    margin: 0;
    /* genuinely transparent - the hero shows through, no scrim, no tint */
    background: transparent;
    box-shadow: none;
    border-radius: 0;
    /* text stays white on the dark hero scrim; the nav already sets text-white */
    color: #ffffff;
}

/* the nav now covers the hero's top edge, so the main column's own top
   padding would leave a sliver of page background showing above it */
.app-shell.sb-landing > main {
    padding-top: 0;
}

/* Text-only navigation on the landing page: drop the per-link Font Awesome
   glyphs. Scoped to .sb-landing, so the dashboard sidebar and mobile menus
   elsewhere keep the icons they already have. The brand logo is a sibling
   of #nav-links and is deliberately left alone. */
.app-shell.sb-landing #nav-links i,
.app-shell.sb-landing #mobile-menu i {
    display: none;
}

/* ---------- the landing bar ignores the collapsed rail ----------
   The collapse control is hidden on the landing view, but its rules are more
   specific than the top-bar rules above, so a saved "collapsed" preference
   pinned this navbar to the 76px rail width and hid every .sb-label - i.e.
   all the nav link text - plus the IN-Vest brand word, leaving an empty
   column with nothing visible at all. These pin the landing navbar back to
   full width with readable text, whatever the saved preference is, which
   also covers the first paint before script.js can run. */
.app-shell.sb-landing.sb-public > nav {
    width: auto;
    min-width: 0;
    max-width: none;
    flex: none;
}

.app-shell.sb-landing.sb-public .sb-label {
    display: inline;
}

.app-shell.sb-landing.sb-public #nav-brand span:last-child {
    display: inline;
}

/* ---------- public pages with a light background ----------
   `home` sits on the dark hero photo, so its navbar text stays white. How It
   Works / FAQ / News / Quick Response have no hero and sit on the page's own
   near-white background, where white text is unreadable. They get the
   identical transparent bar - same height, spacing, alignment, brand
   position, no icons - and only the text colour changes. No background is
   added here and no page is modified. The filled Register button keeps its
   own white-on-sky-600 styling, which is already legible. */
.app-shell.sb-dark-text > nav {
    color: #0f172a;
}

.app-shell.sb-dark-text #nav-links a {
    color: #334155;
}

.app-shell.sb-dark-text #nav-links a:hover {
    background: rgba(56, 189, 248, 0.14);
    color: #0369a1;
}

.app-shell.sb-dark-text #nav-links a[aria-current="page"] {
    background: rgba(56, 189, 248, 0.16);
    border-left-color: #38bdf8;
    color: #0369a1;
}

/* The filled Register button is an <a> inside #nav-links too, so the rules
   above would otherwise repaint its label dark on sky-600. It carries its own
   white text, which is legible on the light pages and identical to the
   homepage navbar - reassert it here, hover included. */
.app-shell.sb-dark-text #nav-links a.bg-sky-600,
.app-shell.sb-dark-text #nav-links a.bg-sky-600:hover {
    color: #fff;
}

/* Two children of the nav are dark boxes or dark-on-light controls, so the
   dark text colour above must not be allowed to reach them:
   - #mobile-menu is a navy-800 panel on every page. Its links inherited the
     nav's text-white; without this they turn navy-on-navy (1.2:1, invisible).
     The active link keeps its existing sky-300 via :not().
   - the mobile hamburger is text-gray-300, which is legible on the dark hero
     but only ~1.6:1 on a near-white page, so it takes the same dark as the
     bar's text. */
.app-shell.sb-dark-text #mobile-menu a:not([aria-current="page"]) {
    color: #fff;
}

.app-shell.sb-dark-text nav .md\:hidden button,
.app-shell.sb-dark-text nav .md\:hidden button:hover {
    color: #334155;
}

/* Clear the absolutely positioned bar. `home` keeps padding 0 so the hero
   runs to the very top, but these sections only carry py-16 (64px) while the
   bar measures 82px, so without this the first heading would sit underneath
   it. 1.5rem tops it up past the bar - no page padding changed. */
.app-shell.sb-landing.sb-dark-text > main {
    padding-top: 1.5rem;
}

/* =========================================
   Bare auth views: login / register /
   payment / password recovery
   =========================================
   navigate() hides every piece of navigation on these six views - #main-nav
   goes .hidden and the standalone #auth-back button appears in its place.
   sb-bare is the class it toggles alongside those, and it exists for exactly
   one reason: #auth-back is a direct child of #app-shell, and #app-shell is
   `lg:flex-row`, so that button used to be laid out as the first flex column
   of the page. Measured consequences at 1920x1080, before:

   1. #main-nav is display:none on these views, so the Back button was the
      only in-flow item ahead of <main>. At lg it reserved a 120px column and
      pushed <main> to x=120 / w=1800, which put the card's centre at 1024 in
      a 1920 viewport - the login form sat 64px right of centre.
   2. <main> carries `min-h-screen`, and the Back button sat in *normal flow
      above* it, so the document was 100vh + ~52px tall and every auth page
      grew a scrollbar it did not need: 895 vs 844 at 390x844, 1232 vs 1180
      at 820x1180, 791 vs 740 at 360x740.
   3. With nothing centred it, <main> kept the card top-aligned inside its
      own full-viewport height, leaving ~500px of blank page below it.

   Same treatment the landing navbar already gets in .sb-landing above: the
   button becomes chrome positioned over the viewport instead of a sibling in
   the content flow. One in-flow child is left, so <main> owns the whole
   viewport, its min-h-screen stops double counting anything, and the active
   section can be centred in it. Declared after .sb-landing/.sb-dark-text
   because those never apply to these views but the ordering keeps the intent
   readable. */
.app-shell.sb-bare {
    /* anchors the absolutely positioned Back button so it cannot escape to
       the viewport, same reason .sb-landing sets this */
    position: relative;
}

.app-shell.sb-bare>#auth-back {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 40;
    /* the markup's own mx-4/mt-4 insets still apply - absolute positioning
       resolves against the shell, which starts at 0,0 */
}

/* <main> is now the only in-flow child, so it can lay its view out as a
   column and centre it. `lg:pl-2` exists to clear the 16rem sidebar rail;
   there is no rail here and it was the last 4px of off-centre. */
.app-shell.sb-bare>main {
    display: flex;
    flex-direction: column;
    padding-left: 0;
}

/* auto margins absorb only *positive* free space, so when the card is taller
   than the viewport (the register form at 360-820px wide) they resolve to 0
   and the page scrolls normally instead of clipping off the top. */
.app-shell.sb-bare>main>.view-section.active {
    margin-block: auto;
}

/* ---------- daily CVP claim: the greyed-out state ----------
   The button's classes are a solid sky-600 fill with a sky-500 hover, so
   simply setting [disabled] left it looking active (and still highlighted on
   hover) while the reward was on cooldown. These rules repaint it grey for
   the whole window between a claim and the 24-hour timer expiring. The
   id selector outranks the Tailwind hover rule, so the fill cannot flash back
   to blue while the button is disabled. Colours are the same slate values
   already used elsewhere in this file. */
#btn-claim-mining:disabled {
    background: #cbd5e1;
    color: #64748b;
    cursor: not-allowed;
}

#btn-claim-mining:disabled:hover {
    background: #cbd5e1;
    color: #64748b;
}

/* =========================================
   Small-phone dashboard + mobile menu
   -----------------------------------------
   Both fixes below are scoped to widths under
   1024px, where #nav-links is still a hidden
   desktop list and #mobile-menu is the only
   menu on screen. Nothing here touches the lg+
   rail rules, so the desktop sidebar and
   dashboard are unchanged.

   1) #mobile-menu: the links are injected as
      display:block anchors whose icon and label
      are plain inline siblings, so they ran
      together with no gap and no reserved icon
      column. Giving each link a flex row with a
      fixed-width icon and a real gap fixes the
      collision, aligns the glyph with its label,
      and the min-height keeps every row a
      comfortable tap target.
   2) #view-member-dashboard: the cards used
      desktop-sized padding and type, so on a
      small phone they overflowed the viewport
      and forced sideways scrolling. Padding,
      gaps and the big CVP figures step down at
      640px and again at 400px. Sizes are reduced
      in proportion rather than scaled down
      uniformly, so the visual hierarchy holds.
   ========================================= */
@media (max-width: 1023px) {

    /* ---------- mobile drop-down menu ---------- */
    #mobile-menu {
        /* overflow-wrap lets a long label break instead of
           running under the icon or off the panel edge */
        overflow-wrap: anywhere;
    }

    #mobile-menu a {
        display: flex;
        align-items: center;
        gap: 0.75rem;
        /* 2.75rem keeps the row a comfortable thumb
           target without making the menu feel sparse */
        min-height: 2.75rem;
        padding: 0.625rem 0.75rem;
        border-radius: 0.5rem;
    }

    /* Reserved icon column: the glyph gets its own
       fixed width and cannot be pushed into the text */
    #mobile-menu a>i {
        flex: 0 0 1.25rem;
        width: 1.25rem;
        text-align: center;
        font-size: 1rem;
        line-height: 1.5;
    }

    #mobile-menu a>.sb-label {
        /* min-width:0 lets a long label shrink inside the
           flex row instead of overflowing it */
        min-width: 0;
        flex: 1 1 auto;
        line-height: 1.5;
    }

    /* Consistent spacing between rows without relying on
       the space-y-3 gap alone */
    #mobile-menu a + a {
        margin-top: 0.25rem;
    }

    /* The filled Register button keeps its own look but
       stays on the same row geometry */
    #mobile-menu a.bg-sky-600 {
        justify-content: flex-start;
    }
}

/* ---------- dashboard cards step down ---------- */
@media (max-width: 640px) {
    #view-member-dashboard>div {
        padding-left: 1rem;
        padding-right: 1rem;
        padding-top: 1.5rem;
        padding-bottom: 1.5rem;
    }

    #view-member-dashboard .grid {
        gap: 1rem;
    }

    /* Card padding: p-6 -> p-4 keeps the content inside
       the viewport on a small screen */
    #view-member-dashboard .bg-white,
    #view-member-dashboard .bg-navy-900 {
        padding: 1rem;
    }

    /* Headings and section titles */
    #view-member-dashboard h1 {
        font-size: 1.25rem;
    }

    #view-member-dashboard h3 {
        font-size: 1rem;
        margin-bottom: 1rem;
    }

    /* The welcome row and the top gap */
    #view-member-dashboard .mb-8 {
        margin-bottom: 1.5rem;
    }

    /* Status badge must not push the header wider */
    #dash-status-badge {
        font-size: 0.75rem;
        padding: 0.375rem 0.75rem;
    }

    /* Big money/CVP figures: 3xl -> 2xl so a long value
       cannot push its card past the screen edge */
    #view-member-dashboard .text-3xl {
        font-size: 1.5rem;
    }

    /* The "/ 100 CVP" suffix sits beside the CVP number;
       it needs to be allowed to wrap under it */
    #view-member-dashboard .text-3xl .text-lg {
        font-size: 0.875rem;
        white-space: nowrap;
    }

    /* Cycle progress header stacks on its own line */
    #view-member-dashboard .flex.justify-between.items-end {
        flex-wrap: wrap;
        gap: 0.25rem;
    }

    /* Mining timer */
    #mining-timer {
        font-size: 1.375rem;
    }

    /* Quick Links rows: tighter padding, and the icon
       keeps its own column so it clears the label */
    #view-member-dashboard button.p-4 {
        padding: 0.75rem;
        gap: 0.5rem;
    }

    #view-member-dashboard button.p-4 span {
        min-width: 0;
        overflow-wrap: anywhere;
    }
}

/* ---------- very small phones (360px and below) ---------- */
@media (max-width: 400px) {
    #view-member-dashboard .text-3xl {
        font-size: 1.25rem;
    }

    #view-member-dashboard .text-2xl {
        font-size: 1.125rem;
    }

    /* Page gutter tightens so cards keep a usable width */
    #view-member-dashboard>div {
        padding-left: 0.75rem;
        padding-right: 0.75rem;
    }

    #mobile-menu a {
        gap: 0.625rem;
        padding-left: 0.625rem;
        padding-right: 0.625rem;
    }
}

/* =========================================
   Progressive responsive scale
   -----------------------------------------
   Every size in this app is a fixed Tailwind utility (a rem or px step), so
   on a phone the desktop dimensions simply stay desktop-sized and the layout
   gets squeezed. This block adds a scale that steps those utilities down as
   the viewport narrows.

   How it works, so it stays maintainable:

   1) The custom properties below are declared at :root with values IDENTICAL
      to Tailwind's current desktop steps. The rules that consume them are
      therefore no-ops at desktop width - the large desktop design renders
      exactly as it does today.
   2) Each media query below only overrides those properties. Adding a tier
      means editing one block, not hunting selectors.
   3) html { font-size } ramps with them. Because Tailwind's text, padding,
      margin and gap utilities are all rem-based, this scales the whole
      layout proportionally in a single move - including the sidebar rail
      (--sb-w: 16rem). The ramp deliberately stops at 15px so the smallest
      text utility (text-xs = 0.75rem) never falls below 11px and stays
      legible. Compaction past that point comes from the properties instead,
      so hierarchy survives rather than everything shrinking uniformly.
   4) Inputs keep their 16px font size (set earlier in this file to stop iOS
      zoom-on-focus). They are deliberately not part of the ramp.

   Breakpoints follow the Tailwind defaults already in use (sm 640, md 768,
   lg 1024, xl 1280) and add tiers at 480px and 380px for the common phone
   widths:

     >= 1280px   large desktop ............ 100%  (untouched)
     <= 1279px   medium desktop ........... ~96%
     <= 1023px   tablet ................... ~92%
     <= 767px    small tablet ............. ~90%
     <= 639px    mobile ................... ~88%
     <= 479px    small mobile phone ....... ~85%
     <= 379px    smallest phones .......... ~82%

   The consuming rules use `body :is(...)` compounds rather than bare class
   names, so they outrank Tailwind's single-class utilities regardless of
   which stylesheet the Tailwind CDN injects first.
   ========================================= */

:root {
    --sc-gutter: 1rem;
    --sc-py-20: 5rem;
    --sc-py-16: 4rem;
    --sc-py-12: 3rem;
    --sc-py-8: 2rem;
    --sc-p-8: 2rem;
    --sc-p-6: 1.5rem;
    --sc-p-5: 1.25rem;
    --sc-p-4: 1rem;
    --sc-gap-8: 2rem;
    --sc-gap-6: 1.5rem;
    --sc-gap-4: 1rem;
    --sc-gap-3: 0.75rem;
    --sc-text-4xl: 2.25rem;
    --sc-text-3xl: 1.875rem;
    --sc-text-2xl: 1.5rem;
    --sc-text-xl: 1.25rem;
    --sc-text-lg: 1.125rem;
    --sc-btn-x: 2rem;
    --sc-btn-y: 0.75rem;
    --sc-nav-h: 3.5rem;
    --sc-brand-text: 1.25rem;
    /* Hero logo height. Monotonic by design: the hero is
       min-h-calc(100vh - 5rem), so the artwork has to shrink with the
       viewport or it crowds out the slogan, description and buttons on
       short/narrow screens. Each tier below steps this down; nothing else
       is allowed to set the hero logo's size. */
    --sc-hero-logo: 212px;
    --sc-brand-logo: 66px;
}

/* ---------- the scale consumers (all no-ops at desktop) ---------- */

/* Page gutter: keep content off the extreme edges without letting the
   container grow past the viewport. */
body :is(.max-w-7xl, .max-w-4xl, .max-w-3xl, .max-w-2xl, .max-w-md).px-4 {
    padding-left: var(--sc-gutter);
    padding-right: var(--sc-gutter);
}

/* Section vertical rhythm. Scoped to a view section's own wrapper so nested
   blocks keep their own spacing. */
body .view-section>.py-20 {
    padding-top: var(--sc-py-20);
    padding-bottom: var(--sc-py-20);
}

body .view-section>.py-16 {
    padding-top: var(--sc-py-16);
    padding-bottom: var(--sc-py-16);
}

body .view-section>.py-12 {
    padding-top: var(--sc-py-12);
    padding-bottom: var(--sc-py-12);
}

body .view-section>.py-8 {
    padding-top: var(--sc-py-8);
    padding-bottom: var(--sc-py-8);
}

/* The landing hero carries its own py-16 sm:py-20, which would otherwise be
   pinned at the desktop value below sm. */
body #view-home .landing-hero>.py-16 {
    padding-top: var(--sc-py-16);
    padding-bottom: var(--sc-py-16);
}

/* Card padding. Keyed off the padding + rounding pair, which is what
   distinguishes a real card from a bare padded block. */
body .p-8:is(.rounded-2xl, .rounded-xl, .rounded-lg) {
    padding: var(--sc-p-8);
}

body .p-6:is(.rounded-2xl, .rounded-xl, .rounded-lg) {
    padding: var(--sc-p-6);
}

body .p-5:is(.rounded-2xl, .rounded-xl, .rounded-lg) {
    padding: var(--sc-p-5);
}

body .p-4:is(.rounded-2xl, .rounded-xl, .rounded-lg) {
    padding: var(--sc-p-4);
}

/* Table rows and list rows are padded but not rounded, so the card rule above
   skips them. They carry the same visual density, so they scale with it. */
body .p-4:is(.flex, .flex-col) {
    padding: var(--sc-p-4);
}

body .p-5.border-b,
body .p-6.border-b {
    padding-top: var(--sc-p-5);
    padding-bottom: var(--sc-p-5);
    padding-left: var(--sc-p-6);
    padding-right: var(--sc-p-6);
}

/* Grid gaps */
body :is(.gap-8) {
    gap: var(--sc-gap-8);
}

body :is(.gap-6) {
    gap: var(--sc-gap-6);
}

body :is(.gap-4) {
    gap: var(--sc-gap-4);
}

body :is(.gap-3) {
    gap: var(--sc-gap-3);
}

/* Typography: only the large steps move. text-sm / text-xs are left alone so
   body copy stays readable, and they still shrink gently with the root ramp. */
body :is(.text-4xl) {
    font-size: var(--sc-text-4xl);
}

body :is(.text-3xl) {
    font-size: var(--sc-text-3xl);
}

body :is(.text-2xl) {
    font-size: var(--sc-text-2xl);
}

body :is(.text-xl) {
    font-size: var(--sc-text-xl);
}

body :is(.text-lg) {
    font-size: var(--sc-text-lg);
}

/* Buttons: less inset, same design. Padding stays generous enough to remain
   a comfortable tap target at every tier. */
body button:is(.px-8) {
    padding-left: var(--sc-btn-x);
    padding-right: var(--sc-btn-x);
}

body button:is(.py-3) {
    padding-top: var(--sc-btn-y);
    padding-bottom: var(--sc-btn-y);
}

/* Every logo instance - navbar, hero, the auth cards, the dashboard and
   admin headers - renders the same public/logo.png, which is a 671x763
   portrait bitmap with transparent padding baked in (the artwork itself is
   about 83% of the file's width and 63% of its height).

   renderBrand() in script.js hands each one a *square* size-class pair such
   as h-[66px] w-[66px], and object-contain then letterboxes the portrait
   artwork inside that square: a 66px box only fills 58x66. ~12% of the width
   every logo box reserved was empty space, which is why the mark reads
   smaller than the box it was measured in.

   Letting the width follow the bitmap's own ratio fixes that - the box then
   reserves the artwork's real footprint, the logo is never distorted at any
   size, and the empty square no longer widens #nav-brand or the centred
   hero/card wrappers. Only the width changes here; each context still sets
   its own height (the --sc-hero-logo / --sc-brand-logo scale for the hero
   and navbar, renderBrand()'s height class for the rest).

   Specificity is (1,0,1), which outranks the single-class h-/w- utilities
   Tailwind generates from renderBrand(), so this holds regardless of the
   order the Tailwind CDN injects its stylesheet. */
body :is(#lg-nav, #lg-landing, #lg-login, #lg-register, #lg-payment, #lg-forgot,
    #lg-forgot-otp, #lg-forgot-reset, #lg-dash, #lg-admin) img {
    width: auto;
}

/* Landing hero artwork: the largest single element on the page, and the one
   place where the size genuinely has to step with the viewport, because the
   hero has a viewport-relative min-height. --sc-hero-logo (bottom of file)
   owns it in a single monotonic ramp, 212px on large desktop down to 84px on
   the narrowest phones; renderBrand()'s h-[340px]..lg:h-[360px] classes on
   this one logo are inert and deliberately left alone, this selector wins. */
body #lg-landing img {
    height: var(--sc-hero-logo);
}

/* The navbar bar height and wordmark are scoped below lg on purpose. At lg
   #nav-row switches to height:auto as a flex column for the sidebar rail, so
   an unconditional height rule here would collapse the desktop rail. */
@media (max-width: 1023px) {
    body #nav-row:is(.h-14) {
        height: var(--sc-nav-h);
    }

    body #nav-brand>span:last-child:is(.text-xl) {
        font-size: var(--sc-brand-text);
    }

    body #lg-nav img {
        height: var(--sc-brand-logo);
    }
}

/* Overflow guards. These properties are not set by any utility, so they never
   fight Tailwind - they only stop content pushing the page wider than the
   viewport. */
body img,
body svg {
    max-width: 100%;
}

body button,
body a {
    max-width: 100%;
}

/* ---------- the tiers ---------- */

/* Medium desktop: a touch tighter, still recognisably the desktop layout. */
@media (max-width: 1279px) {
    html {
        font-size: 15.75px;
    }

    :root {
        --sc-gutter: 1.0625rem;
        --sc-py-20: 4rem;
        --sc-py-16: 3.25rem;
        --sc-py-8: 2.25rem;
        --sc-p-8: 1.75rem;
        --sc-p-6: 1.375rem;
        --sc-p-5: 1.125rem;
        --sc-p-4: 1rem;
        --sc-gap-8: 1.5rem;
        --sc-gap-6: 1.25rem;
        --sc-gap-4: 0.875rem;
        --sc-gap-3: 0.625rem;
        --sc-text-4xl: 1.875rem;
        --sc-text-3xl: 1.625rem;
        --sc-text-2xl: 1.375rem;
        --sc-text-xl: 1.125rem;
        --sc-text-lg: 1.0625rem;
        --sc-btn-x: 1.75rem;
        --sc-btn-y: 0.6875rem;
        --sc-hero-logo: 168px;
        --sc-brand-logo: 56px;
    }
}

/* Tablet: the sidebar becomes the floating top bar, so the bar and the page
   gutter both step down. */
@media (max-width: 1023px) {
    html {
        font-size: 15.25px;
    }

    :root {
        --sc-gutter: 1.125rem;
        --sc-py-20: 3rem;
        --sc-py-16: 2.75rem;
        --sc-py-12: 2.25rem;
        --sc-py-8: 2rem;
        --sc-p-8: 1.5rem;
        --sc-p-6: 1.25rem;
        --sc-p-5: 1rem;
        --sc-p-4: 0.875rem;
        --sc-gap-8: 1.375rem;
        --sc-gap-6: 1.125rem;
        --sc-gap-4: 0.75rem;
        --sc-gap-3: 0.5rem;
        --sc-text-4xl: 1.75rem;
        --sc-text-3xl: 1.5rem;
        --sc-text-2xl: 1.25rem;
        --sc-text-xl: 1.125rem;
        --sc-text-lg: 1rem;
        --sc-btn-x: 1.5rem;
        --sc-btn-y: 0.625rem;
        --sc-nav-h: 3.25rem;
        --sc-brand-text: 1.0625rem;
        --sc-hero-logo: 140px;
        --sc-brand-logo: 48px;
    }
}

/* Small tablet */
@media (max-width: 767px) {
    html {
        font-size: 15px;
    }

    :root {
        --sc-gutter: 1.25rem;
        --sc-py-20: 2.5rem;
        --sc-py-16: 2.25rem;
        --sc-py-12: 1.875rem;
        --sc-py-8: 1.75rem;
        --sc-p-8: 1.25rem;
        --sc-p-6: 1rem;
        --sc-p-5: 0.9375rem;
        --sc-p-4: 0.8125rem;
        --sc-gap-8: 1.125rem;
        --sc-gap-6: 1rem;
        --sc-gap-4: 0.75rem;
        --sc-gap-3: 0.5rem;
        --sc-text-4xl: 1.625rem;
        --sc-text-3xl: 1.4375rem;
        --sc-text-2xl: 1.1875rem;
        --sc-text-xl: 1.0625rem;
        --sc-text-lg: 1rem;
        --sc-btn-x: 1.5rem;
        --sc-btn-y: 0.625rem;
        --sc-nav-h: 3.25rem;
        --sc-brand-text: 1.0625rem;
        --sc-hero-logo: 128px;
        --sc-brand-logo: 46px;
    }
}

/* Normal mobile phone */
@media (max-width: 639px) {
    :root {
        --sc-gutter: 1.25rem;
        --sc-py-20: 2rem;
        --sc-py-16: 1.75rem;
        --sc-py-12: 1.5rem;
        --sc-py-8: 1.5rem;
        --sc-p-8: 1.125rem;
        --sc-p-6: 0.9375rem;
        --sc-p-5: 0.875rem;
        --sc-p-4: 0.75rem;
        --sc-gap-8: 1rem;
        --sc-gap-6: 0.875rem;
        --sc-gap-4: 0.625rem;
        --sc-gap-3: 0.4375rem;
        --sc-text-4xl: 1.5rem;
        --sc-text-3xl: 1.375rem;
        --sc-text-2xl: 1.125rem;
        --sc-text-xl: 1.0625rem;
        --sc-text-lg: 1rem;
        --sc-btn-x: 1.25rem;
        --sc-btn-y: 0.625rem;
        --sc-nav-h: 3rem;
        --sc-brand-text: 1rem;
        --sc-hero-logo: 112px;
        --sc-brand-logo: 42px;
    }
}

/* Small mobile phone */
@media (max-width: 479px) {
    :root {
        --sc-gutter: 1.375rem;
        --sc-py-20: 1.5rem;
        --sc-py-16: 1.5rem;
        --sc-py-12: 1.375rem;
        --sc-py-8: 1.25rem;
        --sc-p-8: 1rem;
        --sc-p-6: 0.875rem;
        --sc-p-5: 0.8125rem;
        --sc-p-4: 0.75rem;
        --sc-gap-8: 0.875rem;
        --sc-gap-6: 0.75rem;
        --sc-gap-4: 0.5625rem;
        --sc-gap-3: 0.4375rem;
        --sc-text-4xl: 1.375rem;
        --sc-text-3xl: 1.25rem;
        --sc-text-2xl: 1.0625rem;
        --sc-text-xl: 1rem;
        --sc-text-lg: 0.9375rem;
        --sc-btn-x: 1.125rem;
        --sc-btn-y: 0.5625rem;
        --sc-nav-h: 2.875rem;
        --sc-brand-text: 0.9375rem;
        --sc-hero-logo: 96px;
        --sc-brand-logo: 38px;
    }
}

/* Smallest phones */
@media (max-width: 379px) {
    :root {
        --sc-gutter: 1.25rem;
        --sc-py-20: 1.25rem;
        --sc-py-16: 1.25rem;
        --sc-py-12: 1.25rem;
        --sc-py-8: 1rem;
        --sc-p-8: 0.875rem;
        --sc-p-6: 0.8125rem;
        --sc-p-5: 0.75rem;
        --sc-p-4: 0.625rem;
        --sc-gap-8: 0.75rem;
        --sc-gap-6: 0.625rem;
        --sc-gap-4: 0.5rem;
        --sc-gap-3: 0.375rem;
        --sc-text-4xl: 1.25rem;
        --sc-text-3xl: 1.125rem;
        --sc-text-2xl: 1rem;
        --sc-text-xl: 0.9375rem;
        --sc-text-lg: 0.9375rem;
        --sc-btn-x: 1rem;
        --sc-btn-y: 0.5rem;
        --sc-nav-h: 2.75rem;
        --sc-brand-text: 0.9375rem;
        --sc-hero-logo: 84px;
        --sc-brand-logo: 34px;
    }
}
