/* =========================================
   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;
}

/* 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 */
@media (max-width: 640px) {
    .view-section {
        font-size: 15px;
    }
    .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;
    }

    /* 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);
        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. */
    :is(.app-shell.sb-collapsed, html.sb-pre .app-shell) #lg-nav img {
        width: 2.25rem;
        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: block;
    }

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

    .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;
}

/* ---------- 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;
    /* Desktop default matches the existing sm: step so the hero logo is
       byte-identical at large desktop widths. */
    --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);
}

/* Landing hero artwork: the largest single element on the page. The default
   matches the existing sm: step (212px) so desktop is unchanged, and every
   tier below steps it down. */
body #lg-landing img {
    height: var(--sc-hero-logo);
    width: 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);
        width: 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;
    }
}
