/* ============================================================================
   app-shell.css — the universal authenticated PRODUCT chrome (nav/IA overhaul).
   A floating left RAIL CARD on desktop/tablet that collapses to a responsive
   off-canvas DRAWER on mobile, both rendered from the ONE AppNavRegistry.
   Loaded app-wide via site.css; the rail only renders where AppNavRail has
   content (an entitled product area), so this is inert everywhere else.

   LAYOUT (owner-directed 2026-07-27, rev 2 — "the whole page has to fit within
   that header alignment; it must float in the page design, not be slapped against
   the far-left edge"): the rail+content SHELL rides the EXACT SAME horizontal
   spine as the top header (.topnav-container) and the footer (.platform-footer-inner)
   — capped at --platform-content-width, centered (margin-inline:auto), with the
   header's own 0.9rem inline padding. So the rail's left edge lands under the brand
   logo and the content's right edge under the user menu: header, body, and footer
   share ONE alignment spine. The rail is a rounded, elevated PANEL floating on the
   area background — part of the page composition, world-class, not an edge-flush
   sidebar. (rev 1 capped the CONTENT column at --platform-content-width and added
   the rail+gutters OUTSIDE it, pushing the shell ~300px wider than the header spine
   — the incoherence the owner rejected on sight. The rail now sits INSIDE the spine,
   so the content column is the spine minus the rail+gap, and everything aligns.)

   AREA-ADAPTIVE THEMING: this sheet owns only the rail STRUCTURE + a set of
   semantic --app-rail-* tokens with SAFE GENERIC defaults (every default is a
   platform token from base.css — no raw hex here). Each product area REASSIGNS
   those tokens scoped to its body class, IN ITS OWN STYLESHEET, so the rail
   inherits that area's palette for visual continuity with the surface it sits on.
   The palette follows the BODY-CLASS SURFACE, not the nav AREA (several areas share
   a surface), so:
     • crm-app  → wwwroot/css/Crm/modules/_base.css   (body.crm-app; green + auto
                  dark-flip via --crm-*). BOTH the CRM area AND the Kinetic/Leads area
                  carry `client-app crm-app` (Kinetic reuses the CRM shell + status-
                  banner mechanism — _Layout isCrmApp branch), so crm.css loads last
                  and the rail reads GREEN on CRM *and* Kinetic. They share the surface;
                  the active-area switcher, not the accent, distinguishes them.
     • client-app-only → wwwroot/css/ClientApp/client-base.css (body.client-app; blue,
                  light-only — Social + Branding, which do NOT carry crm-app).
     • admin    → wwwroot/css/Admin/modules/_base.css (body.admin-page; +.theme-dark).
   So the rail reads GREEN on the crm-app surface (CRM + Kinetic), BLUE on the
   client-app-only surface (Social + Branding), and the admin palette on /Admin —
   flipping with each surface's dark mode automatically. No per-area rules here, no
   hardcoded color. (Making Kinetic blue would require decoupling it from the crm-app
   shell — a larger change, owner's call — not a rail concern.)
   A distinct CSS domain (CSS_ARCHITECTURE Domain 6): no !important, no override
   of other domains — every selector is new (.app-*).
   ============================================================================ */
