@font-face{font-family:'IBM Plex Sans';src:url('../../fonts/plex-regular.woff2');font-weight:400}@font-face{font-family:'IBM Plex Sans';src:url('../../fonts/plex-bold.woff2');font-weight:500 800}@font-face{font-family:'JetBrains Mono';src:url('../../fonts/mono.woff')}
/* ============================================================
   DESIGN TOKENS
   Single source of truth for colors, typography, spacing, etc.
   Change here = change everywhere.
   ============================================================ */

:root {
  /* ---------- COLOR: Background / Surfaces ----------
     Near-neutral dark with a whisper of brand green on the body
     surface only. A +1 on the G channel is as far as this goes —
     anything more tips the whole page into a visible green cast. */
  --bg-base:          #09090b; /* body (original, barely-purple neutral) */
  --bg-surface-1:     #0a0a0c; /* app-detail */
  --bg-surface-2:     #0b0b0d; /* app-list */
  --bg-surface-3:     #0c0c0e; /* app-sidebar */
  --bg-elevated:      #111113; /* feature-ui, menubar-window, active-window */
  --bg-product:       #111114; /* hero-product-inner */
  --bg-nav:           rgba(9, 9, 11, 0.7); /* nav with backdrop-blur */

  /* ---------- COLOR: Borders ---------- */
  --border-subtle:    #141414; /* footer top, compat-bar top, section dividers */
  --border-default:   #1a1a1a; /* mockup internal dividers */
  --border-strong:    #1e1e1e; /* menubar-window, menubar-select */

  /* ---------- COLOR: Text (light → dark, on dark bg) ----------
     Values calibrated to WCAG on --bg-base (#09090b):
     - primary   #fafafa → 19.5:1 (AAA, no pure-white vibration)
     - tertiary  #a0a0a0 → 7.3:1 (AAA)
     - muted     #8a8a8a → 5.3:1 (AA)
     - subtle    #7a7a7a → 4.5:1 (AA) */
  --text-primary:     #fafafa; /* h1/h2, active states, key titles (was #ffffff) */
  --text-secondary:   #cccccc; /* list-item names, active-permit-name, menubar value */
  --text-tertiary:    #a0a0a0; /* subtitle, body copy on main bg, hover targets */
  --text-muted:       #8a8a8a; /* meta, tags, terminal-prompt */
  --text-subtle:      #7a7a7a; /* labels, compat-item, footer-link, redacted, terminal-comment */

  /* ---------- COLOR: Interactive text states ---------- */
  --text-link-hover:  #aaaaaa; /* sidebar-item hover */
  --text-button-fg:   #09090b; /* text on white button (matches bg-base) */
  --text-button-hover-bg: #e0e0e0; /* white btn hover bg */

  /* ---------- COLOR: Accents (semantic) ---------- */
  --accent-green:       #4ade80; /* active, success, category-infra */
  --accent-green-soft:  #86efac; /* terminal-string */
  --accent-amber:       #f59e0b; /* warning, category-apikeys */
  --accent-red:         #ef4444; /* danger, revoke hover, terminal-error */
  --accent-purple:      #8b5cf6; /* category-certificates */
  --accent-purple-soft: #c4b5fd; /* terminal-fn */
  --accent-cyan:        #06b6d4; /* category-cloud */

  /* ---------- COLOR: Overlays (translucent whites) ---------- */
  --overlay-02: rgba(255, 255, 255, 0.02);
  --overlay-03: rgba(255, 255, 255, 0.03);
  --overlay-04: rgba(255, 255, 255, 0.04);
  --overlay-05: rgba(255, 255, 255, 0.05);
  --overlay-06: rgba(255, 255, 255, 0.06);
  --overlay-08: rgba(255, 255, 255, 0.08);
  --overlay-10: rgba(255, 255, 255, 0.10);
  --overlay-20: rgba(255, 255, 255, 0.20);
  --overlay-40: rgba(255, 255, 255, 0.40);

  /* ---------- TYPOGRAPHY: Families ---------- */
  --font-sans: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: 'JetBrains Mono', monospace;

  /* ---------- TYPOGRAPHY: Sizes ---------- */
  --text-xs:         11px; /* labels */
  --text-sm:         12px; /* meta, tags, captions */
  --text-base:       13px; /* small body, code */
  --text-md:         14px; /* button, mockup body */
  --text-lg:         15px; /* nav, body reg, value-desc */
  --text-xl:         16px; /* body, detail title */
  --text-2xl:        17px; /* subtitle */
  --text-3xl:        20px; /* value-heading */
  --text-display-sm: 38px; /* feature-heading */
  --text-display-md: 42px; /* statement */
  --text-display-lg: 46px; /* cta */
  --text-display-xl: 56px; /* hero-heading */
  --text-timer:      48px; /* timer digit */

  /* ---------- TYPOGRAPHY: Weights ---------- */
  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;

  /* ---------- SPACING ---------- */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-7:  32px;
  --space-8:  40px;
  --space-9:  48px;
  --space-10: 56px;
  --space-11: 64px;
  --space-12: 80px;
  --space-13: 100px;
  --space-15: 140px;
  --space-17: 180px;

  /* ---------- RADII ---------- */
  --radius-xs:  2px;
  --radius-sm:  4px;
  --radius-md:  6px;
  --radius-lg:  8px;
  --radius-xl:  10px;
  --radius-2xl: 12px;

  /* ---------- TRANSITIONS ---------- */
  --transition-fast:    0.1s ease;
  --transition-default: 0.15s ease;
  --transition-slow:    0.3s ease;

  /* ---------- SHADOWS ---------- */
  --shadow-hero-product:
    0 0 0 0.5px rgba(255, 255, 255, 0.06),
    0 40px 100px rgba(0, 0, 0, 0.8);

  --shadow-feature-ui:
    0 0 0 0.5px rgba(255, 255, 255, 0.05),
    0 0 40px rgba(255, 255, 255, 0.015),
    0 0 80px rgba(200, 200, 220, 0.02),
    0 20px 60px rgba(0, 0, 0, 0.5);

  --shadow-window:
    0 24px 80px rgba(0, 0, 0, 0.5);

  /* Floating circular chevron buttons (scroll-more indicators in the
     active-permits panel and anywhere else a small sticker sits on
     top of a scroll surface). Kept in sync with the desktop app's
     --shadow-float token. */
  --shadow-float:
    0 6px 16px rgba(0, 0, 0, 0.5);

  --shadow-popover:
    0 8px 24px rgba(0, 0, 0, 0.35);

  /* ---------- LAYOUT ---------- */
  --container-max:       1200px;
  --container-padding-x: 24px;

  --nav-height:  64px;
  --nav-z-index: 100;
}

/* ============================================================
   BASE — reset, body, containers, dividers
   ============================================================ */

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  background: var(--bg-base);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
}

