/* ===========================================================
   AdHush — Mini overlay (260×40 glass pill).

   CANONICAL SOURCE: pill-production-render-rig.html (repo root).
   See Open design finals/LOCKED.md + LOCK_HEAD.json.

   ARCHITECTURE (2026-05-24, see-through pill fix)
   -----------------------------------------------
   The pill renders in TWO layers, plus the ::before sheen:

     .pill           border + box-shadows + rounded clip-region
                     (NO background, NO backdrop-filter — see PWV-2 note)
      ├ .pill__backing  z-index 0  the glass fill (chroma-key halftone)
      ├ .pill::before  z-index 1  top-edge gradient sheen
      └ .body          z-index 2  dot / brand / spectrum / buttons / appview

   Why .pill__backing exists
   -------------------------
   pywebview's WebView2 host runs `transparent=True + bg=#000000` and
   chroma-keys ONLY pixels rendered as exact opaque #000000 through to
   the desktop. A flat `rgba(15,17,25,0.18)` background painted directly
   on .pill (the rig-verbatim approach) composites against the body's
   #000000 to ~#030305 opaque — close to black but NOT exact #000000, so
   chroma-key doesn't fire and the pill renders as an opaque dark slab
   over the wallpaper. That's the production-render bug observed in the
   installed EXE on 2026-05-24.

   .pill__backing fixes this by painting a 2px-tile diagonal HALFTONE:
   half the cells are opaque dark glass tint (#0f1119, the effective
   color of the locked spec's 0.85-alpha backing), half are `transparent`
   over `background-color: #000000` so the final pixel is exact #000000
   and chroma-keys out. Display-DPI antialiasing blurs the 2px pattern
   to a roughly 50% effective transparency — the wallpaper bleeds through
   the pill while the tint cells keep the white text + colored spectrum
   readable. See §PILL BACKING for the rule.

   What the additions to the rig file are
   --------------------------------------
     - bundled @font-face declarations (JetBrains Mono + Geist Mono)
     - --font-mono variable with defensive fallback chain
     - html/body chroma-key background (#000000) for pywebview
     - cursor: grab on .body for drag affordance
     - .btn[data-slot=refresh].is-spinning animation
     - .appview .is-off state class for production toggle
     - .pill__backing chroma-key halftone (this file's see-through layer)

   Pattern C runtime upgrade path (clean glass)
   --------------------------------------------
   The halftone is a CSS-only workaround for the chroma-key compositor.
   For a clean, un-dithered glass effect, switch the pywebview window to
   Win11 acrylic via `DwmSetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE,
   3, ...)` (Pattern C in LOCKED.md) and replace the halftone in
   .pill__backing with a single `rgba(15, 17, 25, 0.55)` flat fill — the
   DWM compositor then delivers real translucency through the window
   chrome and CSS no longer has to fake it.

   overflow: visible on .pill so tooltips can escape its bounds.
   =========================================================== */

/* Runtime mono faces — bundled locally so the installed pywebview pill
   matches the locked Open Design reference instead of falling back to a
   different Windows monospace. */
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/JetBrainsMono-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Geist Mono';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/GeistMono.woff2') format('woff2');
}

:root {
  --ink-1:  #f6f6fb;
  --ink-3:  #8f8fa6;
  --cyan:   #5cf2ea;
  --green:  #34d399;
  --amber:  #fbbf24;
  --red:    #f87171;

  /* Shipping monospace — prefer JetBrains Mono (what was designed in Open Design)
     with Geist Mono (bundled woff2) as deterministic fallback when JetBrains Mono
     is not installed system-wide. JetBrains Mono is visually wider than Geist Mono,
     which is the correct ADHUSH wordmark width per the locked Open Design lock. */
  --font-mono: "JetBrains Mono", "JetBrains Mono NL", "Geist Mono", ui-monospace, "Cascadia Mono", monospace;

  /* Spectrum geometry (scale=1 for the real 260×40 pill) */
  --bar-w:      2px;
  --bar-gap:    1px;
  --spectrum-h: 24px;
}

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

