/*
 * Forge-inspired application chrome.
 * This only changes the navbar's visual treatment; existing controls, order,
 * responsive breakpoints, and JavaScript behaviour stay intact.
 */
.forge-topnav {
    --topnav-accent: var(--violet, var(--indigo, #5b50e8));
    --topnav-primary: var(--violet, var(--indigo, #5b50e8));
    --topnav-ink: var(--text-primary, var(--text, #111827));
    --topnav-muted: var(--text-secondary, var(--text-2, #5b6477));
    /* One attached header keeps navigation separate from the study content.
       Keep the established controls and mobile entry points. */
    position: fixed;
    top: 0;
    left: 50%;
    right: auto;
    width: 100%;
    height: 64px;
    padding: 0 24px;
    transform: translateX(-50%);
    overflow: visible;
    border: 0;
    border-bottom: 1px solid #e2e2e8;
    border-radius: 0;
    background: #fff;
    box-shadow: none;
    /* marketing-nav.css also sets a blur on this element; the bar is opaque,
       so it would buy nothing but a compositing layer. */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    transition:
        transform .35s cubic-bezier(.4, 0, .2, 1),
        border-color .2s ease,
        box-shadow .2s ease;
}

.forge-topnav--marketing { --topnav-muted: #566177; }

.forge-topnav.scrolled {
    border-color: #d8d8e1;
    box-shadow: 0 2px 8px rgba(20, 20, 30, .04);
}

.forge-topnav.nav-hidden {
    transform: translate(-50%, calc(-100% - 18px));
    box-shadow: none;
}

.forge-topnav.nav-hidden:focus-within {
    transform: translateX(-50%);
}

[data-dark] .forge-topnav,
[data-dark] .forge-topnav.scrolled {
    --topnav-accent: #b9b2ff;
    /* The bar was #111113 — the page ground — so a purple border was doing all
       the separating. On the major-surface rung the fill separates it and the
       edge can go back to the system's subtle neutral line. */
    background: #18181B;
    border-color: rgba(255, 255, 255, .08);
    box-shadow: none;
}

[data-dark] .forge-topnav--marketing { --topnav-muted: #B4B4BD; }

[data-dark] .forge-topnav.scrolled {
    border-color: rgba(255, 255, 255, .12);
    box-shadow: 0 2px 8px rgba(0, 0, 0, .38);
}

.forge-topnav .nav-inner {
    max-width: none;
    height: 100%;
}

.forge-topnav .nav-dd-btn,
.forge-topnav .nav-links a,
.forge-topnav .nav-right > a,
.forge-topnav .nav-auth-btn,
.forge-topnav .nav-dash-btn,
.forge-topnav .nav-search input,
.forge-topnav .nav-cta-mobile {
    font-family: var(--font-ui);
    font-weight: 600;
}

/* ── Nothing leaves the bar ───────────────────────────────────────────────
   Every control in the right-hand cluster is a fixed-size pill with a nowrap
   label, so shrinking that cluster's BOX does not shrink what is inside it —
   it pushes the contents out through the right-hand edge. Which is exactly
   what happened: `min-width: 0` here let flexbox pick .nav-right as the thing
   to absorb an over-long row, squeezed it ~50px under its own content, and
   the hamburger — the only route into navigation on a phone — rendered past
   the edge of the screen.

   On iOS that is worse than clipping. The bar is position: fixed, so the
   spill extends the document's scroll width, and because fixed elements are
   laid out against the LAYOUT viewport there, scrolling sideways drags the
   bar off to the left with the page: the brand ends up half cut off and the
   burger is somewhere past the right edge. That is the reported bug.

   So the controls never shrink. The squeeze goes to the brand instead, which
   is the one thing in here that can lose characters and still work. */
.forge-topnav .nav-left {
    min-width: 0;
    flex: 0 1 auto;
}

.forge-topnav .nav-right,
.forge-topnav .nav-links {
    flex: 0 0 auto;
}

.forge-topnav .nav-logo,
.forge-topnav .nav-brand {
    min-width: 0;
}

/* …and absorbing it means truncating inside the bar, not overflowing it.
   Both navs set `white-space: nowrap` on the wordmark, which without an
   overflow rule is a licence to run off the end. */
.forge-topnav .nav-logo > span,
.forge-topnav .nav-brand-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The app's allowance readout is the other variable-width thing in here —
   "7%" and "100%" are not the same pill — so it gives ground too rather than
   pushing the row wider. */
.forge-topnav .nav-usage { min-width: 0; }
.forge-topnav .nav-usage-text { overflow: hidden; }

.forge-topnav .nav-logo,
.forge-topnav .nav-brand {
    min-height: 44px;
    padding: 4px;
    border-radius: 12px;
    transition: background .15s ease, transform .15s cubic-bezier(.32, .72, .28, 1);
}

.forge-topnav .nav-logo:hover,
.forge-topnav .nav-brand:hover {
    background: rgba(91, 80, 232, .07);
}

.forge-topnav .nav-logo:active,
.forge-topnav .nav-brand:active,
.forge-topnav .nav-dd-btn:active,
.forge-topnav .nav-auth-btn:active {
    transform: scale(.96);
}

.forge-topnav .nav-logo-mark {
    width: 32px;
    height: 32px;
    border-radius: 10px;
    box-shadow: 0 1px 2px rgba(35, 28, 110, .2);
}

.forge-topnav .nav-logo > span,
.forge-topnav .nav-brand-name {
    color: var(--topnav-ink);
    font-size: 1rem;
    letter-spacing: -.025em;
}

.forge-topnav .brand-sub {
    color: var(--topnav-muted);
    opacity: 1;
    font-size: .82em;
}

.forge-topnav--marketing .nav-search input::placeholder,
.forge-topnav--marketing .nav-dd-sep,
.forge-topnav--marketing .nav-dd-subcat {
    color: var(--topnav-muted);
    opacity: 1;
}

.forge-topnav .nav-dd-btn {
    min-height: 38px;
    padding: 0 12px;
    border: 1px solid transparent;
    border-radius: 12px;
    color: var(--topnav-muted);
    transition: color .15s, background .15s, border-color .15s, transform .15s;
}

.forge-topnav .nav-dd-btn:hover,
.forge-topnav .nav-dd[data-open="1"] .nav-dd-btn {
    color: var(--topnav-accent);
    background: rgba(91, 80, 232, .09);
    border-color: rgba(91, 80, 232, .13);
}

.forge-topnav .nav-search input {
    height: 38px;
    border: 1px solid rgba(91, 80, 232, .14);
    border-radius: 12px;
    background: #fff;
    box-shadow: none;
}

.forge-topnav .nav-search input:hover {
    border-color: rgba(91, 80, 232, .25);
}

.forge-topnav .nav-search input:focus,
.forge-topnav .nav-search input:focus-visible {
    border-color: var(--topnav-accent);
    box-shadow: 0 0 0 3px rgba(91, 80, 232, .14);
}

[data-dark] .forge-topnav .nav-search input {
    box-shadow: none;
}

.forge-topnav .nav-dd-menu,
.forge-topnav .nav-search-results {
    top: calc(100% + 12px);
    border-color: rgba(91, 80, 232, .16);
    border-radius: 12px;
    background: #fff;
    box-shadow: 0 6px 18px rgba(28, 24, 82, .1);
}

.forge-topnav .nav-dd-menu {
    max-height: calc(100dvh - 90px - env(safe-area-inset-top));
    overflow-y: auto;
}

[data-dark] .forge-topnav .nav-dd-menu,
[data-dark] .forge-topnav .nav-search-results {
    background: #1D1D21;
    border-color: rgba(255, 255, 255, .08);
    box-shadow: 0 10px 28px rgba(0, 0, 0, .45);
}

.forge-topnav .nav-links a,
.forge-topnav .nav-dash-btn,
.forge-topnav #navScorePill,
.forge-topnav #navStreakPill {
    border-radius: 12px;
}

.forge-topnav .nav-links a {
    min-height: 36px;
    display: inline-flex;
    align-items: center;
}

.forge-topnav .nav-host,
.forge-topnav .nav-links a.nav-dash-link,
.forge-topnav .nav-dash-btn,
.forge-topnav #navScorePill {
    color: var(--topnav-accent);
    /* Opaque, and with enough tint to be a BUTTON. Removing the inset sheen
       stopped these looking like lenses but left a 6.5% wash that barely
       cleared the bar behind it, so next to the solid Upgrade pill they still
       read as see-through outlines. Same family of colour, real fill. */
    border: 1px solid #dedbf7;
    background: #eceafa;
    box-shadow: none;
}

.forge-topnav .nav-host:hover,
.forge-topnav .nav-links a.nav-dash-link:hover,
.forge-topnav .nav-dash-btn:hover {
    /* Deeper ink, not just a deeper fill. The accent at rest gives 4.71:1 on
       the chip; on a hover fill dark enough to actually SEE it drops to 4.16
       and fails AA. Lightening the hover until the accent passed left it 1.04
       against the rest state — a hover nobody can see. So the text darkens
       with the fill, which is what a hover should do anyway: 5.88:1. */
    color: #4338ca;
    border-color: #c9c4f2;
    background: #dfdbf7;
    box-shadow: none;
    transform: translateY(-1px);
}

/* The bar is #0b0e1a here,
so the fill has to be lighter than it — the light
   theme's values would vanish into it. */
/* ONE control skin for the bar. The nav is --surface-1,
so every control sits
   one rung up on --surface-3 behind the same subtle line. Before this the bar
   carried four different greys plus two purple-tinted controls (.nav-auth-btn
   and the toggle/burger only had light-theme rules,
so the brand tint showed through on
   charcoal). Purple stays on the logo, the primary CTA, active items and focus
   rings.

   Three tiers, matching what the light bar already does with white / lavender /
   solid violet — one grey for everything quiet, an accent tint for Dashboard,
   and the solid fill for the single primary. Flat-greying all of them removed
   the six-shade mess but left nothing to look at first. */
[data-dark] .forge-topnav #navScorePill,
[data-dark] .forge-topnav .nav-user-pill,
[data-dark] .forge-topnav .nav-search input,
[data-dark] .forge-topnav .nav-burger,
[data-dark] .forge-topnav .hamburger{
    border-color: rgba(255, 255, 255, .08);
    background: #232327;
}

/* Quiet controls take quiet ink. These inherit the accent from the shared rule
   above, which on a neutral chip beside a solid violet button read as a second
   thing competing for the eye. */
[data-dark] .forge-topnav #navScorePill,
[data-dark] .forge-topnav .nav-create:not(.host) {
    color: #B4B4BD !important;
}

/* Join and Dashboard drop their glyphs. Neither ever renders icon-only — both
   hide outright below their breakpoints — so the icon never carries meaning on
   its own, it just adds texture beside a word that already says the same thing.
   The ones that stay all do work: the search magnifier, the dropdown chevrons,
   and Upgrade's spark, which marks the one paid action. */
.forge-topnav #navCreateIcon,
.forge-topnav .nav-dash-btn > svg,
.forge-topnav .nav-links a.nav-dash-link > svg { display: none; }

/* Tier two: still a brand surface, just not the primary. */
[data-dark] .forge-topnav .nav-host,
[data-dark] .forge-topnav .nav-links a.nav-dash-link,
[data-dark] .forge-topnav .nav-dash-btn {
    border-color: rgba(157, 148, 255, .22);
    background: rgba(157, 148, 255, .12);
}

[data-dark] .forge-topnav .nav-user-pill:hover,
[data-dark] .forge-topnav .nav-burger:hover,
[data-dark] .forge-topnav .hamburger:hover{
    border-color: rgba(255, 255, 255, .14);
    background: #34343A;
}

[data-dark] .forge-topnav .nav-host:hover,
[data-dark] .forge-topnav .nav-links a.nav-dash-link:hover,
[data-dark] .forge-topnav .nav-dash-btn:hover {
    border-color: rgba(157, 148, 255, .38);
    background: rgba(157, 148, 255, .2);
}

.forge-topnav--marketing .nav-user-pill {
    border-radius: 999px;
}

.forge-topnav .nav-cta,
.forge-topnav .nav-create:not(.host) {
    min-height: 36px;
    padding: 0 15px !important;
    border-radius: 12px !important;
    box-shadow: none !important;
    transition: transform .15s cubic-bezier(.32, .72, .28, 1), box-shadow .15s ease !important;
}

.forge-topnav .nav-cta {
    border: 0 !important;
    background: var(--topnav-primary) !important;
    color: #fff !important;
}

.forge-topnav .nav-create:not(.host) {
    border: 1px solid #e2e4ea !important;
    background: #f7f8fd !important;
    color: #454e63 !important;
}

.forge-topnav .nav-create:not(.host):hover {
    background: #eceff5 !important;
    color: #0e1220 !important;
}

[data-dark] .forge-topnav .nav-create:not(.host) {
    border-color: rgba(255, 255, 255, .08) !important;
    background: #232327 !important;
    color: #B4B4BD !important;
}

[data-dark] .forge-topnav .nav-create:not(.host):hover {
    border-color: rgba(255, 255, 255, .14) !important;
    background: #34343A !important;
    color: #F5F5F7 !important;
}

/* The icon span was a block wrapping an inline <svg>, so the glyph rested on
   the text baseline — 2.5px above the pill's optical centre, which read as a
   misaligned button. inline-flex makes the span the size of the icon and lets
   the button's own align-items centre it. */
.forge-topnav .nav-create > span {
    display: inline-flex;
    align-items: center;
}

.forge-topnav .nav-cta:hover,
.forge-topnav .nav-create:not(.host):hover {
    filter: none !important;
    transform: translateY(-1px) !important;
    box-shadow: none !important;
}

.forge-topnav .nav-cta:active,
.forge-topnav .nav-create:not(.host):active {
    transform: scale(.96) !important;
    box-shadow: none !important;
}

.forge-topnav .nav-create.host {
    min-height: 36px;
    border-radius: 12px !important;
}

/* The one primary in the bar. Everything else here is a quiet grey control,
   so signing in is the only thing that carries the brand fill — same job
   .nav-cta does on the marketing nav. Without it the signed-out app bar was
   four identical grey pills and nothing to look at first. */
.forge-topnav .nav-auth-btn {
    min-height: 36px;
    padding: 0 15px;
    border: 0;
    border-radius: 12px;
    background: var(--topnav-primary);
    color: #fff;
    font-weight: 700;
    box-shadow: none;
    transition: filter .15s, transform .15s;
}

.forge-topnav .nav-auth-btn:hover {
    filter: brightness(1.08);
}

.forge-topnav .nav-burger,
.forge-topnav .hamburger{
    width: 36px;
    height: 36px;
    min-width: 36px;
    padding: 0;
    border: 1px solid rgba(91, 80, 232, .11);
    border-radius: 12px;
    background: rgba(91, 80, 232, .055);
    color: var(--topnav-muted);
    align-items: center;
    justify-content: center;
}

.forge-topnav .nav-burger:hover,
.forge-topnav .hamburger:hover{
    background: rgba(91, 80, 232, .11);
    color: var(--topnav-accent);
}

.forge-topnav .nav-burger:active,
.forge-topnav .hamburger:active{
    transform: scale(.94);
}

.forge-topnav .hamburger {
    display: flex;
    flex-direction: column;
}

.forge-topnav .nav-user-avatar {
    width: 34px;
    height: 34px;
    background: transparent;
    box-shadow: none;
}

[data-dark] .forge-topnav .nav-user-avatar,
.forge-topnav .nav-user-pill:hover .nav-user-avatar {
    box-shadow: none;
}

.forge-topnav--marketing .nav-user-pill {
    min-height: 38px;
    padding: 2px 10px 2px 2px;
    background: rgba(91, 80, 232, .065);
    border-color: rgba(91, 80, 232, .14);
}

.forge-topnav--marketing + .mobile-menu {
    top: max(74px, calc(env(safe-area-inset-top) + 68px));
    right: 8px;
    left: 8px;
    max-height: calc(100dvh - 82px - env(safe-area-inset-top));
    border: 1px solid rgba(91, 80, 232, .16);
    border-radius: 12px;
    background: #fff;
    box-shadow: 0 6px 18px rgba(28, 24, 82, .1);
}

.forge-topnav--marketing + .mobile-menu .mm-sep {
    color: #566177;
}

[data-dark] .forge-topnav--marketing + .mobile-menu {
    background: #1D1D21;
    border-color: rgba(157, 148, 255, .18);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .24);
}

[data-dark] .forge-topnav--marketing + .mobile-menu .mm-sep {
    color: #B4B4BD;
}

[data-dark] .forge-topnav :focus-visible,
[data-dark] .forge-topnav--marketing + .mobile-menu :focus-visible {
    outline-color: #b9b2ff;
}

@media (max-width: 980px) {
    .forge-topnav { width: 100%; padding-inline: 14px; }
    .forge-topnav .nav-right { gap: 8px; }
}

@media (max-width: 640px) {
    .forge-topnav {
        top: max(8px, env(safe-area-inset-top));
        height: 52px;
        padding: 0 7px 0 9px;
        border-radius: 12px;
    }

    .forge-topnav .nav-logo,
    .forge-topnav .nav-brand {
        gap: 7px;
        min-height: 42px;
        padding: 3px;
    }

    .forge-topnav .nav-logo-mark {
        width: 30px;
        height: 30px;
        border-radius: 9px;
    }

    .forge-topnav .brand-sub { display: none; }

    .forge-topnav .nav-cta-mobile {
        min-height: 36px;
        border-radius: 12px;
        box-shadow: none;
    }

    .forge-topnav--marketing.subjects-open .nav-left-menu {
        position: fixed;
        display: block;
        width: 0;
        height: 0;
    }

    .forge-topnav--marketing.subjects-open #subjectsDd {
        position: static;
    }

    .forge-topnav--marketing.subjects-open #subjectsDd > .nav-dd-btn {
        display: none;
    }

    .forge-topnav--marketing.subjects-open #subjectsDd .nav-dd-menu {
        position: fixed;
        top: max(74px, calc(env(safe-area-inset-top) + 68px));
        right: 8px;
        left: 8px;
        width: auto;
        max-height: calc(100dvh - 82px - env(safe-area-inset-top));
    }
}

@media (max-width: 400px) {
    .forge-topnav .nav-right { gap: 5px; }
}

@media (prefers-reduced-motion: reduce) {
    .forge-topnav,
    .forge-topnav *,
    .forge-topnav + .mobile-menu { transition-duration: .01ms !important; }
}

/* ── "Upgrade" CTA ────────────────────────────────────────────────────────
   Signed-in only: `.is-authed` is added by each page's auth sync, so a
   logged-out visitor is never upsold a plan they can't attach to an account.
   A single-hue violet lit from above, not the old violet→cyan ramp: a
   two-colour diagonal ramp plus a saturated glow is the stock "AI SaaS"
   button, and it read cheap next to the white-first homepage. Depth here
   comes from an edge and a grounded shadow instead of colour.
   The colour rules carry `.nav-links a` / `.nav-right a` specificity because
   both host navs set a muted link colour that otherwise wins. */

/* Both display rules need `.nav-links a` / `.nav-right a` specificity for the
   same reason the colour rules above do. `.forge-topnav .nav-links a` sets
   `display: inline-flex` and out-specifies a bare `.forge-topnav .nav-pro`
   (0,2,1 against 0,2,0) — so the `display: none` default never applied and the
   button showed for EVERYONE: logged-out visitors, and Pro subscribers who
   have nothing left to upgrade to. `.is-authed` was decorative. */
.forge-topnav .nav-links a.nav-pro,
.forge-topnav .nav-right a.nav-pro { display: none; }

/* "Host a quiz" is a teacher tool, so it waits for /auth/me to say `role:
   teacher` (marketing-nav.js / the homepage's syncHomepageAuth add .is-teacher).
   These pages are CDN-cached identically for every visitor, so this cannot be
   gated server-side — a Jinja branch would cache one visitor's nav for all of
   them. Same specificity note as .nav-pro above: `.nav-links a` is (0,2,1), so
   the default has to carry the class to win. */
.forge-topnav .nav-links a.nav-host { display: none; }
.forge-topnav .nav-links a.nav-host.is-teacher { display: inline-flex; }

/* The app nav is the crowded one (streak, score, dashboard, avatar), so the
   label eventually has to go — but keep it as long as possible: icon-only,
   this is just a violet pill sitting next to another violet pill (Join) with
   nothing to say what it does. 820px is where the nav actually runs out of
   room, and below 640px it moves into the mobile menu anyway. */
@media (max-width: 820px) {
    .forge-topnav .nav-pro { padding: 0 11px; gap: 0; }
    .forge-topnav .nav-pro .nav-pro-label { display: none; }
}

/* Deliberately still visible on phones. It was hidden below 640px at first,
   with the mobile menu carrying it — but behind the hamburger it may as well
   not exist, and phones are where most of these students actually study. */
@media (max-width: 640px) {
    /* Once the labels drop, every control here is an icon in a shape — so give
       them all the same shape. The dark toggle and hamburger were already
       36px circles; Join kept `padding: 0 15px` and `min-width: 40px` from its
       labelled state and rendered 45x36, a stretched blob next to them, and
       Upgrade came out 32x36. Square them both to match. */
    .forge-topnav .nav-pro,
    .forge-topnav .nav-pro.is-authed,
    .forge-topnav .nav-create:not(.host) {
        width: 36px;
        min-width: 36px;
        height: 36px;
        min-height: 36px;
        padding: 0 !important;
        gap: 0;
        justify-content: center;
        border-radius: 12px !important;
    }
}

/* ── The tile has to carry the button on its own now ──
   With the label gone this is a solid violet square with a 14px mark floating
   in the middle of it — the SMALLEST glyph in the bar (the theme toggle draws
   17px, the account avatar 34) sitting inside the only control loud enough to
   need one. Two thirds of the tile is empty violet, so beside two outlined
   buttons it reads as a swatch rather than as something to press.

   Size the mark to the tile, and give the tile the edge-and-shadow this
   file's own opening comment describes — "depth comes from an edge and a
   grounded shadow instead of colour" — which the pill never actually had at
   any size. Tight and neutral rather than a violet glow: the point is a
   raised key, not a lit-up chip.

   Both `:hover` and the dark-mode rule above are (0,3,0) and would otherwise
   win, and a tap on a phone can leave `:hover` stuck on — which is exactly
   where `box-shadow: none` would flatten the tile again. So both are
   restated here at matching specificity, and win on source order. */
@media (max-width: 640px) {
    .forge-topnav .nav-pro svg {
        width: 19px;
        height: 19px;
    }

    .forge-topnav .nav-pro,
    .forge-topnav .nav-pro:hover {
        box-shadow:
            0 1px 2px rgba(16, 12, 60, .2),
            0 2px 6px -3px rgba(16, 12, 60, .28),
            inset 0 1px 0 rgba(255, 255, 255, .26),
            inset 0 -1px 0 rgba(16, 12, 60, .18);
    }

    /* Pressed: the key goes down into the bar rather than shrinking away from
       it. `:active` keeps the existing scale, this just drops the lift. */
    .forge-topnav .nav-pro:active {
        box-shadow: inset 0 1px 2px rgba(16, 12, 60, .3);
    }

    /* Dark: the bar is near-black, so a shadow does nothing and the top edge
       is the whole read. Lift it, and drop the cast shadow that is invisible
       anyway. */
    [data-dark] .forge-topnav .nav-pro,
    [data-dark] .forge-topnav .nav-pro:hover {
        box-shadow:
            inset 0 1px 0 rgba(255, 255, 255, .34),
            inset 0 -1px 0 rgba(0, 0, 0, .28);
    }

    [data-dark] .forge-topnav .nav-pro:active {
        box-shadow: inset 0 1px 2px rgba(0, 0, 0, .38);
    }
}

/* Thin the phone nav out. Logo plus five circles is too much at 390px, and
   the icon-only ones are indistinguishable at a glance anyway. Join goes,
   because the side menu lists "Join a live game" as its own row — the dark
   toggle stays, since the menu has no theme control and Settings is two taps
   deep. Leaves logo + Upgrade, account, theme, menu. */
/* Join leaves at 600 rather than 560: at 561-600 the bar is still carrying
   the brand wordmark, the allowance ring and five controls, and Join is the
   one of them the side menu already lists ("Join a live game"). */
@media (max-width: 600px) {
    .forge-topnav .nav-right .nav-create:not(.host) { display: none; }
}

@media (max-width: 560px) {
    /* ── The wordmark is the 110px the phone nav did not have ──
       Thinning the RIGHT-hand controls was only ever half the budget. The
       left-hand brand is a 30px mark plus "ATARprepAI" set at 1rem, and at
       390px that wordmark is most of the difference between a row that fits
       and one whose hamburger renders past the edge of the screen. It is also
       the cheapest thing in the bar to lose: the mark is still the link home,
       and it is the more recognisable half of the brand anyway.

       Clipped rather than `display: none`, because the app nav's mark carries
       alt="" — hiding the text outright would leave that link with no
       accessible name at all. This is out of flow, so it costs no width. */
    .forge-topnav .nav-logo > span,
    .forge-topnav .nav-brand-name {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        border: 0;
    }

    /* With the label gone the link would collapse to the 30px mark; the tap
       target has to stay 44px like the toggle and burger beside it. */
    .forge-topnav .nav-logo,
    .forge-topnav .nav-brand {
        min-width: 44px;
        justify-content: center;
        gap: 0;
    }

    /* The app's allowance readout: same ring and figure, phone padding. */
    .forge-topnav .nav-usage { margin-left: 6px; }
    .forge-topnav .nav-usage-btn { padding: 3px 9px 3px 4px; gap: 5px; }
    .forge-topnav #navStreakPill { padding: 5px 9px; }

    /* Touch targets. These sit at 36px,
under the 44px minimum,
and on a phone
       the burger is the ONLY route into navigation. Widened here rather than
       per-page: this component is shared by the homepage,
the app,
subject and
       teacher pages,
.forge-topnav .nav-burger,
.forge-topnav .hamburger{
        width: 44px;
        height: 44px;
        min-width: 44px;
    }

    /* The same 44px floor for the other two controls in this row.
       The rule above raised the toggle and the burger and stopped there, but
       Upgrade (36px) and the account avatar (34px) are tap targets in the same
       bar — and being the only two left short is also what made the row look
       wrong: four controls in three sizes, with the two loudest ones the
       smallest. Between 401 and 560px, which is every phone, you got a 36px
       violet tile and a 34px white disc beside two 44px buttons.

       Only the hit area grows. Upgrade keeps its 12px tile and the account
       keeps its circle — an avatar reads as an identity, not an action, and
       that difference is deliberate once the sizes agree. The avatar disc
       stays 34px centred inside the 44px target, so the brightest object in
       the bar does not gain weight it has not earned. */
    .forge-topnav .nav-pro,
    .forge-topnav .nav-pro.is-authed,
    .forge-topnav .nav-user-pill {
        width: 44px;
        min-width: 44px;
        height: 44px;
        min-height: 44px;
        align-items: center;
        justify-content: center;
    }

    /* ── Attached, and it stays put ──
       Two complaints, one bar. It read as DETACHED: a rounded pill inset from
       both sides and floating 10px below the top of the content viewport, with
       the page scrolling through that gap behind it. And it DISAPPEARED: the
       hide-on-scroll slid it off screen while reading, taking the burger —
       which at this width is the only route into navigation — with it.

       Flush to the top edge, full width, rounded on the bottom only, so the
       bar meets the browser chrome instead of hovering under it.

       Deliberately no env(safe-area-inset-*) here: the page does not set
       viewport-fit=cover, so the content viewport already starts below the
       status bar and the inset is not a length this layout can trust — an
       earlier draft that mixed it in made the bar and the drawer disagree by
       18px. If viewport-fit=cover is ever added, this rule is where the inset
       belongs, on both the height and the drawer's top.

       Both variants. The app nav was left floating at first and showed the
       same fault the moment the page scrolled: content passing through the
       gap above and beside the pill reads as the bar being broken, and on
       /app the first thing to do it is the signed-out free-quiz banner —
       which is why it looked fine again once you signed in. */
    .forge-topnav {
        top: 0;
        left: 0;
        right: 0;
        width: 100%;
        transform: none;
        border-top: none;
        border-left: none;
        border-right: none;
        border-radius: 0;
    }

    /* The one navigation entry point on a phone is never taken away. These
       match the hide rules' specificity and win on source order. */
    .forge-topnav.nav-hidden,
    .forge-topnav.nav-hidden:focus-within,
    .forge-topnav.m-nav-hidden {
        transform: none;
    }
}

/* ── Give the wordmark back, but only where it provably fits ──
   The clip above is sized for the APP nav, which carries Upgrade, the account
   pill, the allowance ring and the streak alongside the theme toggle and the
   burger — there the wordmark really is the difference between a row that fits
   and a hamburger off the edge. The MARKETING nav (homepage, subject, teach)
   carries four things on a phone: mark, theme, one CTA, menu. It has room.

   Measured on the marketing bar, worst case being the signed-in CTA ("My
   account", 107px — wider than "Sign up" at 78px), against 99px of wordmark
   plus an 8px gap:
       375px -> 104px free, 3px SHORT, so it stays clipped
       390px -> 119px free, 12px spare
   Hence the 390px floor. "· Ask Avi" is dropped in this range: the name alone
   is the identity, and the qualifier is what stops it fitting. */
@media (min-width: 390px) and (max-width: 560px) {
    .forge-topnav--marketing .nav-logo > span {
        position: static;
        width: auto;
        height: auto;
        margin: 0;
        overflow: visible;
        clip: auto;
    }
    .forge-topnav--marketing .nav-logo {
        min-width: 44px;
        justify-content: flex-start;
        gap: 8px;
    }
    .forge-topnav--marketing .nav-logo .brand-sub { display: none; }
}

/* The last cut, for 320-400px phones. Six controls still do not fit there —
   the wordmark is already gone and the pills are already circles — and
   Upgrade is the only one of them with somewhere else to be: both menus
   carry it as a row (#menuPro in the app, #mmPro on the marketing pages),
   revealed for exactly the same signed-in non-Pro visitor this pill is. The
   allowance ring, the streak, the theme toggle and the burger have no second
   home anywhere in the app, so they stay.

   Down here rather than with the other 400px rules above, because it has to
   come after `.nav-pro.is-authed { display: inline-flex }` — same
   specificity, so source order is what decides it. */
@media (max-width: 400px) {
    .forge-topnav .nav-links a.nav-pro,
    .forge-topnav .nav-links a.nav-pro.is-authed,
    .forge-topnav .nav-right a.nav-pro,
    .forge-topnav .nav-right a.nav-pro.is-authed { display: none; }
}

@media (prefers-reduced-motion: reduce) {
}

/* Quiet search chrome; the primary study action retains the brand accent. */
.forge-topnav .nav-search input {
    border-color: transparent;
    border-radius: 8px;
    background: #f5f5f8;
    font-size: .8125rem;
}
.forge-topnav .nav-search input:focus { border-color: #5b50e8; background: #fff; }
[data-dark] .forge-topnav .nav-search input { background: #24242b; border-color: transparent; }
[data-dark] .forge-topnav .nav-search input:focus { border-color: #b9b2ff; }

/* Cached public pages start signed out; reveal dashboard navigation only
   after the session check succeeds. Leave responsive display rules intact. */
body:not(.is-signed-in) [data-auth-dashboard] { display: none !important; }