/* ---------- Container ---------- */
.container {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--container-padding-x);
}

/* ---------- Section divider ---------- */
.section-divider {
  border: none;
  border-top: 1px solid var(--border-subtle);
}

/* ---------- Keyboard focus (a11y) ----------
   :focus-visible only fires on keyboard navigation, not mouse clicks.
   Outline-offset gives the ring breathing room from the element.
   Accent-green so the indicator reads as "interactive" not "error". */
*:focus {
  outline: none;
}

*:focus-visible {
  outline: 2px solid var(--accent-green);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* ---------- Screen-reader-only utility ----------
   Visually hidden, still announced by AT. Used for live regions
   like #copy-announce that confirm a successful clipboard copy. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   COMPONENTS — Nav, Footer (site chrome)
   ============================================================ */

/* ============ NAV ============ */
.site-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--nav-z-index);
  padding: 0 var(--space-6);
  height: var(--nav-height);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--bg-nav);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--overlay-06);
}

.nav-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text-primary);
}

.nav-logo svg {
  width: 24px;
  height: 24px;
}

.nav-logo span {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  letter-spacing: -0.02em;
}

.nav-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.nav-link {
  /* Visible padding stays compact, but min-height + flex-center
     gives a 44x44 hit area without making the nav bar look tall. */
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text-tertiary);
  text-decoration: none;
  font-size: var(--text-md);
  font-weight: 450;
  padding: 0 var(--space-3);
  border-radius: var(--radius-md);
  transition: color var(--transition-default);
}

.nav-link:hover {
  color: var(--text-secondary);
}

.nav-divider {
  width: 1px;
  height: var(--space-4);
  background: var(--overlay-10);
  margin: 0 var(--space-1);
}

.nav-download {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text-primary);
  text-decoration: none;
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  padding: 0 var(--space-4);
  border-radius: var(--radius-lg);
  border: 1px solid var(--overlay-20);
  transition: border-color var(--transition-default), background var(--transition-default);
  background: transparent;
}

.nav-download:hover {
  border-color: var(--overlay-40);
  background: var(--overlay-04);
}

/* ============ FOOTER ============ */
footer {
  border-top: 1px solid var(--border-subtle);
  padding: var(--space-8) 0 var(--space-6);
  margin-top: var(--space-10);
}

/* Two stacked rows: brand + nav on top, legal meta on bottom.
   A hairline between them gives the footer rhythm without shouting. */
.footer-top,
.footer-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.footer-top {
  margin-bottom: var(--space-3);
}

.footer-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  text-decoration: none;
  color: var(--text-tertiary);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  transition: color var(--transition-default);
}

.footer-logo:hover {
  color: var(--text-primary);
}

.footer-logo svg {
  width: 18px;
  height: 18px;
  opacity: 0.55;
  transition: opacity var(--transition-default);
}

.footer-logo:hover svg {
  opacity: 0.85;
}

.footer-links {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.footer-link {
  color: var(--text-subtle);
  text-decoration: none;
  font-size: var(--text-base);
  transition: color var(--transition-default);
}

.footer-link:hover {
  color: var(--text-primary);
}

.footer-meta {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-subtle);
  white-space: nowrap;
}

.footer-meta-link {
  color: var(--text-tertiary);
  text-decoration: none;
  border-bottom: 1px dashed var(--overlay-10);
  padding-bottom: 1px;
  transition: color var(--transition-default), border-color var(--transition-default);
}

.footer-meta-link:hover {
  color: var(--text-primary);
  border-bottom-color: var(--text-tertiary);
}

/* Stack everything on narrow viewports so nothing overflows. */
@media (max-width: 640px) {
  .footer-top,
  .footer-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-3);
  }

  .footer-links {
    flex-wrap: wrap;
    gap: var(--space-4);
  }
}

/* ============================================================
   MOCKUPS — App 3-col mockup, Menubar, Terminal, Active permits
   ============================================================ */

/* ============ APP TITLE BAR (Hero) ============
   Spans the top row of the .app-mockup grid (grid-column: 1 / -1).
   Carries the macOS traffic-light cluster, the brand logo, and the
   sidebar-toggle button. Mirrors the desktop app's .app-titlebar:
   a single full-width band with a bottom border, no vertical column
   dividers cutting through it. */
.app-titlebar {
  grid-column: 1 / -1;
  grid-row: 1;
  display: flex;
  align-items: center;
  background: var(--bg-surface-3);
  border-bottom: 1px solid var(--border-default);
  position: relative;
  z-index: 2;
}

/* Traffic-light cluster. Sits in the leading slot the desktop app
   reserves for the macOS window controls — fixed 76px so the brand
   logo lands at the same x as in the real app. */
.chrome-dots {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  width: 76px;
  padding-left: var(--space-4);
  box-sizing: border-box;
  flex-shrink: 0;
}

.chrome-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}