html, body {
  /* Sized to the OS window CLIENT area (600×240 — see runner.py
     create_window). The CSS .pill stays at its locked 260×40 design
     geometry; the surplus 340×200 px around the pill paints the
     chroma-key sentinel (#1A1A1A) which Windows' layered-window engine
     makes truly transparent at the OS level. The generous surplus
     gives tooltips, the tiny-mode ADHUSH hump, and future popovers
     room to render above/below/beside the pill without being clipped
     at the WebView2 viewport boundary. */
  width: 600px;
  height: 240px;
  overflow: hidden;
  /* Flex-center the pill within the OS window. The pill is centered
     in the 600×240 surface; everything around it paints the sentinel
     and chroma-keys to desktop. */
  display: flex;
  align-items: center;
  justify-content: center;
  /* CHROMA-KEY SENTINEL — we set this up ourselves via Win32.
     Neither chroma-key NOR true-alpha just works in pywebview's
     transparent=True path (confirmed by reading the source: it sets
     ControlStyles.SupportsTransparentBackColor + WebView2's
     DefaultBackgroundColor = Color.Transparent, but does NOT engage
     WS_EX_LAYERED, AllowTransparency, TransparencyKey, or any DWM
     SystemBackdrop — so the Form's GDI canvas paints opaque
     whatever-the-default is and WebView2 transparent areas show that).
     runner.py's _apply_mini_layered_transparency() (called on
     mini_window.events.shown) calls Win32 SetWindowLongW + WS_EX_LAYERED
     and SetLayeredWindowAttributes with crKey = COLORREF(0x001A1A1A)
     = RGB(26, 26, 26) = #1A1A1A. Any pixel matching this color EXACTLY
     at the final layered-window stage becomes alpha=0 and shows the
     desktop through. The sentinel was chosen so the .pill__backing
     rgba(15, 17, 25, 0.85) blend over it produces ~(17, 18, 25) —
     imperceptibly close to the design (15, 17, 25) and mathematically
     distinct from the sentinel, so the pill renders visibly while
     the surround chroma-keys cleanly. */
  /* TAURI 2 OVERRIDE — v2 host uses true per-pixel alpha via
     DirectComposition / DWM SystemBackdrop. No chroma-key needed:
     the 600×240 surround paints fully transparent, .pill__backing's
     rgba(15,17,25,0.85) composites directly against the desktop.
     The #1a1a1a sentinel above is a historical comment for legacy
     pywebview (AdHush v0.1.7) and no longer active. */
  background: transparent;
  color: var(--ink-1);
  font-family: -apple-system, "Segoe UI Variable", "Segoe UI", system-ui, sans-serif;
  font-size: 13px;
  -webkit-font-smoothing: antialiased;
  user-select: none;
  -webkit-user-select: none;
}

/* ===========================================================
   THE PILL — 260×40 glass-prism shell
   ===========================================================
   Height 40px (2026-05-29) to match Ben's ACTUAL Windows taskbar
   (40 px) so the pill sits flush IN the taskbar without protruding
   above it. Pass A's 2026-05-28 bump to 48px overshot — the real
   taskbar is 40px, corrected here. Internal flex `align-items:
   center` re-centers dot / brand / spectrum / buttons automatically;
   MUTE morph stays correct because spectrum cols are positioned
   relative to the spectrum element, not the pill. */
.pill {
  position: relative;
  width: 286px;
  height: 34px;
  border-radius: 10px;
  /* NO background and NO backdrop-filter here — see file preamble.
     The translucent fill lives on .pill__backing so it can be a chroma-key
     halftone instead of a flat color. .pill owns ONLY the rounded clip-
     region, border hairline, and box-shadows (sheen comes from ::before). */
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.16),
    inset 0 -1px 0 rgba(0, 0, 0, 0.28),
    0 6px 18px rgba(0, 0, 0, 0.45);
  /* visible so tooltips can escape pill bounds */
  overflow: visible;
}

