/* ── Hoppe.home Portal — Shared Frame CSS ──────────────────── */

/* ── Cascade layer ─────────────────────────────────────────────────────────
   Everything below is in the `hh.frame` layer. portal-ui.css is NOT layered,
   and unlayered normal declarations beat layered ones at ANY specificity, so
   the precedence is now a stated fact rather than an accident of which file
   the browser happened to read second:

       hh.frame  (this file)   the shell
       unlayered (portal-ui)   the components   -- always wins over the frame
       unlayered (page <style>)                 -- wins by source order, last

   This is why this file no longer needs a single `!important`. Thirteen of
   them existed to beat page-local copies of the sidebar; those copies were
   removed on 2026-09-05 and the layer makes sure the frame can never
   out-specify the component layer again.

   The page tier is deliberately NOT a third layer yet. Making it one would
   promote every page-local rule above portal-ui.css at any specificity, and
   34 pages still carry their own `.card`-family rules -- some would silently
   restyle. That is the next step, after those are swept, not this one. */
/* Declared here, in the file the browser reads first, so the order is a fact
   rather than a consequence of which stylesheet happened to load second. */
/* Three layers, in this order. hh.page is where every page's own <style>
   block now lives -- see the wrap in each page. Before 2026-09-06 those
   blocks were UNLAYERED, and an unlayered declaration beats every layer at
   any specificity: fourteen pages carried `* { margin:0; padding:0 }`, which
   is specificity ZERO and still stripped the padding off every sidebar row
   that portal-ui.css had set. That is the ~21px menu Joern kept seeing on
   some pages and not others -- the difference was simply whether the page
   had a reset. Layered, the reset loses to `.sidebar .nav-item` on
   specificity, which is the behaviour everyone assumes CSS already has. */
@layer hh.frame, hh.components, hh.page;