.chrome-dot-red    { background: #ff5f57; }
.chrome-dot-yellow { background: #febc2e; }
.chrome-dot-green  { background: #28c840; }

.app-titlebar-brand {
  display: inline-flex;
  align-items: center;
  padding: 0 4px;
  flex-shrink: 0;
}

.app-titlebar-logo {
  width: 16px;
  height: 16px;
  color: var(--text-subtle);
  opacity: 0.75;
  flex-shrink: 0;
}

/* Sidebar-toggle. Decorative for now — the collapse interaction is
   wired up later. Hover state matches the desktop app so it still
   reads as a real control. */
.app-titlebar-toggle {
  margin: 0 4px 0 8px;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: var(--radius-md);
  color: var(--text-subtle);
  cursor: pointer;
  padding: 0;
  appearance: none;
  transition: color var(--transition-fast), background var(--transition-fast);
  flex-shrink: 0;
}

.app-titlebar-toggle svg {
  width: 18px;
  height: 18px;
}

.app-titlebar-toggle:hover,
.app-titlebar-toggle:focus-visible {
  color: var(--text-primary);
  background: var(--overlay-06);
  outline: none;
}

.app-titlebar-spacer {
  flex: 1;
  min-width: 0;
}


/* ============ APP MOCKUP (Hero) ============ */
.app-mockup {
  display: grid;
  grid-template-columns: 220px 1fr 380px;
  /* Row 1 = TitleBar (40px, spans all three columns). Row 2 = the
     sidebar / list / detail columns. Matches the desktop app's
     two-row grid shell. */
  grid-template-rows: 40px 1fr;
  /* Fixed dimensions so the window doesn't jump when you click
     between categories with different secret counts OR meta-string
     lengths. Without an explicit width, grid-children with default
     `min-width: auto` would push the 1fr track out to min-content
     of whichever category had the longest unbreakable string —
     "api.payments.example.com" makes the list column ~13px wider
     than "production-server" does. max-width:100% lets the mockup
     shrink on tablets/mobile where viewport < 800. */
  width: 800px;
  max-width: 100%;
  /* 580 = 40px TitleBar + 540px content row, so the three columns
     keep the same height they had before the TitleBar moved inside. */
  height: 580px;
  font-size: var(--text-base);
  /* Anchor the absolutely-positioned History panel. */
  position: relative;
  /* The sidebar toggle animates the first column between 220px and the
     collapsed 52px icon rail. */
  transition: grid-template-columns 260ms cubic-bezier(0.4, 0, 0.2, 1);
}

.app-list,
.app-detail {
  /* min-width:0 overrides the default grid-child min-width:auto
     (=min-content). Without this, the .app-list track would grow
     to fit the longest meta-URL and the whole mockup would resize
     on every category click. With min-width:0, the track stays
     at the 1fr value computed from the .app-mockup width and the
     meta strings get text-overflow:ellipsis (already set further
     down) when they don't fit. */
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
}

.app-sidebar {
  overflow-y: auto;
  /* Clip the labels as they shrink to zero width in the collapsed rail. */
  overflow-x: hidden;
}

/* ---- Sidebar ---- */
.app-sidebar {
  background: var(--bg-surface-3);
  border-right: 1px solid var(--border-default);
  /* No padding top or bottom. The header owns its own vertical
     rhythm via min-height; Lock vault should sit flush against the
     window bottom — user feedback said it was floating too high. */
  padding: 0;
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

.app-sidebar-section {
  padding: var(--space-4) var(--space-4) var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  display: flex;
  align-items: center;
  justify-content: space-between;
  transition: opacity 140ms ease;
}

/* Visual alignment with the .count numbers on each category item.
   The svg has internal padding (plus path only fills ~80% of the
   viewBox), so a negative margin-right shifts the visible stroke
   out to where the '4' glyph ends — without resizing the icon. */
.app-sidebar-section-add {
  width: auto;
  height: 16px;
  border: none;
  background: transparent;
  color: var(--text-subtle);
  display: inline-flex;
  align-items: center;
  padding: 0;
  margin-right: -2px;
  cursor: pointer;
  appearance: none;
  transition: color var(--transition-default);
}

.app-sidebar-section-add svg {
  width: 13px;
  height: 13px;
}

.app-sidebar-section-add:hover,
.app-sidebar-section-add:focus-visible {
  color: var(--text-primary);
}

.app-sidebar-item {
  /* Reset <button> defaults so it looks like the original <div>. */
  background: transparent;
  border: none;
  appearance: none;
  font: inherit;
  text-align: left;
  color: inherit;
  width: 100%;

  padding: 7px var(--space-4);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  color: var(--text-tertiary);
  cursor: pointer;
  /* Padding rides the same easing as the grid-column animation so the
     dot's horizontal shift into the icon rail stays in lockstep with
     the sidebar collapse. */
  transition: background var(--transition-fast), color var(--transition-fast),
    padding 260ms cubic-bezier(0.4, 0, 0.2, 1),
    gap 260ms cubic-bezier(0.4, 0, 0.2, 1);
  font-size: var(--text-base);
}

.app-sidebar-item:hover {
  background: var(--overlay-03);
  color: var(--text-link-hover);
}

.app-sidebar-item.active {
  background: var(--overlay-06);
  color: var(--text-primary);
}

.app-sidebar-item .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* Settings rows use a 14×14 outline icon in place of the colored
   category dot — same visual slot, different metaphor (no category
   identity to communicate, just a destination). */
.app-sidebar-item .app-sidebar-icon {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  /* Pull the icon back so its optical center lines up with the
     6px category dots (the dots sit centered in their own 6px
     box, while the 14px icon would otherwise look 4px too far
     right). Negative margin keeps text-baseline alignment intact. */
  margin-left: -4px;
  margin-right: -4px;
  color: var(--text-subtle);
}

.app-sidebar-item:hover .app-sidebar-icon {
  color: var(--text-tertiary);
}

.app-sidebar-item.active .app-sidebar-icon {
  color: var(--text-primary);
}

.app-sidebar-item .count {
  margin-left: auto;
  font-size: var(--text-xs);
  color: var(--text-subtle);
  font-family: var(--font-mono);
}

/* ---- Unlocked category ----
   A category with an active time-locked permit. No row highlighting —
   the green countdown timer on the right is the sole indicator, slotted
   where the count badge usually lives. */
.app-sidebar-item.is-unlocked .app-sidebar-timer {
  margin-left: auto;
}

.app-sidebar-item.is-unlocked .count {
  display: none;
}

.app-sidebar-timer {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--accent-green);
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}

/* Settings group: pinned to the bottom of the sidebar and visually
   separated from Categories by a hairline divider above the header. */
.app-sidebar-section.is-settings-header {
  margin-top: auto;
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-default);
}

/* Pushes the bottom settings group (Settings / MCP Server / Trash /
   Lock vault) to the actual bottom of the sidebar — user feedback
   said they were floating too high when this was a fixed compact
   gap. flex:1 claims all remaining space after Categories and the
   settings group, anchoring the group to the panel floor. */
.app-sidebar-bottom-spacer {
  flex: 1;
  min-height: var(--space-4);
}

/* Hairline splitting the first settings group (Trash + Change password)
   from the second group (MCP Server + Lock vault). Kept for legacy use
   in case a view wants to re-introduce the split layout. */
.app-sidebar-divider {
  height: 1px;
  background: var(--border-subtle);
  margin: var(--space-2) var(--space-4);
}

/* ---- Collapsed sidebar ----
   The TitleBar toggle shrinks the sidebar to a narrow icon rail. The
   colored category dots and the footer icons (Settings / Trash / MCP /
   Lock) stay visible so you can still navigate; labels, timers and the
   count badges fade out while the grid column animates its width. */
.app-mockup.is-sidebar-collapsed {
  grid-template-columns: 52px 1fr 380px;
}

.app-sidebar-label,
.app-sidebar-item .app-sidebar-timer,
.app-sidebar-item .count {
  white-space: nowrap;
  overflow: hidden;
  /* min-width:0 lets a flex item shrink past its min-content width —
     without it the label keeps its longest-word width and max-width:0
     is ignored, so the dot never centers in the collapsed rail. */
  min-width: 0;
  /* A finite max-width is needed so it can animate down to 0. The items
     are never wider than the 220px sidebar, so 200px never clips. */
  max-width: 200px;
  /* Delay on the way back in: the text appears only once the column has
     widened again, so it never flashes inside a too-narrow rail. */
  transition: opacity 160ms ease 100ms, max-width 240ms ease 60ms,
    margin 240ms ease 60ms, padding 240ms ease 60ms;
}

.is-sidebar-collapsed .app-sidebar-label,
.is-sidebar-collapsed .app-sidebar-item .app-sidebar-timer,
.is-sidebar-collapsed .app-sidebar-item .count {
  opacity: 0;
  max-width: 0;
  /* Drop the spacing the unlocked-row timer / count carry (auto-margin,
     padding, divider border) so they claim zero room and the dot can
     truly center in the rail. */
  margin: 0;
  padding: 0;
  border-width: 0;
  /* No delay collapsing: the text is gone before the rail gets narrow. */
  transition: opacity 120ms ease, max-width 200ms ease,
    margin 200ms ease, padding 200ms ease;
}

/* Park the dot/icon at a fixed offset that lands its optical center on
   the 52px rail's midpoint (16+3+7 ≈ 26 = rail-center). No
   justify-content here — letting flexbox re-center the row while the
   labels/timer/count still claim non-zero width during the collapse
   transition made the dots drift horizontally based on label length. */
.is-sidebar-collapsed .app-sidebar-item {
  gap: 0;
  padding-left: 23px;
  padding-right: 23px;
}

/* The Categories header has nothing to show in the rail — fade it, but
   keep its height so the dots below don't jump. */
.is-sidebar-collapsed .app-sidebar-section {
  opacity: 0;
}

/* The toggle itself reads as active while the sidebar is closed. */
.is-sidebar-collapsed .app-titlebar-toggle {
  color: var(--text-primary);
}

/* ---- List (middle column) ---- */
.app-list {
  border-right: 1px solid var(--border-default);
  background: var(--bg-surface-2);
}

.app-list-header {
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--border-default);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  /* Kept in sync with .app-sidebar-header so both dividers align. */
  min-height: 58px;
}

.app-list-header-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.app-list-title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  line-height: 1.2;
}