/* ===========================================================
   PILL BACKING — the see-through glass fill (chroma-key halftone)
   ===========================================================
   Renders the pill's translucent body. Sits BELOW .pill::before (sheen)
   and .body (content) via z-index. See file preamble for the chroma-key
   compositor reasoning. Geometry inherits from .pill so the rounded
   corners line up perfectly with the border.
   =========================================================== */
.pill__backing {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  /* Pill fill — rgba 0.85 (LOCKED.md canonical). Blends with the
     chroma-key sentinel #1A1A1A behind: result ≈ (17, 18, 25), which
     reads as the design's dark-glass (15, 17, 25) and is distinct
     enough from the sentinel that the chroma-key doesn't match.
     Result: visibly dark-glass pill on truly transparent surround.
     If/when we move to per-pixel-alpha (WS_EX_NOREDIRECTIONBITMAP
     pywebview patch), drop this back to 0.55 or lower so wallpaper
     bleeds through the pill body. */
  background: rgba(15, 17, 25, 0.85);
  /* backdrop-filter kept for Pattern C upgrade path: in chroma-key mode it
     is a no-op (nothing painted behind the page to blur), but the moment
     pywebview switches to acrylic this line starts doing useful work
     without another CSS edit. Safe to leave in. */
  -webkit-backdrop-filter: blur(4px) saturate(125%);
  backdrop-filter: blur(4px) saturate(125%);
}

.pill::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  border-radius: inherit;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.06) 0%,
    rgba(255, 255, 255, 0)    60%);
}

/* ===========================================================
   PILL CONTROLS — lock + link micro-icons (Pass A 2026-05-28)
   ===========================================================
   Two tiny utility toggles that FLANK the ADHUSH wordmark inline
   (2026-05-29 — moved out of the old top-left absolute strip). Default
   state is intentionally faint so they don't compete with the spectrum
   + APP VIEW chip; hover lifts them to ~72% white; active (toggled-on)
   state lights the icon cyan with a soft glow matching the spectrum
   bars' luminescence.

   They live inside .brand-wrap (lock · ADHUSH · link) so they sit on the
   wordmark's vertical midline. Being inline DOES consume row width, so
   they're kept to 10×10 with a 3px gap and the spectrum's MUTE pixel-snap
   was re-verified after the move. */
.brand-wrap {
  display: flex;
  align-items: center;
  gap: 3px;
  flex-shrink: 0;
}

.pill-ctl {
  width: 10px;
  height: 10px;
  padding: 0;
  border: 0;
  background: transparent;
  color: rgba(255, 255, 255, 0.32);
  cursor: pointer;
  display: grid;
  place-items: center;
  border-radius: 2px;
  transition:
    color    .15s ease,
    filter   .15s ease,
    background-color .15s ease;
}
.pill-ctl:hover {
  color: rgba(255, 255, 255, 0.72);
  background: rgba(255, 255, 255, 0.08);
}
.pill-ctl.is-active {
  color: var(--cyan);
  filter:
    drop-shadow(0 0 1.5px rgba(92, 242, 234, 0.95))
    drop-shadow(0 0 3.5px rgba(92, 242, 234, 0.55));
}
.pill-ctl.is-active:hover {
  background: rgba(92, 242, 234, 0.10);
}
.pill-ctl svg {
  width: 100%;
  height: 100%;
  display: block;
}

.body {
  position: relative;
  height: 100%;
  display: flex;
  align-items: center;
  /* TAURI 2 FIX (2026-05-28) — was gap:6px padding:0 7px. Tauri/WebView2
     in transparent-window mode renders ADHUSH + APP VIEW slightly wider
     than legacy pywebview's WebView2 host did, so the flex-distributed
     space for .spectrum dropped from ~60–62px to ~57–59px, clipping the
     trailing edge of the MUTE 'E' and pushing the leading edge onto a
     fractional pixel (col 1, the M's left vertical, anti-aliased thin).
     Reclaiming 9px (4px from padding + 5px from gap) restores the
     spectrum to its design-intended 60–62px window. Spacing remains
     visually balanced — the change is sub-perceptual to the eye but
     decisive for pixel-snap on the spectrum's leading edge. */
  gap: 5px;
  padding: 0 5px;
  z-index: 2;
  border-radius: inherit;
  cursor: grab;
}
.body:active { cursor: grabbing; }