@layer hh.frame {

/* One template, all pages. Do NOT add page-specific rules here. */


:root {
    --bg:#1c2333; --surface:#212d40; --card:#1e2a3a; --card-hover:#243246;
    --topbar:#141d2c; --page-grad-start:#1a2438; --page-grad-end:#1c2333;
    --text:#e8f5ff; --strong:#ffffff; --muted:#a0b8d4;
    --accent:#4a9eff; --accent-lt:rgba(74,158,255,0.15); --accent-hov:#2e86eb;
    --border:#2a3c54;
    --ok:#3fb950; --warn:#f0b429; --err:#f85149;
    --ok-bg:rgba(63,185,80,0.13); --warn-bg:rgba(240,180,41,0.13); --err-bg:rgba(248,81,73,0.13);
    --shadow:0 4px 16px rgba(0,0,0,0.38); --shadow-sm:0 1px 4px rgba(0,0,0,.28);
    --shadow-md:0 8px 24px rgba(0,0,0,.40); --radius:12px;
}
[data-theme="light"] {
    --bg:#b8cce0; --surface:#c8d9e9; --card:#f4f8fc; --card-hover:#e6f0fa;
    --topbar:#a8bdd4; --page-grad-start:#c4d4e4; --page-grad-end:#b8cce0;
    --text:#0f1f30; --strong:#000000; --muted:#2a3f54;
    --accent:#176cc8; --accent-lt:rgba(23,108,200,0.12); --accent-hov:#0e59a7;
    --border:#b8cfe3;
    --ok:#1f8f42; --warn:#b37000; --err:#c43831;
    --ok-bg:rgba(31,143,66,0.12); --warn-bg:rgba(179,112,0,0.12); --err-bg:rgba(196,56,49,0.12);
    --shadow:0 4px 16px rgba(18,44,80,0.16); --shadow-sm:0 1px 6px rgba(18,44,80,.12);
    --shadow-md:0 8px 28px rgba(18,44,80,.16);
}
[data-theme="horde"] {
    --bg:#2a1013; --surface:#34161a; --card:#3c1a1f; --card-hover:#4a1f24;
    --topbar:#2d1216; --page-grad-start:#3c161d; --page-grad-end:#271014;
    --text:#ffeaea; --strong:#ffffff; --muted:#e2a9a9;
    --accent:#e24444; --accent-lt:rgba(226,68,68,0.20); --accent-hov:#ff5c5c;
    --border:#6a2a31;
    --ok:#7ed957; --warn:#ff9e2c; --err:#ff4b4b;
    --ok-bg:rgba(126,217,87,0.12); --warn-bg:rgba(255,158,44,0.14); --err-bg:rgba(255,75,75,0.16);
    --shadow:0 4px 16px rgba(30,8,10,0.42); --shadow-sm:0 1px 6px rgba(30,8,10,.34);
    --shadow-md:0 10px 28px rgba(30,8,10,.46);
}
[data-theme="horde-light"] {
    --bg:#f5e8e8; --surface:#faf3f3; --card:#fffbfb; --card-hover:#fff0f0;
    --topbar:#f0e5e5; --page-grad-start:#faf0f0; --page-grad-end:#f5e8e8;
    --text:#2a0a0a; --strong:#ffffff; --muted:#c24a4a;
    --accent:#d63030; --accent-lt:rgba(214,48,48,.15); --accent-hov:#b91e1e;
    --border:#e6bfbf;
    --ok:#1f8f42; --warn:#b37000; --err:#c43831;
    --ok-bg:rgba(31,143,66,.12); --warn-bg:rgba(179,112,0,.12); --err-bg:rgba(196,56,49,.12);
    --shadow:0 4px 16px rgba(120,10,10,.12); --shadow-sm:0 1px 4px rgba(120,10,10,.10);
    --shadow-md:0 8px 24px rgba(120,10,10,.16);
}
[data-theme="fusion"] {
    --bg:#1d2230; --surface:#222b3d; --card:#202a3a; --card-hover:#28354a;
    --topbar:#1a2232; --page-grad-start:#1f283a; --page-grad-end:#231724;
    --text:#dbe6f4; --strong:#ffffff; --muted:#8fa1ba;
    --accent:#7c59ff; --accent-lt:rgba(124,89,255,.18); --accent-hov:#6847e6;
    --border:#3b3f66;
    --ok:#3fb950; --warn:#f0b429; --err:#f85149;
    --ok-bg:rgba(63,185,80,.13); --warn-bg:rgba(240,180,41,.13); --err-bg:rgba(248,81,73,.13);
    --shadow:0 4px 16px rgba(20,10,30,.42); --shadow-sm:0 1px 6px rgba(20,10,30,.36);
    --shadow-md:0 10px 28px rgba(20,10,30,.45);
}

*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:"Segoe UI",-apple-system,Helvetica,Arial,sans-serif;font-size:14px;
    background:linear-gradient(160deg,var(--page-grad-start) 0%,var(--page-grad-end) 100%) fixed;
    color:var(--text);min-height:100vh;display:flex;}

/* ── Sidebar ─── */
/* Tokens, not hex. These four rules hard-coded the August pale-blue panel, so
   the frame's own fallback looked wrong on four of the five themes whenever
   portal-ui.css was slow, cached out, or (as happened) not being served at all.
   portal-ui.css still owns the glass treatment on top. */
.sidebar{background:var(--surface);border-right:1px solid var(--border);width:292px;
    height:100vh;min-height:100vh;flex-shrink:0;display:flex;flex-direction:column;
    position:fixed;left:0;top:0;z-index:3000;box-shadow:2px 0 18px rgba(20,42,68,.12);overflow:hidden;}
.brand-block{display:flex;align-items:center;gap:12px;padding:11px 12px;margin:12px;
    border-radius:10px;border:1px solid var(--border);
    background:linear-gradient(180deg,color-mix(in srgb,var(--card) 92%,transparent),color-mix(in srgb,var(--surface) 92%,transparent));
    box-shadow:inset 0 1px 0 var(--glass-edge,rgba(255,255,255,.14)),0 8px 20px rgba(0,0,0,.18);}