.app-list-count {
  font-size: var(--text-sm);
  color: var(--text-subtle);
  font-family: var(--font-mono);
  line-height: 1.2;
}

.app-list-add {
  width: 24px;
  height: 24px;
  border-radius: var(--radius-sm);
  border: none;
  background: transparent;
  color: var(--text-subtle);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  appearance: none;
  flex-shrink: 0;
  transition: color var(--transition-default), background var(--transition-default);
}

/* Re-assert [hidden]: the display:flex above beats the UA default,
   so Trash/MCP views can actually hide the +. */
.app-list-add[hidden] {
  display: none;
}

.app-list-add svg {
  width: 14px;
  height: 14px;
}

.app-list-add:hover,
.app-list-add:focus-visible {
  color: var(--text-primary);
  background: var(--overlay-06);
}

.app-list-item {
  /* Reset <button> defaults so it looks like the original <div>. */
  background: transparent;
  border: none;
  appearance: none;
  font: inherit;
  text-align: left;
  color: inherit;
  display: block;
  width: 100%;

  padding: 14px var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
  cursor: pointer;
  transition: background var(--transition-fast);
}

.app-list-item:hover {
  background: var(--overlay-02);
}

.app-list-item.active {
  /* Background-only active state. The 2px left-stripe was an
     Impeccable absolute-ban tell — replaced with stronger fill +
     bolder name + brighter color (Linear-style row selection). */
  background: var(--overlay-06);
}

.app-list-item-name {
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  margin-bottom: var(--space-1);
}

.app-list-item.active .app-list-item-name {
  color: var(--text-primary);
  font-weight: var(--weight-semibold);
}

.app-list-item-meta {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  font-family: var(--font-mono);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Detail (right column) ----
   Background matches the list column so the three-column shell
   reads as one continuous surface. The detail fields get their
   card look from `.app-detail-rows`, not from this outer panel.
   No outer padding — the head + rows handle their own breathing
   room so the head baseline aligns with .app-sidebar-header and
   .app-list-header titles on the same y. */
.app-detail {
  background: var(--bg-surface-2);
  padding: 0 var(--space-6) var(--space-6);
}

/* ---- Detail head: name + subline, left-aligned.
        min-height locks to 58px to match .app-sidebar-header and
        .app-list-header so all three titles sit on the same y. NO
        border-bottom — the real desktop app does not divide the
        detail head from its rows, it lets the card below own that
        visual separation. ---- */
.app-detail-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  gap: 2px;
  min-height: 58px;
  padding: var(--space-3) 0;
  margin-bottom: var(--space-5);
}

.app-detail-name {
  font-size: var(--text-3xl);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  letter-spacing: -0.01em;
  margin: 0;
  line-height: 1.1;
}

.app-detail-sub {
  font-size: var(--text-sm);
  color: var(--text-subtle);
  margin: 0;
  font-family: var(--font-mono);
}

/* Settings detail subtitles are prose, not metadata — sans, not mono. */
.app-detail-sub--prose {
  font-family: var(--font-sans);
  line-height: 1.45;
}

/* ---- Change-password settings form (inside the detail column) ---- */
.app-detail-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-5) var(--space-6);
}

.app-detail-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.app-detail-field-label {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: var(--weight-semibold);
}

.app-detail-field-input {
  background: var(--bg-surface-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-base);
  font-family: var(--font-mono);
  outline: none;
  transition: border-color var(--transition-fast);
}

.app-detail-field-input:focus {
  border-color: var(--accent-green);
}

.app-detail-submit {
  background: var(--text-primary);
  color: var(--bg-base);
  border: none;
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  font-weight: var(--weight-semibold);
  cursor: pointer;
  transition: opacity var(--transition-fast);
  margin-top: var(--space-2);
}

.app-detail-submit:hover {
  opacity: 0.9;
}

.app-detail-form-hint {
  margin: 0;
  color: var(--text-subtle);
  font-size: var(--text-sm);
  line-height: 1.5;
}

/* ============ SETTINGS DETAIL VIEWS ============
   The eight settings sections (Auto-lock, Biometric, Wrapped tokens,
   Audit log, Backup, Change password, Regenerate recovery key, About)
   share these building blocks. Same padding context as the change-
   password form so every settings detail lines up. */
.app-detail-settings {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-5) var(--space-6);
}

/* A labelled control: uppercase mini-label stacked over its input. */
.app-detail-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.app-detail-section-label {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: var(--weight-semibold);
}

/* Dropdown pill. Static in the mockup — the real picker lives in the
   Tauri app. Full-width by default (Auto-lock / TTL), auto-width inside
   a toolbar (Audit-log filter). */