/* ===========================================================
   STATE DOT — green=playing, amber=idle, red(pulse)=muting
   =========================================================== */
.dot {
  width: 6px;
  height: 6px;
  border-radius: 99px;
  background: var(--green);
  box-shadow: 0 0 5px var(--green);
  flex-shrink: 0;
  transition: background-color 0.4s ease, box-shadow 0.4s ease;
}
.dot.idle   {
  background: var(--amber);
  box-shadow: 0 0 5px var(--amber);
  animation: none;
}
.dot.muting {
  background: var(--red);
  box-shadow: 0 0 5px var(--red);
  animation: dot-pulse 1.2s ease-in-out infinite;
}
@keyframes dot-pulse {
  0%, 100% { opacity: 1;    transform: scale(1); }
  50%       { opacity: 0.30; transform: scale(0.85); }
}

/* ===========================================================
   BRAND — small caps mono wordmark
   =========================================================== */
.brand {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.10em;
  color: rgba(255, 255, 255, 0.96);
  text-transform: uppercase;
  margin-left: 2px;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
  flex-shrink: 0;
}

/* ===========================================================
   SPECTRUM — animated bars / MUTE morph
   =========================================================== */
.spectrum {
  flex: 1;
  min-width: 0;
  height: var(--spectrum-h);
  display: flex;
  align-items: center;
  /* Was `justify-content: center`. Under center-justify, when the 59px of
     spectrum content can't fit cleanly in the flex-distributed container
     (typically ~60–61px), the ~1px overflow splits 0.5px / 0.5px across
     the two sides. The leading-edge sub-pixel offset lands on col 1 — the
     M's left vertical — rendering it at 50% coverage across two pixels,
     which reads visibly thinner than its mirror col 5. flex-start anchors
     content to the spectrum's leading edge on an integer-pixel boundary,
     so every M/U/T/E vertical stroke renders solid at its designed 2px.
     Visual centering of MUTE comes from the column array itself (col 0
     and cols 18-19 are silent leadin/trailout). */
  justify-content: flex-start;
  gap: var(--bar-gap);
  /* Padding REMOVED (was: 0 4px). The 20 spectrum columns total 59px of
     content; the flex-distributed container provides ~60–62px. With 8px
     of internal padding, content overflowed by ~6px and clipped equally
     on both sides under `overflow: hidden`. Browsers round sub-pixel
     center-overflow toward the leading edge, so the leftmost stroke of
     the M morph rendered visibly clipped while the right looked fine.
     0-padding fits the content cleanly; .body's 6px flex `gap` keeps
     the M letterform off the ADHUSH wordmark. If a future revision
     reintroduces the M-kisses-brand symptom, the approved deviation is
     the asymmetric tune `0 2px 0 14px` (shifts bars 6px right). */
  padding: 0;
  position: relative;
  overflow: hidden;
  border-radius: 4px;
}

.col {
  width: var(--bar-w);
  height: var(--spectrum-h);
  position: relative;
  flex-shrink: 0;
}

.seg {
  position: absolute;
  left: 0;
  width: 100%;
  border-radius: 1px;
  background: var(--cyan);
  box-shadow: 0 0 3px rgba(92, 242, 234, 0.55);
  top:    var(--t, 50%);
  height: var(--h, 0);
  transition:
    top        var(--morph-dur, 0.55s) cubic-bezier(.55, 0, .25, 1),
    height     var(--morph-dur, 0.55s) cubic-bezier(.55, 0, .25, 1),
    background-color calc(var(--morph-dur, 0.55s) * 0.85) ease,
    box-shadow       calc(var(--morph-dur, 0.55s) * 0.85) ease,
    opacity          calc(var(--morph-dur, 0.55s) * 0.65) ease;
}

