/* shell.css — the ONE shell stylesheet (admin.html + portal.html; was admin-shell.css until 2026-09-13).
   Everything visual lives in the book (dialed-tokens/ui/skins). This file holds
   ONLY: (a) the LAW 12 role gate, (b) shell plumbing (iframe), (c) legacy-only
   vars still read by the Pearl chat widget (its own slice migrates them out). */

/* ACCESS GATE (Elle 2026-07-15, LAW 12 hide-not-disable): Team surface is
   admin-only; hidden from first paint, revealed only for confirmed admins. */
body:not(.role-admin) [data-page="team"] { display: none !important; }
/* the Pearl model pick is Owner (Dialed) only (T0, 2026-09-13; pearl-chat is the server truth) */
body:not(.role-owner) #pearlModelSelect { display: none !important; }

:root {
            /* Mother of Pearl Iridescent Theme */
            --bg-warm: #F9F7F5;
            --bg-cream: #FEFDFB;

            /* Sidebar - Deep Iridescent Purple-Black */
            --sidebar-accent: #4D4258;

            /* Iridescent Accent Colors */
            --iridescent-pink: #E8C4D0;
            --iridescent-gold: #D4C4A8;
            --iridescent-blue: #A8D4E6;

            /* Text */
            --text-light: #A8A0B0;

            /* Pearl Palette */
            --pearl-blush: #FDF8F6;
            --pearl-champagne: #F5EFE6;
            --pearl-taupe: #E8E0D8;

            /* Borders */
            --border-gold: var(--iridescent-gold);
            --border-hover: #D4C4A8;

            /* Iridescent Tints */
            --tint-blue: rgba(168, 212, 230, 0.25);
            --tint-pink: rgba(232, 196, 208, 0.25);
            --tint-lavender: rgba(184, 169, 201, 0.2);
            --tint-teal: rgba(125, 211, 192, 0.15);
            --tint-gold: rgba(212, 196, 168, 0.3);
            --tint-rose: rgba(232, 196, 208, 0.2);
            --tint-champagne: rgba(212, 196, 168, 0.25);

            /* Status */
            --info: #5A9BB5;
            --info-bg: #EDF6F9;

            /* Shadows - Purple-tinted */
            --shadow-sm: 0 1px 3px rgba(45, 36, 56, 0.06);
            --shadow-md: 0 4px 12px rgba(45, 36, 56, 0.08);
            --shadow-lg: 0 8px 30px rgba(45, 36, 56, 0.1);
            --shadow-iridescent: 0 4px 20px rgba(125, 211, 192, 0.15);

            /* Typography */
            --font-display: 'Satoshi', sans-serif;
            --font-body: 'Inter', sans-serif;

            /* Radius */
            --radius-sm: 8px;
            --radius-md: 12px;
            --radius-lg: 16px;
        }

/* THE SHELL DOES NOT SCROLL. ONLY THE PAGE INSIDE IT DOES.
   Elle 2026-08-06: "the searchbar ... should be fixed. currently its scrolling
   with the page floating ... nothing can scroll above the rail top height and
   bottom height."
   It scrolled because main was TALLER than the viewport: a topbar plus a 100vh
   iframe overflows by exactly the topbar's height, so the document scrolled and
   carried the topbar away. main is now a fixed-height column — topbar holds its
   size, the frame takes the rest — and the shell itself never scrolls at all.
   The inset matches the RAIL's own bounds (it is centred with --sp-8 of slack,
   so --sp-4 top and bottom), which is what makes nothing pass above the rail's
   top edge or below its bottom edge. */
/* overflow CLIP, never only hidden (2026-09-23): a hidden box is still a scroll container that CODE can scroll, so a
   scrollIntoView or a focus() inside the page frame (opening a program, an input) scrolled this column 35-72px and
   carried the frame up with it: a sheet's ✕ went off the top and a bare band opened at the bottom (the audit's
   "bare band"). clip paints the same and cannot be scrolled by anything; hidden stays as the fallback. */
.main-content { flex: 1; position: relative; display: flex; flex-direction: column;
  height: 100dvh; overflow: hidden; overflow: clip;
  /* LEFT padding clears the FLOATING rail — .dl-shell's own value. Zeroing it
     put the page under the rail and cut the search field. Top and bottom match
     the rail's own inset so nothing passes above or below it. */
  padding: var(--sp-4) var(--sp-4) var(--sp-4) calc(var(--dl-rail-w) + var(--sp-12)); }