.app-detail-select {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  padding: var(--space-3) var(--space-4);
  background: var(--bg-surface-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font: inherit;
  font-size: var(--text-base);
  cursor: pointer;
  appearance: none;
  transition: border-color var(--transition-fast);
}

.app-detail-select:hover {
  border-color: var(--overlay-10);
}

.app-detail-select-chevron {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: var(--text-subtle);
}

/* Toggle row: label hugs left, switch pins right. */
.app-detail-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.app-detail-toggle-label {
  font-size: var(--text-base);
  color: var(--text-secondary);
}

/* Switch — track + sliding knob. On-state uses --accent-green (the one
   place green is allowed: an active/enabled control). */
.app-detail-toggle {
  flex-shrink: 0;
  width: 36px;
  height: 21px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: var(--overlay-10);
  cursor: pointer;
  appearance: none;
  transition: background var(--transition-fast);
}

.app-detail-toggle-knob {
  display: block;
  width: 15px;
  height: 15px;
  margin: 3px;
  border-radius: 50%;
  background: var(--text-primary);
  transition: transform 160ms cubic-bezier(0.4, 0, 0.2, 1);
}

.app-detail-toggle[aria-checked="true"] {
  background: var(--accent-green);
}

.app-detail-toggle[aria-checked="true"] .app-detail-toggle-knob {
  transform: translateX(15px);
  background: var(--bg-base);
}

/* Tinted info box (Wrapped-tokens "How secrets reach AI tools"). */
.app-detail-callout {
  background: var(--overlay-03);
  border: 1px solid var(--overlay-06);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.app-detail-callout-title {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-secondary);
}

.app-detail-callout-text {
  margin: 0;
  font-size: var(--text-sm);
  color: var(--text-subtle);
  line-height: 1.55;
}

.app-detail-callout-text code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  color: var(--text-tertiary);
}

/* Horizontal toolbar: filter dropdown + action button (Audit log). */
.app-detail-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.app-detail-toolbar .app-detail-select {
  width: auto;
}

/* Secondary / ghost button — Export, Check for updates, etc. */
.app-detail-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: var(--space-3) var(--space-4);
  background: var(--overlay-03);
  border: 1px solid var(--overlay-06);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  white-space: nowrap;
  cursor: pointer;
  appearance: none;
  transition: color var(--transition-fast), background var(--transition-fast),
    border-color var(--transition-fast);
}

.app-detail-action:hover {
  color: var(--text-primary);
  background: var(--overlay-06);
  border-color: var(--overlay-10);
}

/* Audit-log event cards. */
.app-detail-events {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.app-detail-event {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: var(--space-3) var(--space-4);
  background: var(--overlay-03);
  border: 1px solid var(--overlay-05);
  border-radius: var(--radius-md);
}

.app-detail-event-kind {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

.app-detail-event-detail {
  font-size: var(--text-sm);
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  line-height: 1.4;
  word-break: break-word;
}

/* Action card — a titled block with its own button (Backup section).
   Stacked vertically: the action buttons are too long to sit beside
   the description without crushing it. */
.app-detail-action-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--overlay-03);
  border: 1px solid var(--overlay-05);
  border-radius: var(--radius-md);
}

.app-detail-action-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.app-detail-action-title {
  font-size: var(--text-base);
  color: var(--text-primary);
}

.app-detail-action-card--danger .app-detail-action-title {
  color: var(--accent-amber);
}

.app-detail-action-desc {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  line-height: 1.45;
}

/* Key/value info rows (About). */
.app-detail-info {
  display: flex;
  flex-direction: column;
  background: var(--overlay-03);
  border: 1px solid var(--overlay-05);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.app-detail-info-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--overlay-04);
  font-size: var(--text-sm);
}

.app-detail-info-row:last-child {
  border-bottom: none;
}

.app-detail-info-key {
  color: var(--text-subtle);
  flex-shrink: 0;
}

.app-detail-info-val {
  color: var(--text-secondary);
  font-family: var(--font-mono);
  text-align: right;
  word-break: break-word;
}

/* Button row (About actions). */
.app-detail-action-row {
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* ---- Rows card: label/value list grouped inside a single surface.
   Horizontal padding lives on the row (not the ul) so the row
   hover background fills the full card width — otherwise the
   hover tint clips at the ul's padding edges. */
.app-detail-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--overlay-03);
  border: 1px solid var(--overlay-05);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.app-detail-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 13px var(--space-4);
  border-bottom: 1px solid var(--overlay-04);
  font-size: var(--text-md);
}

/* Label hugs left, value fills the middle and right-aligns its
   text, copy-icon sits on the right edge. Without flex:1 on the
   value, space-between would center the value between label and
   copy-icon — which is why the old layout looked mid-aligned. */
.app-detail-row-label {
  flex-shrink: 0;
}

.app-detail-row-value,
.app-detail-row-link {
  flex: 1;
}

.app-detail-row:last-child {
  border-bottom: none;
}

.app-detail-row-label {
  color: var(--text-tertiary);
  flex-shrink: 0;
}

.app-detail-row-value {
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  text-align: right;
  word-break: break-all;
  min-width: 0;
}

.app-detail-row-value--dim {
  color: var(--text-subtle);
  font-family: var(--font-sans);
}

/* Clickable URL-like values render as <a> with app-detail-row-link
   (see fieldRowHTML in hero-mockup.js). Styling ported 1:1 from the
   desktop app's SecretDetail so the mockup matches what the user
   actually gets: mono + right-aligned like a plain value, but with
   a hover underline to flag "click me". */
.app-detail-row-link {
  color: var(--text-secondary);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  text-align: right;
  text-decoration: none;
  word-break: break-all;
  min-width: 0;
  cursor: pointer;
  transition: color var(--transition-default);
}

.app-detail-row-link:hover,
.app-detail-row-link:focus-visible {
  color: var(--text-primary);
  text-decoration: underline;
  text-underline-offset: 3px;
  outline: none;
}

/* Editable values: contenteditable=true. Subtle hover hint + focus
   ring so users feel they can click-to-edit before typing. */
.app-detail-row-value[contenteditable="true"],
.app-detail-name[contenteditable="true"],
.app-list-item-name[contenteditable="true"] {
  outline: none;
  cursor: text;
  border-radius: var(--radius-xs);
  transition: background var(--transition-fast), box-shadow var(--transition-fast);
}

.app-detail-row-value[contenteditable="true"]:hover,
.app-detail-name[contenteditable="true"]:hover {
  background: var(--overlay-02);
}

.app-detail-row-value[contenteditable="true"]:focus,
.app-detail-name[contenteditable="true"]:focus,
.app-list-item-name[contenteditable="true"]:focus {
  background: var(--overlay-04);
  box-shadow: 0 0 0 2px color-mix(in oklab, var(--accent-green) 45%, transparent);
}

/* Secret value (password / ssh key): dots by default, reveals the
   plaintext on hover / focus of the row. Both children share the
   exact same typography (mono, text-base, text-primary) so swapping
   them on hover produces zero size or color shift — just content. */
.app-detail-row-value--secret {
  cursor: pointer;
}