.brand-text{line-height:1.1;}
.brand-name{font-size:20px;font-weight:800;color:var(--strong);}
.brand-name span{color:var(--accent);}
.brand-sub{font-size:12px;text-transform:uppercase;letter-spacing:.10em;color:var(--muted);margin-top:4px;}
.sidebar-nav{flex:1;min-height:0;max-height:100%;overflow-y:auto;overflow-x:hidden;padding:8px 0 16px;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--border) transparent;}
.sidebar-nav::-webkit-scrollbar{width:11px}
.sidebar-nav::-webkit-scrollbar-track{background:transparent}
.sidebar-nav::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--border) 75%,transparent);border:2px solid transparent;background-clip:padding-box;border-radius:999px}
.sidebar-nav::-webkit-scrollbar-thumb:hover{background:color-mix(in srgb,var(--accent) 60%,var(--border));border:2px solid transparent;background-clip:padding-box}
.nav-grp-hd{padding:12px 16px 4px;font-size:10px;text-transform:uppercase;letter-spacing:.10em;font-weight:700;color:var(--muted);}
.nav-item{display:flex;align-items:center;gap:9px;padding:9px 16px;margin:1px 8px;border-radius:7px;
    font-size:15px;font-weight:500;color:var(--text);text-decoration:none;border:1px solid transparent;cursor:pointer;
    transition:background .15s ease,color .15s ease;}
.nav-item:hover{background:transparent;color:var(--strong);}
.nav-item.active{background:var(--accent-lt);color:var(--strong);border-left:3px solid var(--accent);padding-left:13px;font-weight:700;}
.nav-item.sub-item{padding-left:32px;font-size:14px;}
.nav-main{justify-content:space-between;font-weight:700;color:var(--text);}
.menu-section.expanded > .nav-main{color:var(--strong);}
.menu-section > .nav-main:hover{color:var(--strong);}
.nav-main .nav-main-left{display:inline-flex;align-items:center;gap:9px;}
.nav-chevron{display:inline-block;transition:transform .2s ease;color:var(--muted);font-size:12px;}
.menu-section.expanded > .nav-main:not(.nav-direct) .nav-chevron{transform:rotate(90deg);color:var(--strong);}
.menu-submenu{display:none;}
.menu-section.expanded > .menu-submenu{display:block;}
.nav-icon{font-size:18px;width:22px;text-align:center;flex-shrink:0;}

/* The canonical sidebar lock lived here: thirteen !important rules whose only
   job was to beat page-local copies of the sidebar. 2026-09-05 removed the
   copies instead -- 184 shell rules across 11 pages -- so the lock has nothing
   left to fight, and portal-ui.css now owns how the sidebar looks.

   It had to go for a second reason. With cascade layers, an !important
   declaration in an EARLIER layer beats one in a later layer. Leaving these
   here would have inverted the whole design system the moment @layer was
   introduced: the frame would have won every contested sidebar rule against
   portal-ui.css, silently.

   The .hoppe-h-icon rules went with it -- that class has no users left; the
   mark is the brick-built <svg><use href="#pi-hmark"> now. */

.sidebar-footer{padding:12px 16px;margin-top:auto;border-top:1px solid var(--border);}
.env-badge{width:8px;height:8px;border-radius:50%;background:var(--muted);display:inline-block;margin:4px 8px;box-shadow:0 0 6px var(--accent);transition:background .3s;}
.theme-btn{margin-top:10px;width:100%;padding:7px 12px;background:transparent;border:1px solid var(--border);
    border-radius:7px;color:var(--muted);font-size:12px;font-family:inherit;cursor:pointer;text-align:left;
    transition:border-color .15s,color .15s;}