.content-frame { width: 100%; flex: 1 1 auto; height: auto; min-height: 0;
  border: none; background: transparent; border-radius: var(--r-xl);
  /* LAW D11 — NO SHAPE BEHIND THE SHAPES (Elle 2026-08-23: "there's still a
     border background containing all the other containers ... it's like a
     shape behind the shapes in front of the actual glass background, so
     there must be a law that that must not exist on any page portal or
     admin"). Between the ambient canvas and a page's OWN components,
     NOTHING paints: the frame carries no background, border, shadow or
     blur, in either shell. Admin removed this container deliberately; two
     cures for the portal C- (a wash, then glass) reintroduced it and were
     both wrong — the page's components are the only shapes on the mesh.
     Sparse pages are fixed by composing the PAGE, never by wrapping it. */
  /* ABOVE the shell scrim (z-index 70) so a modal inside this frame is never
     covered by the shell's half of its own backdrop, and above the rail (60) is
     deliberate too: with a modal open the dialog outranks the navigation. */
  position: relative; z-index: 80; }

/* LAW D8.2 — the topbar FLOATS: inset from frame top + right edge, never glued.
   It is flex:0 0 auto now, so it holds its height while the frame takes the rest. */
.main-content .dl-topbar{flex:0 0 auto;margin:0 0 var(--sp-4) 0;
  transition:transform .22s ease, opacity .22s ease}
/* THE DISAPPEARING BAR. Scrolling DOWN inside the page hides it; the smallest
   scroll UP brings it back, so it is never more than one flick away and never in
   the way of what you are reading. */
.main-content[data-bar="hidden"] .dl-topbar{
  transform:translateY(calc(-100% - var(--sp-4)));opacity:0;pointer-events:none}
.main-content[data-bar="hidden"] .content-frame{margin-top:calc(-1 * (var(--h-md) + var(--sp-4) + var(--sp-4)))}

/* THE HOST CAN NEVER BE PANNED (Elle 2026-08-28, "still same glitch bug on
   scroll and blocked wasted space that expands and shrinks"). The gap above
   the nav was the DOCUMENT itself: iOS chains a scroll out of the content
   iframe when the inner scroller hits its edge, pans the host document, and
   fires none of the events that would heal it — the in-flow shell lifts off
   the fixed tab bar by exactly the pan, a gap that grows and shrinks per
   gesture. A position:fixed body has no scrollable overflow AND no
   rubber-band, so the pan is impossible by construction — the iOS-proof
   scroll lock. Mobile only: the desktop shell already never scrolls. */
@media (max-width: 768px) {
  body {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100dvh;
    overflow: hidden;
    overscroll-behavior: none;
  }
}

/* THE FRAME ENDS AT THE NAV BY FLEX, NOT BY A PINNED HEIGHT (Elle
   2026-08-28). The column is 100dvh (tracks Safari's chrome in CSS); the
   tab-bar clearance is column padding (--mtb-clear, kept fresh by the
   shell's measure); the frame is flex:1 1 auto and simply fills what
   remains — through topbar hide/show, chrome collapse, everything. A pinned
   px height was only ever right for the layout it was measured in: hiding
   the topbar freed 72px the pinned frame could not absorb — the
   expanding/shrinking gap above the nav. */
@media (max-width: 768px) {
  .main-content { padding-bottom: var(--mtb-clear, 62px); }
}

/* Apple top band (Elle 2026-08-29): the topbar's gap below halves on mobile —
   .main-content .dl-topbar outranks dialed-ui's mobile rule, so the override
   lives at the same specificity. */
@media (max-width: 900px) {
  .main-content .dl-topbar { margin-bottom: var(--sp-2); }
}

/* (this sheet was css/admin-shell.css until 2026-09-13: it is the ONE shell sheet, admin.html and portal.html both)

/* ── SHELL RULES THAT LIVED IN css/pearl-chat-widget.css (moved 2026-09-13
   when that sheet died with the dl-pc-dock migration; they were never the
   widget's). Verbatim geometry, values on the scale. ── */

/* E1 (Elle 2026-07-10: "top of the email page is unclickable") — in the
   INSTALLED PWA (standalone) the iOS status bar overlays the viewport top
   (viewport-fit=cover) and every page's header row sat under it: visible,
   dead to taps. The shell absorbs the inset once so every iframe page
   inherits a clear top edge. Browser-tab use: env() = 0, no-op. */
@media (display-mode: standalone) {
  .main-content { padding-top: calc(env(safe-area-inset-top, 0px)) !important; }
}