/* ── PLAYING ─────────────────────────────────────────────── */
.pill.playing .col .s1,
.pill.playing .col .s3 { --t: 50%; --h: 0; opacity: 0; }

.pill.playing .col .s2 {
  background: var(--cyan);
  box-shadow: 0 0 3px rgba(92, 242, 234, 0.55);
  opacity: 1;
  --t: calc((var(--spectrum-h) - var(--peak, 12px)) / 2);
  --h: var(--peak, 12px);
  transform-origin: 50% 50%;
  animation: breathe var(--breathe-dur, 1s) ease-in-out infinite;
  animation-delay: var(--breathe-delay, 0s);
}
@keyframes breathe {
  0%, 100% { transform: scaleY(0.55); opacity: 0.7; }
  50%       { transform: scaleY(1.00); opacity: 1.0; }
}

/* ── IDLE ────────────────────────────────────────────────── */
.pill.idle .col .s1,
.pill.idle .col .s3 { --t: 50%; --h: 0; opacity: 0; }

.pill.idle .col .s2 {
  --t: calc((var(--spectrum-h) - 2px) / 2);
  --h: 2px;
  opacity: 0.55;
  animation: none;
  transform: none;
  /* Idle bars match the amber state dot (2026-06-01) instead of the cyan
     'playing' luminescence, so a not-playing pill reads uniformly yellow.
     opacity bumped 0.22→0.55 so the thin amber baseline stays visible. */
  background: var(--amber);
  box-shadow: 0 0 3px rgba(251, 191, 36, 0.55);
}

/* ── MUTING — bars snap into MUTE letter shapes ──────────── */
.pill.muting .col .seg {
  background: var(--red);
  box-shadow: 0 0 4px rgba(248, 113, 113, 0.65);
  opacity: 1;
  animation: none;
  transform: none;
}
.pill.muting .col .s1 { --t: var(--s1-t, 50%); --h: var(--s1-h, 0); }
.pill.muting .col .s2 { --t: var(--s2-t, 50%); --h: var(--s2-h, 0); }
.pill.muting .col .s3 { --t: var(--s3-t, 50%); --h: var(--s3-h, 0); }
.pill.muting .col .seg[data-empty="1"] { opacity: 0; }

/* ===========================================================
   BUTTONS — 24×24 hit target, optically matched glyphs
   Refresh icon paints ~16/24 of viewBox → 16px
   Volume-X paints ~14/24  → bump to 18.5px to match painted edges
   =========================================================== */
.btn {
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: rgba(255, 255, 255, 0.82);
  display: grid;
  place-items: center;
  cursor: pointer;
  flex-shrink: 0;
  position: relative;
  transition: background-color .15s ease, color .15s ease;
}
.btn:hover { background: rgba(255, 255, 255, 0.16); color: #fff; }

.btn svg {
  display: block;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.6));
}
.btn[data-slot="refresh"] svg { width: 16px;   height: 16px; }
.btn[data-slot="mute"]    svg { width: 18.5px; height: 18.5px; }

/* Refresh spinning during fetch */
.btn[data-slot="refresh"].is-spinning svg {
  animation: spin 0.9s linear infinite;
  transform-origin: 50% 50%;
}
@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ===========================================================
   APP VIEW CHIP — toggles the full panel window
   =========================================================== */
.appview {
  /* 2026-06-09 (Ben): compact + tiny both render the App View control as a
     small circular EYE button. The old text "APP VIEW" chip ate ~70px and
     squeezed the spectrum so the MUTE morph's trailing E clipped. The eye
     matches the tiny pill for consistency and frees the room. */
  width: 20px;
  height: 20px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 99px;
  border: 1px solid rgba(92, 242, 234, 0.42);
  background: rgba(92, 242, 234, 0.14);
  flex-shrink: 0;
  cursor: pointer;
  position: relative;
  transition: background-color .15s ease, border-color .15s ease;
}
.appview:hover {
  background: rgba(92, 242, 234, 0.22);
  border-color: rgba(92, 242, 234, 0.52);
}
.appview.is-off {
  border-color: rgba(92, 242, 234, 0.42);
  background: rgba(92, 242, 234, 0.14);
}