.app-detail-row-value--secret .secret-dots,
.app-detail-row-value--secret .secret-plain {
  font-family: var(--font-mono);
  font-size: var(--text-base);
  color: var(--text-primary);
  letter-spacing: 0;
}

.app-detail-row-value--secret .secret-plain {
  display: none;
}

.app-detail-row-value--secret .secret-dots {
  user-select: none;
}

.app-detail-row:hover .app-detail-row-value--secret .secret-dots,
.app-detail-row:focus-within .app-detail-row-value--secret .secret-dots {
  display: none;
}

.app-detail-row:hover .app-detail-row-value--secret .secret-plain,
.app-detail-row:focus-within .app-detail-row-value--secret .secret-plain {
  display: inline;
}

.app-detail-row:hover {
  background: var(--overlay-02);
}

/* Copy-icon button on the right edge of every row that has a value
   worth copying (sensitive + plain editable fields). ALWAYS visible
   (the real desktop app keeps it rendered — it is a permanent
   affordance, not a hover-only one). Ported from the desktop app's
   CopyIconButton component. */
.app-detail-copy {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  border: none;
  background: transparent;
  /* Dimmed to --overlay-10 (10% white). Previous pass used
     --overlay-30 which does not exist in tokens.css (only 02/03/04/
     05/06/08/10/20/40 are defined) so the browser fell back on the
     inherited color and the icons stayed bright. The real desktop
     app's copy-icon is barely visible until hovered. */
  color: var(--overlay-10);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  appearance: none;
  transition: color var(--transition-fast),
              background var(--transition-fast);
  flex-shrink: 0;
}

.app-detail-copy:hover,
.app-detail-copy:focus-visible {
  color: var(--text-secondary);
  background: var(--overlay-06);
  outline: none;
}

.app-detail-copy svg {
  width: 13px;
  height: 13px;
}

/* Notes row: value wraps onto a second line under the label
   instead of hugging the right. */
.app-detail-row--notes {
  align-items: flex-start;
  flex-direction: column;
  gap: 4px;
}

.app-detail-row--notes .app-detail-row-value {
  text-align: left;
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--text-tertiary);
}

/* 'Add field' CTA — subtle ghost button beneath the rows card. */
.app-detail-add-field {
  margin-top: var(--space-3);
  width: 100%;
  padding: 10px var(--space-3);
  background: transparent;
  border: 1px dashed var(--overlay-10);
  border-radius: var(--radius-lg);
  color: var(--text-subtle);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  transition: color var(--transition-default), border-color var(--transition-default), background var(--transition-default);
}

.app-detail-add-field:hover,
.app-detail-add-field:focus-visible {
  color: var(--text-primary);
  border-color: var(--overlay-20);
  background: var(--overlay-03);
}

.app-detail-add-field svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

/* The dashed "Add field" button only shows when the user enters
   edit mode (otherwise it clutters the read-only state). */
.app-detail[data-editing="false"] .app-detail-add-field {
  display: none;
}

/* Trash detail uses a Restore button anchored top-right (the detail
   head is left-aligned, so we position the button absolutely).
   Styled as a visible ghost chip so users can read the intent even
   without hover. */
.app-detail-head {
  position: relative;
}

.app-detail-restore {
  position: absolute;
  top: 2px;
  right: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--overlay-03);
  border: 1px solid var(--overlay-06);
  border-radius: var(--radius-md);
  color: var(--text-tertiary);
  font-family: inherit;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  cursor: pointer;
  appearance: none;
  transition: color var(--transition-fast), background var(--transition-fast), border-color var(--transition-fast);
}

.app-detail-restore svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.app-detail-restore:hover,
.app-detail-restore:focus-visible {
  color: var(--text-primary);
  background: var(--overlay-06);
  border-color: var(--overlay-10);
  outline: none;
}

/* Read-only variant of the rows card (Trash detail). */
.app-detail-rows--readonly .app-detail-row-value {
  color: var(--text-secondary);
}

.app-detail-rows--readonly .app-detail-row:hover {
  background: transparent;
}

.app-detail-footnote {
  margin: var(--space-3) 0 0;
  font-size: var(--text-xs);
  color: var(--text-subtle);
  text-align: center;
  font-family: var(--font-sans);
  letter-spacing: 0.01em;
}

/* ---- Trash list item: dim + strikethrough name + sans meta ---- */
.app-list-item--trash .app-list-item-name {
  color: var(--text-tertiary);
  text-decoration: line-through;
  text-decoration-color: color-mix(in oklab, currentColor 30%, transparent);
}

.app-list-item--trash.active .app-list-item-name {
  color: var(--text-secondary);
}

.app-list-item--trash .app-list-item-meta {
  font-family: var(--font-sans);
  color: var(--text-subtle);
}

/* ---- List empty state (Trash is empty, MCP placeholder) ---- */
.app-list-empty {
  padding: var(--space-6) var(--space-5);
  text-align: left;
}

.app-list-empty-title {
  font-size: var(--text-base);
  color: var(--text-tertiary);
  margin-bottom: 4px;
}

.app-list-empty-hint {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  font-family: var(--font-sans);
  line-height: 1.4;
}

/* ---- Detail empty state (no selection / empty trash / MCP) ----
   When the empty state is the ONLY child of .app-detail (e.g. the
   settings menu view), we position it absolutely so it centers
   across the full detail column, not just the padded area. */
.app-detail-empty {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: var(--space-2);
  padding: var(--space-6);
}

/* Drop the detail column's own padding when it only contains an
   empty state — lets the absolutely-positioned empty state center
   across the full panel. */
.app-detail:has(> .app-detail-empty:only-child) {
  position: relative;
  padding: 0;
}

/* When the empty state follows a head (Trash view: "Trash / 30-day
   window" + empty body), revert to inline flow inside the head's
   padding context. */
.app-detail-head + .app-detail-empty {
  position: static;
  inset: auto;
  flex: 1;
  min-height: 240px;
}

.app-detail-empty-icon {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--overlay-03);
  border: 1px solid var(--overlay-05);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-subtle);
  margin-bottom: var(--space-1);
}

.app-detail-empty-icon svg {
  width: 20px;
  height: 20px;
}

.app-detail-empty-title {
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  color: var(--text-tertiary);
  margin: 0;
  letter-spacing: -0.01em;
}

.app-detail-empty-hint {
  font-size: var(--text-sm);
  color: var(--text-subtle);
  margin: 0;
  max-width: 260px;
  line-height: 1.5;
}

/* ============ HISTORY PANE (inside the detail column) ============ */
/* The pane sits inside .app-detail and replaces the secret content.
   It reuses the detail column's background + scrolling — we only
   need structural layout here. The detail column's own padding is
   cancelled so the history can span edge-to-edge. */
.app-detail:has(.app-history-pane) {
  padding: 0;
}

.app-history-pane {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
  animation: app-history-fade 180ms ease-out;
}