.theme-btn:hover{border-color:var(--accent);color:var(--strong);}

/* ── Main ─── */
.main{margin-left:292px;flex:1;display:flex;flex-direction:column;min-height:100vh;}
.page-header{padding:56px 36px 0;}
.page-title{font-size:28px;font-weight:800;color:var(--strong);}
.page-subtitle{margin-top:6px;font-size:14px;color:var(--muted);}
.tile-actions{display:flex;align-items:center;gap:8px;margin-bottom:12px;flex-wrap:wrap;}
.shell-tools:not(.topbar){position:fixed;top:10px;right:16px;z-index:200;display:flex;align-items:center;justify-content:flex-end;gap:8px;}
.shell-tools:not(.topbar) .back-btn{order:1;}
.shell-tools:not(.topbar) .user-menu{order:2;}
.topbar.shell-tools{position:static;top:auto;right:auto;z-index:auto;}
.back-btn{padding:7px 12px;}
.user-menu{position:relative;}
.user-chip{display:inline-flex;align-items:center;gap:7px;padding:7px 12px;background:var(--surface);
    color:var(--text);border:1px solid var(--border);border-radius:8px;cursor:pointer;font-size:12px;font-weight:600;box-shadow:var(--shadow-sm);white-space:nowrap;}
.user-chip:hover{border-color:var(--accent);background:var(--accent-lt);color:var(--strong);}
.menu-panel{display:none;position:absolute;right:0;top:calc(100% + 6px);width:240px;background:var(--card);
    border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow-md);padding:8px;z-index:210;}
.menu-section-divider{font-size:9px;font-weight:800;text-transform:uppercase;letter-spacing:.10em;color:var(--muted);padding:10px 8px 4px;border-top:1px solid var(--border);margin-top:4px;}
.menu-section-divider:first-of-type{border-top:none;margin-top:0;padding-top:4px;}
.menu-panel.open{display:block;}
.menu-user{font-size:12px;color:var(--strong);padding:8px 8px 10px;border-bottom:1px solid var(--border);margin-bottom:6px;}
.menu-item{display:block;width:100%;text-align:left;background:transparent;color:var(--text);border:1px solid transparent;
    border-radius:7px;padding:8px;font-size:12px;cursor:pointer;text-decoration:none;}
.menu-item:hover{background:var(--accent-lt);border-color:var(--border);}
.content{padding:24px 36px 108px;flex:1;}

/* ── Shared utilities ──────────────────────────────────────── */
.btn{display:inline-flex;align-items:center;gap:6px;padding:8px 12px;background:var(--accent);color:#fff;
  border-radius:7px;text-decoration:none;font-size:13px;font-weight:600;font-family:inherit;border:0;cursor:pointer}
.btn:hover{background:var(--accent-hov)}
.btn.secondary{background:transparent;border:1px solid var(--border);color:var(--text)}
.btn.secondary:hover{border-color:var(--accent);background:var(--accent-lt);color:var(--strong)}
.banner{margin:0 0 14px;padding:10px 14px;border:1px solid var(--border);border-radius:10px;
  background:var(--surface);font-size:12px;line-height:1.5}
.banner.ok{border-color:rgba(63,185,80,.35);color:var(--ok)}
.banner.warn{border-color:rgba(240,180,41,.4);color:var(--warn)}
.banner.err{border-color:rgba(248,81,73,.4);color:var(--err)}
.hamburger{display:none;position:fixed;top:12px;left:12px;z-index:3010;background:var(--topbar);
    border:1px solid var(--border);border-radius:8px;padding:8px 10px;cursor:pointer;font-size:18px;color:var(--text);}