@media (max-width: 768px) {
  /* 2026-07-20 LAW 46: the frame's inner viewport ENDS AT THE TAB-BAR TOP via
     height, never via padding — a padded clearance made every in-page fixed
     bottom bar float 96px in the air and painted a phantom band over the last
     row. One geometry, never toggled; pages treat "bottom: 0" as flush on the
     nav. */
  .content-frame { padding-bottom: 0 !important; box-sizing: border-box; }
  /* an open compose owns the screen (Apple Mail covers the tab bar); atomic
     toggle via dialed:compose-state */
  body.compose-owns-screen #mobileTabBar { display: none !important; }

  /* 2026-07-11 (Elle: "one background… pearly blended pretty movement"): the
     frame is EDGE-TO-EDGE, the shell paints the same pearl world as the pages
     with three slow orbs under the glass tab bar (LAW 9 cadence). The column
     padding IS the fit (2026-08-28): --mtb-clear is measured by the shell. */
  .main-content {
    padding: env(safe-area-inset-top, 0px) 0 var(--mtb-clear, 54px) !important;
    position: relative;
    overflow: hidden; overflow: clip;
    background:
      radial-gradient(ellipse at 15% 8%, color-mix(in oklab, var(--accent), transparent 90%) 0%, transparent 45%),
      radial-gradient(ellipse at 85% 92%, color-mix(in oklab, var(--teal), transparent 90%) 0%, transparent 45%),
      linear-gradient(180deg, var(--surface) 0%, var(--canvas) 100%) !important;
  }
  .main-content::before,
  .main-content::after {
    content: '';
    position: absolute;
    border-radius: 50%;
    pointer-events: none;
    z-index: 0;
    filter: blur(28px);
  }
  .main-content::before {
    width: 240px; height: 240px; left: -70px; bottom: -60px;
    background: radial-gradient(circle at 35% 35%, color-mix(in oklab, var(--accent), transparent 78%), color-mix(in oklab, var(--teal), transparent 90%) 60%, transparent 75%);
    animation: dialedOrbA 26s ease-in-out infinite;
  }
  .main-content::after {
    width: 200px; height: 200px; right: -60px; bottom: -40px;
    background: radial-gradient(circle at 60% 40%, color-mix(in oklab, var(--teal), transparent 82%), var(--glass-hi) 55%, transparent 78%);
    animation: dialedOrbB 32s ease-in-out infinite;
  }
  @keyframes dialedOrbA {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50% { transform: translate(46px, -30px) scale(1.12); }
  }
  @keyframes dialedOrbB {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50% { transform: translate(-40px, -22px) scale(1.08); }
  }
  @media (prefers-reduced-motion: reduce) {
    .main-content::before, .main-content::after { animation: none; }
  }
  .content-frame { position: relative; z-index: 1; border-radius: 0 !important; display: block; }
  /* 2026-07-11 (Elle: "emails footer bar is cut off the bottom") — the frame
     subtracts the notch AND the tab-bar zone so its bottom edge is the nav
     top; _fitContentFrame refines this with the measured tab-bar height. */
  .content-frame { height: calc(100dvh - env(safe-area-inset-top, 0px) - 54px - env(safe-area-inset-bottom, 0px)) !important; }
}
/* T1/T8 (2026-09-14): the rail hides what role_capabilities does not grant (el.hidden set by
   paintCapabilityGates; the role classes stay as the stand-in until the grid arrives) */
body:not(.role-admin) [data-page="analytics"], body:not(.role-admin) [data-page="comms-center"], body:not(.role-admin) [data-page="pearl-playbook"] { display: none !important; }
.nav-item[hidden] { display: none !important; }
/* View as: one band, fixed above everything, the Owner's only */
.dl-viewas { position: fixed; left: 50%; top: calc(env(safe-area-inset-top, 0px) + 8px); transform: translateX(-50%); z-index: 10050; display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-2) var(--sp-4); border-radius: 999px; background: var(--pearl-white, #FDFCFA); color: var(--text-primary); border: 1px solid var(--accent); box-shadow: 0 8px 24px rgba(28, 28, 30, .12); font-size: var(--fs-sm); max-width: calc(100vw - 32px); }
.dl-viewas b { font-weight: 600; }

/* NO HARD CUT AT THE SCROLL EDGE (Elle 2026-09-23: "the bottom of the section that scrolls is sharp corners and everything
   should be curved"). The frame's own corners were round, but a card scrolled past the frame's bottom was sliced straight
   across. Content now dissolves into the glass over the last 28px (Apple's scroll-edge fade), desktop shell only; while a
   modal is open the fade is off so a sheet's footer never dims. */
@media (min-width: 901px){
  /* LAWFUL-FADE: the desktop content frame IS the page's vertical scroller at >=901px (the page scrolls inside it and cards
     pass under its bottom edge); the fade covers only the last 28px of that scroll edge and is off while a modal is open. */
  .main-content .content-frame{
    -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent 100%);
            mask-image: linear-gradient(to bottom, #000 calc(100% - 28px), transparent 100%); }
  body.dl-modal-scrim-open .main-content .content-frame,
  body.dl-veiled .main-content .content-frame{ -webkit-mask-image:none; mask-image:none; }
}