@keyframes app-history-fade {
  from { opacity: 0; transform: translateY(-2px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .app-history-pane { animation: none; }
}

.app-history-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--border-default);
  /* Match the detail-head vertical rhythm with the list/sidebar headers. */
  min-height: 58px;
  flex-shrink: 0;
}

.app-history-title {
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

.app-history-close {
  width: 22px;
  height: 22px;
  border-radius: var(--radius-sm);
  border: none;
  background: transparent;
  color: var(--text-subtle);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  appearance: none;
  transition: color var(--transition-fast), background var(--transition-fast);
}

.app-history-close:hover,
.app-history-close:focus-visible {
  color: var(--text-primary);
  background: var(--overlay-06);
  outline: none;
}

.app-history-close svg {
  width: 14px;
  height: 14px;
}

.app-history-list {
  list-style: none;
  margin: var(--space-4) var(--space-5);
  padding: 0;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
  /* Wrap the whole feed in a single elevated card — mirrors the
     SecretHistoryPanel chrome in the shipped app so the mockup reads
     as the same product. */
  background: var(--bg-elevated);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-2xl);
}

.app-history-entry {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-3);
  padding: 12px var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
  transition: background var(--transition-fast);
}

.app-history-entry:hover {
  background: var(--overlay-04);
}

.app-history-entry:last-child {
  border-bottom: none;
}

.app-history-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.app-history-entry-title {
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-history-entry-sub {
  font-size: 11px;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

.app-history-chevron {
  width: 14px;
  height: 14px;
  color: var(--text-muted);
  flex-shrink: 0;
}
.app-history-entry:hover .app-history-chevron {
  color: var(--text-primary);
}

/* Legacy rules kept for the empty state + footer below — the
   entry-specific .app-history-detail isn't rendered anymore but some
   descendants still rely on .app-history-* utilities. */
.app-history-detail-legacy {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  font-family: var(--font-mono);
  line-height: 1.5;
  word-break: break-word;
}

.app-history-old {
  color: var(--text-subtle);
  text-decoration: line-through;
  text-decoration-color: color-mix(in oklab, currentColor 40%, transparent);
}

.app-history-arrow {
  color: var(--text-subtle);
  padding: 0 2px;
}

.app-history-new {
  color: var(--text-primary);
}

.app-history-field {
  color: var(--text-secondary);
}

.app-history-name {
  color: var(--text-primary);
}

.app-history-empty {
  padding: var(--space-6) var(--space-4);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 6px;
}

.app-history-empty-icon {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--overlay-03);
  border: 1px solid var(--overlay-05);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-subtle);
  margin-bottom: 4px;
}

.app-history-empty-icon svg {
  width: 16px;
  height: 16px;
}

.app-history-empty-title {
  font-size: var(--text-sm);
  color: var(--text-tertiary);
  font-weight: var(--weight-medium);
}

.app-history-empty-hint {
  font-size: var(--text-xs);
  color: var(--text-subtle);
  max-width: 200px;
  line-height: 1.4;
}

.app-history-footer {
  padding: 10px var(--space-5);
  border-top: 1px solid var(--border-default);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--text-subtle);
  text-align: center;
  background: var(--overlay-02);
  flex-shrink: 0;
}

/* ============ CONTEXT MENU (right-click on list rows) ============ */
.app-context-menu {
  position: fixed;
  z-index: 100;
  min-width: 160px;
  padding: 4px;
  background: var(--bg-surface-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-popover);
  display: flex;
  flex-direction: column;
  animation: app-context-menu-in 120ms ease-out;
  transform-origin: top left;
}

@keyframes app-context-menu-in {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .app-context-menu { animation: none; }
}

.app-context-menu-item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 8px 12px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-family: inherit;
  font-size: var(--text-sm);
  text-align: left;
  cursor: pointer;
  appearance: none;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.app-context-menu-item svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  color: var(--text-subtle);
  transition: color var(--transition-fast);
}

.app-context-menu-item:hover,
.app-context-menu-item:focus-visible {
  background: var(--overlay-06);
  color: var(--text-primary);
  outline: none;
}

.app-context-menu-item:hover svg,
.app-context-menu-item:focus-visible svg {
  color: inherit;
}

.app-context-menu-item--danger:hover,
.app-context-menu-item--danger:focus-visible {
  background: color-mix(in oklab, var(--accent-red) 14%, transparent);
  color: var(--accent-red);
}

/* Thin divider between action group (edit/history) and the
   destructive Delete item. */
.app-context-menu-separator {
  height: 1px;
  margin: 4px 2px;
  background: var(--overlay-06);
}

/* Green unread dot next to "History" when there are changes the user
   hasn't seen yet. Sits at the right edge of the menu item. */
.app-context-menu-item {
  position: relative;
}

.app-context-menu-dot {
  margin-left: auto;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent-green);
  flex-shrink: 0;
}

/* ============ MENUBAR MOCKUP (Feature 1) ============ */
.menubar-mockup {
  max-width: 380px;
  margin: 0 auto;
  padding: var(--space-8) 0 var(--space-12);
}

.menubar-window {
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-2xl);
  overflow: hidden;
  box-shadow: var(--shadow-window);
  /* Fixed height so the outer frame doesn't jump when switching
     tabs, granting, or revoking. Body scrolls internally if the
     Active list grows past capacity. */
  height: 430px;
  display: flex;
  flex-direction: column;
}

.menubar-tabs {
  display: flex;
  flex-shrink: 0;
  border-bottom: 1px solid var(--border-default);
}

.menubar-tab {
  flex: 1;
  text-align: center;
  padding: var(--space-3);
  font-size: var(--text-base);
  font-weight: var(--weight-medium);
  font-family: inherit;
  color: var(--text-subtle);
  cursor: pointer;
  transition: color var(--transition-default), border-bottom-color var(--transition-default);
  border: none;
  border-bottom: 2px solid transparent;
  background: transparent;
  appearance: none;
}

.menubar-tab:hover {
  color: var(--text-tertiary);
}

.menubar-tab.active {
  color: var(--text-primary);
  border-bottom-color: var(--text-primary);
}