/* Dot + text label retired in favor of the eye (kept in the DOM for a11y/JS). */
.appview-dot { display: none; }
.appview-label { display: none; }

/* ===========================================================
   TINY MODE — super-minimal Spotify-companion variant
   ===========================================================
   Triggered when .pill carries .is-tiny. The pill narrows from 260×40
   to 124×40 (height unchanged so it still matches the 40px taskbar) and
   re-centers inside the transparent 600×240 Tauri host window (the
   surround composites fully transparent via DirectComposition, so the
   OS window VISUALLY appears as just the narrow pill).

   Surface contents in tiny mode:
     • spectrum   — state indicator (idle / playing / muting MUTE morph)
     • mute btn   — manual mute toggle
     • refresh    — refresh app state
     • .appview   — collapses to a ~22×22 circular puck so the cycle
                    button is still reachable (its dot indicates the
                    next mode in the cycle; see mini.js)
   Hidden in tiny mode:
     • .brand     — "ADHUSH" wordmark removed per design (m0014)
     • .dot      — redundant with spectrum, kept off for minimalism
     • .appview-label — only the dot remains, label hidden
   =========================================================== */
.pill.is-tiny {
  /* Narrow companion variant (2026-05-29). Width drops to 124px (the mute
     button is removed in this mode — just spectrum + refresh + eye-puck),
     but HEIGHT stays 40px to match the compact pill and sit flush in Ben's
     40px Windows taskbar. Radius 10 mirrors the compact pill so both read
     as the same pill family; only the width distinguishes them. */
  width: 124px;
  height: 34px;
  border-radius: 10px;
}

.pill.is-tiny .body {
  gap: 4px;
  padding: 0 6px;
}

.pill.is-tiny .dot,
.pill.is-tiny .btn[data-slot="mute"] {
  display: none;
}

/* Tiny mode (2026-06-01): the .brand-wrap IS the hump. Lock · ADHUSH ·
   link live together inside one notch above the pill, with the two
   buttons spaced like extra glyphs flanking the wordmark (gap = inter-
   letter rhythm, not edge-to-edge). The standalone .pill-logo-hump text
   element is suppressed so there is a single source of truth for the
   hump. Chrome (bg/border/radius/halftone) mirrors the old hump exactly
   so the see-through behavior and merged-perimeter look are unchanged. */
