/* Component layer for the admin portal.
 *
 * assets/portal-theme.css already unified the *palette* across these pages but
 * deliberately stopped there ("overriding their layout from here would mean
 * fighting 15 sets of inline rules I can't see the effect of"). That caution
 * was right at the time. This file finishes the job, on the evidence that the
 * 21 pages carrying `header.appbar` all declare the SAME class vocabulary -
 * .appbar, .brand, .brand-badge, .brand-sub, .spacer, .secondary, .primary -
 * and simply redeclare the same ~40 lines of rules for it, each on a slightly
 * different shade and size. So this defines those components once; each page's
 * copy is then deleted rather than overridden.
 *
 * Load order this depends on, unchanged from what portal-theme.css documents:
 *
 *   page inline <style>  ->  portal-theme.css  ->  portal-ui.css  ->  responsive.css
 *        (layout)            (tokens)              (components)       (mobile)
 *
 * Because it loads after the page's own <style>, an identical selector here
 * wins on source order - which is what lets a page be migrated by deletion,
 * one page at a time, with the portal never in a broken intermediate state.
 *
 * Not touched, on purpose: .invoice and .preview-scale. Those reproduce a real
 * A4 document at fixed pixel width and the PDF pipeline depends on that exact
 * geometry - the same exclusion responsive.css already makes by name.
 */

/* ============================================================
   Scales
   Pages were each inventing 11px / 12.5px / 13.5px / 14.5px in
   isolation, which is most of why nothing lined up. One ramp.
   ============================================================ */