.menubar-body {
  padding: var(--space-6);
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

/* Grant-panel-only: distribute the 3 blocks (Category, Duration, CTA)
   across the fixed-height window. Active panel stacks top-to-bottom
   with natural spacing instead. */
.menubar-body[data-panel="grant"] {
  justify-content: space-between;
}

/* display:flex above beats [hidden]'s user-agent display:none —
   re-assert so the inactive panel actually hides. */
.menubar-body[hidden] {
  display: none;
}

/* Active panel: tighten gap between permits + add a sticky scroll-more
   indicator that floats at the bottom while there's more content
   below the fold. */
.menubar-body--active {
  gap: var(--space-1);
  position: relative;
}

.menubar-scroll-more {
  position: sticky;
  bottom: 6px;
  align-self: center;
  margin-top: auto;
  /* Bigger circle so it reads as a tappable target, not a stray
     decoration. aspect-ratio:1 + flex-basis lock the box to a
     perfect square regardless of any inherited line-height. */
  flex: 0 0 36px;
  width: 36px;
  height: 36px;
  aspect-ratio: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: 9999px;
  color: var(--text-tertiary);
  cursor: pointer;
  appearance: none;
  padding: 0;
  box-shadow: var(--shadow-float);
  transition:
    color var(--transition-default),
    background var(--transition-default),
    transform var(--transition-default);
}

.menubar-scroll-more:hover,
.menubar-scroll-more:focus-visible {
  color: var(--text-primary);
  background: var(--bg-product);
  transform: translateY(-1px);
  outline: none;
}

.menubar-scroll-more svg {
  width: 18px;
  height: 18px;
}

.menubar-scroll-more[hidden] {
  display: none;
}

/* Inner grouping for Category + Duration: label sits above its
   input, margins inside the group stay tight. */
.menubar-field {
  display: flex;
  flex-direction: column;
}

/* Active-view body: tighter padding, permits rendered as stack.
   Shares .active-permit / .active-permit-bar / .active-permit-locked
   styles (originally drafted for a separate mockup, now reused here). */
.menubar-body--active {
  padding: var(--space-3);
}

.menubar-field-label {
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--text-subtle);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: var(--space-2);
}

.menubar-select {
  width: 100%;
  padding: 10px 14px;
  background: var(--overlay-04);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  color: var(--text-secondary);
  font-size: var(--text-md);
  font-family: var(--font-sans);
  margin-bottom: var(--space-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  position: relative;
  transition: background var(--transition-default), border-color var(--transition-default);
  user-select: none;
}

.menubar-select:hover,
.menubar-select[aria-expanded="true"] {
  background: var(--overlay-06);
  border-color: var(--overlay-20);
}

.menubar-select-value {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.menubar-select-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.menubar-select-chevron {
  width: 14px;
  height: 14px;
  opacity: 0.5;
  flex-shrink: 0;
  transition: transform var(--transition-default);
}

.menubar-select[aria-expanded="true"] .menubar-select-chevron {
  transform: rotate(180deg);
}

/* Dropdown panel — positioned absolute just below the select.
   [hidden] must override display:flex, hence the explicit rule. */
.menubar-select-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 10;
  list-style: none;
  margin: 0;
  padding: 6px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-window);
  display: flex;
  flex-direction: column;
  gap: 2px;
  animation: menubar-select-menu-in 160ms ease-out;
}

.menubar-select-menu[hidden] {
  display: none;
}

@keyframes menubar-select-menu-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

.menubar-select-option {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 9px 10px;
  border-radius: var(--radius-md);
  font-size: var(--text-md);
  color: var(--text-tertiary);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.menubar-select-option:hover {
  background: var(--overlay-04);
  color: var(--text-primary);
}

.menubar-select-option.is-selected {
  color: var(--text-primary);
  background: var(--overlay-03);
}

@media (prefers-reduced-motion: reduce) {
  .menubar-select-menu { animation: none; }
  .menubar-select-chevron { transition: none; }
}

.menubar-timer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-5);
  margin-bottom: var(--space-6);
}

.menubar-timer-btn {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border-strong);
  background: var(--overlay-03);
  color: var(--text-muted);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-family: inherit;
  padding: 0;
  cursor: pointer;
  appearance: none;
  transition: border-color var(--transition-default), color var(--transition-default), background var(--transition-default);
}

.menubar-timer-btn:hover {
  border-color: var(--text-subtle);
  color: var(--text-tertiary);
  background: var(--overlay-05);
}

.menubar-timer-btn:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.menubar-timer-btn:disabled:hover {
  border-color: var(--border-strong);
  color: var(--text-muted);
  background: var(--overlay-03);
}

.menubar-timer-value {
  font-size: var(--text-timer);
  font-weight: var(--weight-semibold);
  color: var(--text-primary);
  font-family: var(--font-mono);
  letter-spacing: -0.03em;
  line-height: 1;
}

.menubar-timer-unit {
  font-size: var(--text-base);
  color: var(--text-subtle);
  text-align: center;
  margin-top: -16px;
  margin-bottom: var(--space-6);
  font-family: var(--font-mono);
}

.menubar-grant-btn {
  width: 100%;
  padding: var(--space-3);
  background: var(--text-primary);
  color: var(--text-button-fg);
  border: none;
  border-radius: var(--radius-lg);
  font-size: var(--text-md);
  font-weight: var(--weight-semibold);
  font-family: var(--font-sans);
  cursor: pointer;
  transition: background var(--transition-default);
  letter-spacing: -0.01em;
  /* Positioning handled by body's justify-content: space-between —
     no longer needs margin-top: auto. */
}

.menubar-grant-btn:hover {
  background: var(--text-button-hover-bg);
}

/* ============ TERMINAL MOCKUP (Feature 2) ============ */
.terminal-mockup {
  padding: var(--space-7) var(--space-8) var(--space-13);
  font-family: var(--font-mono);
  font-size: var(--text-base);
  line-height: 2;
}

.terminal-prompt { color: var(--text-subtle); }
.terminal-fn     { color: var(--accent-purple-soft); }
.terminal-string { color: var(--accent-green-soft); }
.terminal-comment{ color: var(--text-subtle); }
.terminal-result { color: var(--text-tertiary); padding-left: var(--space-5); }
.terminal-error  { color: var(--accent-red);    padding-left: var(--space-5); }

.terminal-line { margin-bottom: 2px; }
.terminal-gap  { height: var(--space-4); }

/* ============ ACTIVE PERMIT ROWS (Feature 1 menubar) ============ */
.active-permit {
  /* Was: padding var(--space-4) + margin-bottom var(--space-1).
     Both shrunk because the parent flex container now uses
     gap: var(--space-1), which doubled with the margin. Vertical
     padding also down a notch — header + bar + revoke don't need
     16px of breathing room above and below. */
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
}

.active-permit:hover {
  background: var(--overlay-02);
}

.active-permit-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}

.active-permit-name {
  font-size: var(--text-md);
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.active-permit-name .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
}

.active-permit-time {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--accent-green);
}

.active-permit-revoke {
  margin-top: 10px;
  font-size: var(--text-sm);
  color: var(--text-subtle);
  cursor: pointer;
  transition: color var(--transition-default);
  background: transparent;
  border: none;
  padding: 2px 0;
  font-family: inherit;
  appearance: none;
  display: inline-block;
}

.active-permit-revoke:hover,
.active-permit-revoke:focus-visible {
  color: var(--accent-red);
}