.sidebar-backdrop{display:none;position:fixed;inset:0;background:rgba(0,0,0,.48);z-index:2990;}
@media(max-width:780px){
    .sidebar{transform:translateX(-100%);transition:transform .25s ease;}
    .sidebar.open{transform:translateX(0);}.sidebar-backdrop.open{display:block;}
    .hamburger{display:flex;align-items:center;}.main{margin-left:0;}
    .page-header,.content,footer{padding-left:20px;padding-right:20px;}
    footer{position:static;left:auto;right:auto;bottom:auto;margin-top:20px;}
    .content{padding-bottom:24px;}
}
/* — 640px: large phones / small tablets portrait — */
@media(max-width:640px){
    .page-header{padding-left:16px;padding-right:16px;}
    .page-title{font-size:23px;}
    .content{padding-left:16px;padding-right:16px;}
    .tile-actions{flex-wrap:wrap;gap:6px;}
}
/* — 480px: small phones — */
@media(max-width:480px){
    .page-header{padding-top:48px;padding-left:12px;padding-right:12px;}
    .page-title{font-size:19px;}
    .page-subtitle{font-size:12px;}
    .content{padding-left:12px;padding-right:12px;padding-bottom:16px;}
    .tile-actions{gap:4px;}
    .btn{padding:7px 10px;font-size:12px;}
    footer{padding:5px 12px;font-size:10px;}
}
/* — 1400px: wide desktop — */
@media(min-width:1400px){
    .sidebar{width:308px;}
    .main{margin-left:308px;}
    footer{left:308px;}
    .page-header{padding-left:52px;padding-right:52px;}
    .content{padding-left:52px;padding-right:52px;}
}
/* — 1800px: ultrawide — */
@media(min-width:1800px){
    .page-header{padding-left:80px;padding-right:80px;}
    .content{padding-left:80px;padding-right:80px;}
}

footer{position:fixed;bottom:0;left:292px;right:0;padding:6px 20px;font-size:11px;color:var(--muted);border-top:1px solid var(--border);background:color-mix(in srgb,var(--topbar) 92%,transparent);backdrop-filter:blur(4px);display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;z-index:55;}
.footer-brand{display:inline-flex;align-items:center;gap:8px;}
/* Pages that declare data-portal-shell="none" (the front door, the public
   /home//joern//joanna/ pages, download pages, standalone widgets — the same
   set stale-code-monitor.sh's is_standalone_page() exempts from shell checks)
   have no sidebar to reserve 292px for and are plain scrolling documents, not
   an app shell with a fixed status bar. The bare footer{} rule above still
   matched their <footer> element regardless — an element selector has no
   idea which page it landed on — so it pinned itself to the viewport bottom
   over whatever content was scrolled underneath, with the reserved 292px gap
   on the left (meant for a sidebar that was never rendered) showing the page
   behind straight through. Found 2026-09-18 on /home/, still visible after
   the footer's own content was fixed, because the actual bug was position,
   not content. Every standalone page defines its OWN local footer{...} for
   padding/spacing (see e.g. home/index.html's footer.site-footer) but none
   of them reset position, because nothing told them they needed to. */
html[data-portal-shell="none"] footer{
  position:static;left:auto;right:auto;bottom:auto;
  backdrop-filter:none;
}

/* ── Network section tab bar ──────────────────────────────────────────
   2026-08-16: was defined inline in network/index.html only (and twice
   in that one file, so the second block silently won). The four Network
   sub-pages carried no tab bar at all, which meant clicking a tab
   stranded you with no way across the section except the sidebar. Moved
   here so all five Network pages share one definition and the section
   reads as a single tabbed surface. */
.network-submenu { display: flex; gap: 4px; margin: 0 0 18px; flex-wrap: wrap; }
.network-submenu .sub-link {
    padding: 8px 16px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--muted);
    text-decoration: none;
    border: 1px solid transparent;
    transition: background .12s, color .12s;
}
.network-submenu .sub-link:hover { background: var(--accent-lt); color: var(--strong); }
.network-submenu .sub-link.active {
    background: var(--accent-lt);
    border-color: var(--accent);
    color: var(--strong);
}

}