html:root{
  --fs-xs:11px; --fs-sm:12.5px; --fs-base:13.5px;
  --fs-md:15px; --fs-lg:18px; --fs-xl:22px; --fs-2xl:28px;

  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px; --sp-6:32px;

  --appbar-h:60px;
  --appbar-bg:linear-gradient(112deg,#0b1220 0%,#16213a 55%,#1d2a4a 100%);
  --appbar-ink:#f1f5f9;
  --appbar-muted:#9fb0cc;
  --appbar-line:rgba(255,255,255,.14);

  --ease:cubic-bezier(.2,.7,.3,1);
}

/* ============================================================
   Icons
   The box is reserved here, before icons.js hydrates the <i>,
   so a toolbar never reflows as its icons arrive.
   ============================================================ */
i[data-icon]{
  display:inline-flex; align-items:center; justify-content:center;
  width:1.05em; height:1.05em; flex:none; vertical-align:-.15em;
}
svg.ic{ width:100%; height:100%; display:block }
/* An icon sitting alone in a button wants a touch more presence than one
   sitting beside a word. */
button > i[data-icon]:only-child,
a > i[data-icon]:only-child{ width:1.25em; height:1.25em }

/* An icon leading a section heading: slightly larger than the (often 11px,
   uppercase) label it introduces, and in the accent rather than the label's
   muted grey, so it reads as a marker rather than as part of the word. */
h1 > i[data-icon]:first-child,
h2 > i[data-icon]:first-child,
h3 > i[data-icon]:first-child,
h4 > i[data-icon]:first-child{
  width:1.35em; height:1.35em; margin-right:7px; color:var(--accent); vertical-align:-.3em;
}

/* ============================================================
   Appbar
   ============================================================ */
header.appbar{
  position:sticky; top:0; z-index:30;
  display:flex; align-items:center; gap:var(--sp-2);
  flex-wrap:nowrap;
  padding:10px var(--sp-5);
  min-height:var(--appbar-h);
  background:var(--appbar-bg); color:var(--appbar-ink);
  box-shadow:0 1px 0 var(--appbar-line), 0 6px 24px rgba(8,12,24,.28);
}

/* flex:none on the brand and on every control, so an over-full bar actually
   overflows instead of quietly squeezing the page title down to an ellipsis.
   appbar.js measures scrollWidth vs clientWidth to decide what to collapse,
   and that measurement only means anything if nothing volunteers to shrink. */
header.appbar .brand{ display:flex; align-items:center; gap:10px; flex:none; min-width:0 }
header.appbar .brand-badge{
  display:flex; align-items:center; justify-content:center;
  width:36px; height:36px; flex:none;
  border-radius:10px;
  background:rgba(255,255,255,.10);
  border:1px solid var(--appbar-line);
  color:var(--appbar-ink);
  font-size:var(--fs-md);
}
header.appbar .brand-badge img,
header.appbar .brand-badge svg{ width:20px; height:20px; display:block }
header.appbar .brand-text{ min-width:0 }
header.appbar h1{
  margin:0; font-size:var(--fs-md); font-weight:650; letter-spacing:-.01em;
  color:var(--appbar-ink); line-height:1.25;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  max-width:34ch;   /* a long generator name truncates; it never eats the bar */
}
header.appbar .brand-sub{
  display:block; font-size:var(--fs-xs); font-weight:500;
  color:var(--appbar-muted); letter-spacing:.02em; line-height:1.3;
}
header.appbar .spacer{ flex:1 1 auto; min-width:var(--sp-2) }

/* Appbar controls. Three levels of emphasis, so a bar of 16 actions stops
   reading as 16 identical grey rectangles:
     .primary  gold, filled     - the one thing this page is for
     .secondary ghost outline   - real actions
     .quiet    plain text       - leaving (Dashboard, Log out)              */
/* `> a` covers the links that carry no class at all (the console's "Full log",
   the groups page's "User Accounts"). Without it they fell through to the UA
   default and rendered as blue underlined text on the navy bar. The classed
   selectors below are more specific, so .primary/.quiet still win. */
header.appbar button,
header.appbar > a,
header.appbar a.secondary,
header.appbar a.primary,
header.appbar a.quiet,
header.appbar .btn{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:8px 13px; min-height:36px;
  font-family:inherit; font-size:var(--fs-sm); font-weight:600;
  border-radius:9px; cursor:pointer; text-decoration:none; white-space:nowrap;
  flex:none;
  background:rgba(255,255,255,.07);
  border:1px solid var(--appbar-line);
  color:var(--appbar-ink);
  transition:background .14s var(--ease), border-color .14s var(--ease), transform .14s var(--ease);
}
header.appbar button:hover,
header.appbar > a:hover,
header.appbar a.secondary:hover,
header.appbar .btn:hover{ background:rgba(255,255,255,.15); border-color:rgba(255,255,255,.26) }
header.appbar button:active{ transform:translateY(1px) }

header.appbar button.primary,
header.appbar a.primary,
header.appbar .btn.primary{
  background:var(--gold); border-color:var(--gold); color:#20180a; font-weight:700;
}
header.appbar button.primary:hover,
header.appbar a.primary:hover{ background:#c9962f; border-color:#c9962f }

/* a.quiet / button.quiet rather than just .quiet: the Dashboard link is
   `class="secondary quiet"`, and `header.appbar a.secondary` above is (0,2,2).
   A bare `header.appbar .quiet` is (0,2,1) and would lose to it, leaving the
   exit links looking like primary actions. */
header.appbar a.quiet,
header.appbar button.quiet,
header.appbar .btn.quiet{
  background:transparent; border-color:transparent; color:var(--appbar-muted); font-weight:600;
}
header.appbar a.quiet:hover,
header.appbar button.quiet:hover,
header.appbar .btn.quiet:hover{ background:rgba(255,255,255,.08); color:var(--appbar-ink) }

header.appbar button.danger{ background:rgba(211,79,70,.18); border-color:rgba(211,79,70,.45); color:#ffd7d3 }
header.appbar button.danger:hover{ background:rgba(211,79,70,.3) }
header.appbar button:disabled,
header.appbar .btn:disabled{ opacity:.45; cursor:not-allowed; transform:none }

header.appbar input,
header.appbar select{
  flex:none;
  padding:8px 12px; min-height:36px;
  border-radius:9px;
  border:1px solid var(--appbar-line);
  background:rgba(255,255,255,.08);
  color:var(--appbar-ink);
  font-family:inherit; font-size:var(--fs-sm);
}
header.appbar input::placeholder{ color:var(--appbar-muted) }
header.appbar input:focus,
header.appbar select:focus{
  outline:none; border-color:rgba(255,255,255,.42); background:rgba(255,255,255,.13);
}
header.appbar select option{ color:var(--ink); background:var(--panel) }

/* ---- Overflow menu -----------------------------------------------------
   assets/appbar.js moves surplus actions in here rather than letting them
   wrap. The invoice generator alone carries 16 - which wrapped to two rows
   even at 1440px, and stacked ~330px tall on a phone.                     */
header.appbar .appbar-more{ position:relative; flex:none }
header.appbar .appbar-more > summary{
  display:inline-flex; align-items:center; gap:6px;
  padding:8px 13px; min-height:36px;
  font-size:var(--fs-sm); font-weight:600;
  border-radius:9px; cursor:pointer; list-style:none;
  background:rgba(255,255,255,.07); border:1px solid var(--appbar-line);
  color:var(--appbar-ink); white-space:nowrap;
}
header.appbar .appbar-more > summary::-webkit-details-marker{ display:none }
header.appbar .appbar-more > summary:hover{ background:rgba(255,255,255,.15) }
header.appbar .appbar-more[open] > summary{ background:rgba(255,255,255,.18) }
header.appbar .appbar-more .appbar-more-panel{
  position:absolute; top:calc(100% + 8px); right:0; z-index:60;
  min-width:232px; max-width:min(320px,calc(100vw - 24px));
  max-height:min(70vh,520px); overflow-y:auto;
  display:flex; flex-direction:column; gap:2px;
  padding:6px;
  background:var(--panel); color:var(--ink);
  border:1px solid var(--border); border-radius:12px;
  box-shadow:var(--shadow-lg);
}
/* Inside the dropdown the actions are on a light surface, so they shed the
   translucent-on-navy treatment entirely and become menu rows. */
header.appbar .appbar-more-panel button,
header.appbar .appbar-more-panel a{
  justify-content:flex-start; width:100%;
  padding:9px 10px; min-height:38px;
  background:transparent; border:0; border-radius:8px;
  color:var(--ink); font-weight:550; font-size:var(--fs-base);
  text-align:left; white-space:normal;
}
header.appbar .appbar-more-panel button:hover,
header.appbar .appbar-more-panel a:hover{ background:var(--accent-soft); color:var(--accent) }
header.appbar .appbar-more-panel button.primary,
header.appbar .appbar-more-panel a.primary{
  background:transparent; color:var(--gold-ink); font-weight:700;
}
header.appbar .appbar-more-panel .appbar-more-sep{
  height:1px; margin:5px 4px; background:var(--border); flex:none;
}
/* Hidden file inputs and the like ride along with their button - they must
   not become 38px-tall menu rows. */
header.appbar .appbar-more-panel input[type=file]{ display:none }

/* ============================================================
   Buttons on the page body (not the appbar)
   ============================================================ */
.btn,
button.page-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  padding:8px 14px; min-height:36px;
  font-family:inherit; font-size:var(--fs-base); font-weight:600;
  border-radius:var(--radius-sm); cursor:pointer; text-decoration:none;
  background:var(--panel); color:var(--ink-sub);
  border:1px solid var(--border-strong);
  transition:background .14s var(--ease), border-color .14s var(--ease), box-shadow .14s var(--ease);
}
.btn:hover{ background:var(--panel-2); border-color:var(--muted); box-shadow:var(--shadow-md) }
.btn.primary{ background:var(--accent); border-color:var(--accent); color:#fff }
.btn.primary:hover{ background:var(--accent-2); border-color:var(--accent-2) }
.btn.danger{ background:var(--danger); border-color:var(--danger); color:#fff }
.btn.ghost{ background:transparent; border-color:transparent; color:var(--muted) }
.btn.ghost:hover{ background:var(--accent-soft); color:var(--accent) }
.btn:disabled{ opacity:.5; cursor:not-allowed }

/* ============================================================
   Status pills
   Every page had its own take on "a small coloured chip". One.
   ============================================================ */
.pill{
  display:inline-flex; align-items:center; gap:6px;
  padding:3px 10px; border-radius:99px;
  font-size:var(--fs-xs); font-weight:700; letter-spacing:.02em;
  background:var(--accent-soft); color:var(--accent);
  border:1px solid transparent; white-space:nowrap;
}
.pill.ok     { background:var(--success-soft); color:var(--success-2) }
.pill.warn   { background:var(--warn-soft);    color:var(--warn) }
.pill.danger { background:var(--danger-soft);  color:var(--danger) }
.pill.muted  { background:var(--panel-2);      color:var(--muted); border-color:var(--border) }

/* ============================================================
   Off-canvas drawer
   One drawer behaviour in the portal. responsive.css already
   implements this shape for document-chat's .sidebar; the
   dashboard's .side now joins it rather than inventing a second.
   ============================================================ */
.drawer-backdrop{
  position:fixed; inset:0; z-index:39;
  background:rgba(15,23,42,.48);
  opacity:0; pointer-events:none; transition:opacity .22s var(--ease);
}
.drawer-backdrop.show{ opacity:1; pointer-events:auto }

.nav-toggle{
  display:none; align-items:center; justify-content:center;
  width:38px; height:38px; flex:none; padding:0;
  border-radius:9px; cursor:pointer;
  background:rgba(255,255,255,.08); border:1px solid var(--appbar-line);
  color:var(--appbar-ink);
}

/* ============================================================
   Focus
   One visible ring, never on mouse click.
   ============================================================ */
:focus-visible{ outline:2px solid var(--accent-2); outline-offset:2px; border-radius:4px }
header.appbar :focus-visible{ outline-color:#8ab4f8 }

/* ============================================================
   Mobile
   The appbar is the piece that broke hardest on a phone, so its
   rules live next to the desktop ones rather than in
   responsive.css - keeping one component's behaviour readable in
   one place.
   ============================================================ */
@media (max-width:820px){
  header.appbar{
    padding:8px var(--sp-3);
    gap:6px;
    min-height:54px;
  }
  header.appbar .brand-badge{ width:32px; height:32px; border-radius:9px }
  header.appbar h1{ font-size:var(--fs-base) }
  header.appbar .brand-sub{ display:none }

  /* A search box and a row of buttons cannot share 390px. Title and actions
     take the first row; any appbar field drops to a full-width second row.
     (responsive.css already forces flex-wrap here with !important - this works
     with that rather than against it.) */
  header.appbar{ flex-wrap:wrap; row-gap:8px }
  header.appbar .brand{ flex:1 1 auto; min-width:0 }
  header.appbar h1{ max-width:none }
  header.appbar .spacer{ display:none }
  header.appbar > input,
  header.appbar > select{ order:10; flex:1 1 100%; width:100%; min-width:0 }
  header.appbar .appbar-more{ order:9 }
  header.appbar input,
  header.appbar select{ min-height:38px; font-size:16px } /* 16px stops iOS zooming on focus */
  header.appbar button,
  header.appbar > a,
  header.appbar a.secondary,
  header.appbar a.primary,
  header.appbar a.quiet,
  header.appbar .btn,
  header.appbar .appbar-more > summary{ min-height:38px; padding:8px 11px }
  /* On a phone a bare icon is the label - appbar.js adds .icon-only to the
     exits it can safely reduce. */
  header.appbar .icon-only span,
  header.appbar .icon-only .label{ display:none }
  header.appbar .icon-only{ padding:8px 10px }
  .nav-toggle{ display:inline-flex }
}