:root {
    --app-rail-w: 236px;
    --app-rail-radius: 8px;
    --app-shell-gap: 1rem;       /* ONE shell rhythm unit (16px): rail↔content gap = header→first-card = card↔card. Owner-directed 2026-07-27: every shell gap is this single value so the layout reads as an intentional grid, never three mismatched gaps. */
    --app-shell-pad-top: 1rem;   /* header bottom → content/rail top = the same 16px unit */
    /* The content column's inner wrapper (.client-page-inner / .admin-page-inner) carries its own
       top padding, which pushes the first content CARD down; the rail card has none, so their TOP
       EDGES misalign. This offsets the rail card down by the SAME amount so the two card tops line
       up. Per-surface: client 0 (the client inner's top padding is now 0 — --app-shell-pad-top owns
       the whole header→content gap on the client surface), admin 0.75rem (body.admin-page override
       below; admin-page-inner keeps its own top padding, so the admin rail still needs the offset). */
    --app-shell-inner-pad-top: 0;
    --app-shell-pad-side: 0; /* 0 so the rail + content CARDS sit FLUSH to the spine edges (=
                                the header card's outer edges, 113/1313 @1440); the header's own
                                0.9rem is its INTERNAL padding, mirrored by the rail card's own
                                inner padding — so the cards line up edge-to-edge, not inset. */

    /* Semantic rail tokens — GENERIC DEFAULTS (platform tokens only; each area
       overrides these on its body class). Kept blue-neutral so an unthemed
       authenticated surface still renders a coherent rail. */
    --app-rail-bg:        var(--white);
    --app-rail-border:    var(--gray-300);
    --app-rail-fg:        var(--gray-800);
    --app-rail-fg-muted:  var(--gray-550);
    --app-rail-hover-bg:  var(--gray-100);
    --app-rail-accent:    var(--primary-blue);
    --app-rail-on-accent: var(--white);
    --app-rail-active-bg: color-mix(in srgb, var(--primary-blue) 12%, var(--white));
    --app-rail-active-fg: var(--primary-blue);
    /* Card elevation — neutral-black rgba is the sanctioned shadow escape hatch. */
    --app-rail-shadow:    0 1px 2px rgba(0, 0, 0, 0.04), 0 10px 30px rgba(0, 0, 0, 0.07);
}

/* Admin surface: .admin-page-inner's top padding is 0.75rem (vs the 0.6rem client default), so the
   admin rail needs the larger top offset to align its card top with the first admin card. This lives
   HERE (the reliably-served shell sheet in the site.css chain) and NOT in Admin.css's @import chain:
   Admin.css is fingerprinted as a unit, so editing an @imported module (modules/_base.css) does not
   change Admin.css's hash and the stale bundle keeps being served to returning browsers. */
body.admin-page {
    --app-shell-inner-pad-top: 0.75rem;
    /* admin-page-inner (Admin/modules/_layout.css) adds 0.75rem of its OWN top padding above the first
       admin card, which the client surface does not. So the admin shell reduces its pad-top by that
       amount (1rem unit − 0.75rem inner pad = 0.25rem) to keep header→content at the SAME 16px unit as
       every other surface. Kept in this reliably-served shell sheet, not the @import-stale Admin bundle. */
    --app-shell-pad-top: 0.25rem;
}

.app-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr); /* single column by default (and when no rail renders) */
    align-items: start;
    gap: 0;
}

/* Desktop/tablet: a CENTERED two-column composition ONLY when the rail is
   actually present (a no-service tenant, or a page outside any product area,
   renders no .app-rail → the shell stays a plain single column). The shell is
   capped at the SAME --platform-content-width the header + footer use and
   centered with ZERO inline padding, so the rail CARD's outer edge sits FLUSH to
   the header CARD's outer edge (left) and the content CARD's outer edge sits flush
   to the header card's right edge — header/body/footer read as one aligned stack,
   not a rail inset inside the header's footprint. The rail (--app-rail-w) + gap
   live INSIDE the spine, so the content column is the spine minus the rail. */