.pill.is-tiny .brand-wrap {
  position: absolute;
  left: 50%;
  bottom: 100%;
  transform: translate(-50%, 5px);
  width: auto;
  min-width: 56px;
  height: 12px;
  padding: 0 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  background: rgba(15, 17, 25, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-bottom: 0;
  border-radius: 5px 5px 0 0;
  z-index: 4;
  pointer-events: auto;
}

/* ADHUSH wordmark inside the tiny hump. Higher specificity than the
   generic tiny hides above, so it un-hides .brand only when nested in
   the hump. margin-left:0 lets the flex `gap` own the lock↔word spacing. */
.pill.is-tiny .brand-wrap .brand {
  display: inline-block;
  margin-left: 0;
  font-size: 7px;
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
}

.pill.is-tiny .pill-ctl {
  width: 9px;
  height: 9px;
  border-radius: 1.5px;
}

/* The 24px hit-target buttons are kept full-size for accessibility — only
   the chrome shrinks, not the controls. Spectrum keeps its 24px height
   so the absolutely-positioned MUTE strokes (positioned via JS-baked
   `top: TOP + row*ROW` with TOP=6) stay vertically centered — a shorter
   spectrum would push the 12px-tall morph below the pill's centerline. */

/* .appview collapses to a small circle. Diameter 18px gives the eye
   icon room without making the chip's tint look chunky relative to the
   pill. Background drops to fully transparent so only the 1px border
   reads as a ring — the glowing eye inside carries the affordance. */
.pill.is-tiny .appview,
.pill.is-tiny .appview.is-off {
  width: 18px;
  height: 18px;
  padding: 0;
  border-radius: 99px;
  justify-content: center;
  gap: 0;
  background: transparent;
  border-color: rgba(92, 242, 234, 0.32);
}
.pill.is-tiny .appview:hover,
.pill.is-tiny .appview.is-off:hover {
  background: rgba(92, 242, 234, 0.12);
  border-color: rgba(92, 242, 234, 0.52);
}
.pill.is-tiny .appview-dot {
  display: none;
}
.pill.is-tiny .appview-label {
  display: none;
}

/* Glowing cyan eye — swaps in for the dot in tiny mode. The eye SVG is
   injected by mini.js at boot (ICON_EYE) into the .appview-eye host
   span. Hidden by default; only the tiny-mode rule un-hides it. The
   double drop-shadow stacks an inner sharp glow + outer soft halo to
   match the cyan luminescence on the spectrum bars. */
.appview-eye {
  display: grid;
  place-items: center;
  width: 13px;
  height: 13px;
  color: var(--cyan);
  filter:
    drop-shadow(0 0 1px rgba(92, 242, 234, 1))
    drop-shadow(0 0 4px rgba(92, 242, 234, 0.75));
}
.pill.is-tiny .appview-eye {
  display: grid;
  place-items: center;
  width: 12px;
  height: 12px;
  color: var(--cyan);
  filter:
    drop-shadow(0 0 1px rgba(92, 242, 234, 1))
    drop-shadow(0 0 4px rgba(92, 242, 234, 0.75));
}
.appview-eye svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* ===========================================================
   TINY-MODE LOGO — "ADHUSH" hump (LOCKED variant)
   ===========================================================
   Renders only when .pill carries .is-tiny. A 10px-tall notch
   anchored to the pill's top edge via `bottom: 100%` and then
   translated DOWN 5px so half the hump sits above the pill and
   half overlaps inside it. The bottom border is removed so the
   hump visually merges with the pill perimeter. Background is
   the same chroma-key halftone as .pill__backing so see-through
   behavior stays consistent.

   Locked 2026-05-25 after the watermark alternative was retired.
   The hump renders just above the pill via bottom:100%; the pill is
   flex-centered in the 600×240 Tauri host, so there is ~100px of clear
   headroom above it ((240-40)/2) and the 10px hump never clips.
   Increasing the hump height stays safe as long as it fits that headroom.
   =========================================================== */
.pill-logo-hump {
  display: none;
}

/* Retired 2026-06-01: in tiny mode the .brand-wrap now renders the hump
   (lock · ADHUSH · link together). This standalone text-only hump stays
   display:none in every mode. Kept in the DOM + here for quick revert. */

/* ===========================================================
   TOOLTIPS — appear above buttons on hover (350ms delay)
   =========================================================== */
[data-tip] { position: relative; }

[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  background: rgba(15, 17, 25, 0.95);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  color: rgba(255, 255, 255, 0.96);
  font-family: var(--font-mono);
  font-size: 9.5px;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 6px 10px;
  border-radius: 5px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.55);
  white-space: normal;
  width: max-content;
  max-width: 180px;
  text-align: center;
  line-height: 1.45;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
  z-index: 100;
}

[data-tip]::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 4px);
  left: 50%;
  transform: translateX(-50%);
  border: 5px solid transparent;
  border-top-color: rgba(15, 17, 25, 0.95);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.15s ease;
  z-index: 100;
}

[data-tip]:hover::after {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
  transition-delay: 0.35s;
}
[data-tip]:hover::before {
  opacity: 1;
  visibility: visible;
  transition-delay: 0.35s;
}