@media (min-width: 901px) {
    .app-shell:has(.app-rail) {
        grid-template-columns: var(--app-rail-w) minmax(0, 1fr);
        gap: var(--app-shell-gap);
        /* The shared alignment spine (base.css --platform-spine-w). Defaults to
           --platform-content-width, so the rev-2 composition described above is unchanged on
           every surface that does not widen it; admin widens the spine for header, rail,
           content AND footer together, so the stack stays aligned at the wider measure. */
        max-width: var(--platform-spine-w);
        margin-inline: auto;
        padding: var(--app-shell-pad-top) var(--app-shell-pad-side) 2rem;
        box-sizing: border-box;
    }

    /* THE SPINE IS NOT WIDENED FOR DATA PAGES, DELIBERATELY — and the reason is recorded here
       because it is the obvious fix and it is the wrong one.

       DIAGNOSIS (owner 2026-08-07: "the admin tables were working well before, I'm not sure how
       they broke"): they broke HERE. This rail was introduced INSIDE the pre-existing
       --platform-content-width cap. Admin pages previously had no rail, so a table got the
       whole 1200px; afterwards the rail (236px) + gap (16px) come out of that same 1200px,
       leaving 948px — the exact content width measured on prod, where /Admin/Users crushed
       every email into 59px. All 42 admin tables silently lost 21% of their width to a change
       that was about navigation.

       WHY NOT JUST WIDEN THE CAP: the header comment above records the owner's rev-2 ruling
       that the shell rides the SAME horizontal spine as the header and footer, and that rev 1 —
       which pushed the shell ~300px wider than that spine — was "the incoherence the owner
       rejected on sight." A wider cap on data pages is that same shape. Reversing a documented
       owner decision without asking is exactly what Tier 1 Rule 16 forbids, so the width is
       recovered INSIDE the spine instead: `.admin-table` carries a readability floor
       (--table-min-w) and its wrapper scrolls, so no column is crushed and no alignment moves.
       If the owner would rather have the pixels back and accept a wider shell on
       table-dominated pages, that is a one-line change here — it needs their call, not mine. */
}

.app-shell-content {
    min-width: 0; /* let the content column shrink; its own inner keeps max-width */
}

/* The rail is a floating, rounded, elevated CARD that sits on the area
   background (a gutter from the viewport edge, a gap to the content). */
.app-rail {
    position: sticky;
    top: var(--app-shell-pad-top);
    align-self: start;
    margin-top: var(--app-shell-inner-pad-top); /* align the rail card's TOP edge with the first content card */
    max-height: calc(100vh - (2 * var(--app-shell-pad-top)));
    overflow-y: auto;
    scrollbar-width: thin; /* a quiet scrollbar on the long (admin) rail, not a chunky one */
    background: var(--app-rail-bg);
    border: 1px solid var(--app-rail-border);
    border-radius: 14px;
    box-shadow: var(--app-rail-shadow);
    padding: 0.85rem 0.7rem 1.1rem;
}

/* Cross-area switcher (CRM · Social · Leads …) at the top of the rail. */
.app-rail-areas {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding-bottom: 0.6rem;
    margin-bottom: 0.5rem;
    border-bottom: 1px solid var(--app-rail-border);
}

.app-rail-area-link {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.5rem 0.6rem;
    border-radius: var(--app-rail-radius);
    color: var(--app-rail-fg);
    text-decoration: none;
    font-size: 0.92rem;
    font-weight: 600;
}

.app-rail-area-link:hover { background: var(--app-rail-hover-bg); }

.app-rail-area-link.is-active {
    background: var(--app-rail-active-bg);
    color: var(--app-rail-active-fg);
    box-shadow: inset 3px 0 0 var(--app-rail-accent); /* accent bar; no layout movement */
}

/* Active-workspace label above the sub-nav (a small accent eyebrow so the
   section list reads as "you are in <area>"). */
.app-rail-head { padding: 0.15rem 0.6rem 0.35rem; }

.app-rail-area {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    /* The active-workspace name is the TOP of the rail's hierarchy — it must not be smaller than the
       section headers below it (0.9rem). Matches them in size/weight; the accent color + tracking keep it
       reading as the workspace label. (Admin is the only surface that shows this — the others use the switcher.) */
    font-size: 0.9rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--app-rail-accent);
}

/* Tight WITHIN a group; the section-title's top margin does the BETWEEN-group spacing,
   so items read as clearly nested under their header (the header owns the rhythm). */
.app-rail-body { display: flex; flex-direction: column; gap: 0.15rem; }

.app-rail-section { display: flex; flex-direction: column; gap: 0.05rem; }

/* Section headers ANCHOR their group and must read as HEADERS, never as shrunken labels
   (owner-directed 2026-07-27: a heading smaller than the items it heads is a design defect).
   So the label is NEVER smaller than its items (0.9rem, matching .app-rail-link), weight 700,
   and rendered in the AREA ACCENT color (green on CRM/Leads, blue on Social/Branding) — uppercase
   tracking makes it unmistakably a section header sitting above, not beside, its items. */
.app-rail-section-title {
    margin: 1rem 0.6rem 0.35rem;
    font-size: 0.9rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--app-rail-accent);
}

/* The first group hugs the top (the switcher/eyebrow above already spaces it). */
.app-rail-body > .app-rail-section:first-child .app-rail-section-title {
    margin-top: 0.15rem;
}

.app-rail-list { list-style: none; margin: 0; padding: 0; }

.app-rail-link {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.45rem 0.6rem;
    border-radius: var(--app-rail-radius);
    color: var(--app-rail-fg);
    text-decoration: none;
    font-size: 0.9rem;
    font-weight: 500;
    line-height: 1.2;
}

.app-rail-link:hover { background: var(--app-rail-hover-bg); }

.app-rail-link.is-active {
    background: var(--app-rail-active-bg);
    color: var(--app-rail-active-fg);
    font-weight: 600;
    box-shadow: inset 3px 0 0 var(--app-rail-accent); /* accent bar; no layout movement */
}

/* Icons render in their full natural color — a consistent 1.2rem glyph column so labels align. */
.app-rail-icon {
    flex: 0 0 auto;
    width: 1.2rem;
    text-align: center;
    font-size: 1rem;
    line-height: 1;
}

.app-rail-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Toggle + scrim only exist on mobile. */
.app-rail-toggle,
.app-rail-scrim { display: none; }

/* ---- Mobile: the rail becomes a full-height off-canvas drawer (edge-anchored,
   not the floating card). The drawer stack sits ABOVE the header's user-dropdown
   (position:relative; z-index:1002): the header is static so that dropdown competes
   in the ROOT stacking context, and at z-70 the drawer lost to it — the header's
   email button painted THROUGH the open drawer. FAB 1080 < scrim 1090 < drawer 1100,
   all above 1002, so the open drawer + scrim fully cover the header. ---- */
@media (max-width: 900px) {
    .app-shell { grid-template-columns: minmax(0, 1fr); }

    .app-rail-toggle {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        position: fixed;
        left: 0.9rem;
        bottom: 0.9rem;
        z-index: 1080;
        width: 2.75rem;
        height: 2.75rem;
        border-radius: 999px;
        border: none;
        background: var(--app-rail-accent);
        color: var(--app-rail-on-accent);
        font-size: 1.25rem;
        cursor: pointer;
        box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25);
    }

    .app-rail {
        position: fixed;
        top: 0;
        left: 0;
        z-index: 1100;
        margin-top: 0; /* the desktop card-top alignment offset is meaningless for the fixed drawer */
        width: min(84vw, var(--app-rail-w));
        height: 100vh;
        max-height: none;
        border: none;
        border-radius: 0;
        transform: translateX(-100%);
        transition: transform 0.22s ease;
        box-shadow: 2px 0 18px rgba(0, 0, 0, 0.2);
    }

    .app-shell.app-rail-open .app-rail { transform: translateX(0); }

    .app-rail-scrim {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 1090;
        background: rgba(0, 0, 0, 0.4);
    }

    .app-rail-scrim[hidden] { display: none; }
}

/* Print: navigation chrome never prints (platform-wide; each piece hidden in
   its owning sheet). This sheet owns the product rail + its mobile FAB/scrim;
   the shell grid collapses so content takes the full page width. */
@media print {
    .app-rail,
    .app-rail-toggle,
    .app-rail-scrim {
        display: none;
    }

    .app-shell {
        grid-template-columns: minmax(0, 1fr);
    }
}
