@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');

/* ============================================================================
   Homepage-style dashboard theme. Slate, minimal, compact rows, masonry groups.
   Light/dark via CSS variables keyed off [data-bs-theme].
   ============================================================================ */
:root,
[data-bs-theme="dark"] {
  --hp-bg:        #1c2030;
  --hp-bg-2:      #232838;
  --hp-card:      rgba(255, 255, 255, 0.035);
  --hp-card-hover:rgba(255, 255, 255, 0.08);
  --hp-border:    rgba(255, 255, 255, 0.07);
  --hp-text:      #e7eaf0;
  --hp-muted:     #8b93a7;
  --hp-heading:   #cbd5e1;
  --hp-accent:    #5b8def;
  --hp-icon-bg:   rgba(255, 255, 255, 0.05);
}
[data-bs-theme="light"] {
  --hp-bg:        #eef1f6;
  --hp-bg-2:      #ffffff;
  --hp-card:      #ffffff;
  --hp-card-hover:#f3f5fa;
  --hp-border:    rgba(15, 23, 42, 0.10);
  --hp-text:      #1f2733;
  --hp-muted:     #64748b;
  --hp-heading:   #334155;
  --hp-accent:    #2563eb;
  --hp-icon-bg:   rgba(15, 23, 42, 0.04);
}

body {
  background-color: var(--hp-bg) !important;
  color: var(--hp-text);
  -webkit-user-select: none;
  user-select: none;
  padding-bottom: 2.25rem;
}
.hp-page-footer {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 1020;
  background: var(--hp-bg);
  border-top-color: var(--hp-border) !important;
}
/* …but keep inputs, the YAML editor, and explicitly-copyable text selectable */
input, textarea, select, [contenteditable], .CodeMirror, .CodeMirror *, .user-select-all {
  -webkit-user-select: text;
  user-select: text;
}

/* Navbar adopts the theme bg */
.navbar.bg-dark { background-color: var(--hp-bg-2) !important; }

/* PWA standalone: fill behind the macOS transparent title bar. */
@media (display-mode: standalone) {
  html { background-color: var(--hp-bg-2); }
}

/* Applied only when the inline <head> script detects a transparent macOS
   title bar (outerHeight ≈ innerHeight, meaning the viewport extends INTO
   the title-bar zone — iMac built-in display behaviour).
   On external monitors the viewport starts BELOW the title bar, so
   outerHeight − innerHeight ≈ 28 px and the class is never set.
   !important on padding-top overrides the higher-specificity collapsed rule
   (html.hdr-collapsed #appHeader) so collapsed controls also clear the zone. */
@media (display-mode: standalone) {
  html.pwa-transparent-titlebar #appHeader { padding-top: 30px !important; }
}

/* ---- brand logos + collapsible header ------------------------------------ */
/* Transparent theme-aware logos (no border). logo-dark = light wordmark for the
   dark theme; logo-light = dark wordmark for the light theme. */
.app-logo { height: 46px; transition: height .15s ease; }
.app-logo-light { display: none; }                              /* dark theme (default) */
[data-bs-theme="light"] .app-logo-dark { display: none; }
[data-bs-theme="light"] .app-logo-light { display: inline-block; }
.login-logo { max-height: 240px; width: auto; max-width: 100%; }
.app-logo-sq { height: 34px; display: none; }   /* rocket — shown only when collapsed */
#appHeader { position: sticky; top: 0; z-index: 1030; transition: padding .15s ease; }
#headerToggle i { transition: transform .15s ease; }
html.hdr-collapsed #navActions { display: none !important; }
html.hdr-collapsed .app-logo { display: none; }
html.hdr-collapsed .app-logo-sq { display: inline-block; }
html.hdr-collapsed #appHeader { padding-top: .1rem; padding-bottom: .1rem; }
html.hdr-collapsed #headerToggle i { transform: rotate(180deg); }

/* Top bar relocated into the collapsed header */
.header-widgets { display: none; }
.header-widgets.active { display: flex; flex: 1 1 auto; min-width: 0; align-items: center; }
.header-widgets.active .hp-topbar { padding: 0; margin: 0; width: 100%; gap: 1rem 1.5rem; }
.header-widgets.active .hp-search input { width: 180px; }
#widgetsInHeaderToggle.active { color: var(--hp-accent); border-color: var(--hp-accent); }

/* No divider line while the header is collapsed */
html.hdr-collapsed .hp-divider { display: none; }

/* Controls that should remain reachable when the header is collapsed */
.collapsed-only { display: none; }
html.hdr-collapsed .collapsed-only { display: inline-flex; }

/* ---- Top bar: widgets + clock + search ---------------------------------- */
.hp-topbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5rem 2rem;
  padding: .25rem 0 1rem;
}
.hp-widgets { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem 1.75rem; flex: 1 1 auto; }
.hp-topbar-right { display: flex; align-items: center; gap: 1.25rem; margin-left: auto; }

.hp-stat { display: flex; align-items: center; gap: .5rem; }
.hp-stat .hp-stat-icon { color: var(--hp-muted); font-size: 1.05rem; width: 1.2rem; text-align: center; flex: 0 0 auto; }
/* Fixed-width value so live updates (4% → 100%, 13 GiB → 9 GiB) never reflow the
   row. Tabular numerals keep digit columns aligned. min-width is in em so it
   scales with text_size. */
.hp-stat .hp-stat-val  {
  font-weight: 600; font-size: .9rem; white-space: nowrap;
  display: inline-block; min-width: 4.75em; text-align: left;
  font-variant-numeric: tabular-nums;
}
.hp-stat .hp-stat-label{ color: var(--hp-muted); font-size: .8rem; white-space: nowrap; flex: 0 0 auto; }
.hp-stat .hp-bar { width: 54px; height: 3px; border-radius: 2px; background: var(--hp-border); overflow: hidden; }
.hp-stat .hp-bar > span { display: block; height: 100%; background: var(--hp-accent); width: 0; transition: width .4s ease; }
/* Email widget: no progress bar; accent colour when there are unread messages */
.hp-stat[data-stat="email"] .hp-bar { display: none; }
.hp-stat--alert .hp-stat-val { color: var(--hp-accent); }

/* ---- Widget-bar item borders (settings.widget_bar default) ----------------
   Enabled per-side via wb-on + wb-top/right/bottom/left classes on .hp-topbar.
   Colour and radius come from the --wb-color / --wb-radius custom properties.
   Per-item overrides in the widgets YAML are applied as inline styles (app.js),
   which win over these rules. */
.hp-topbar.wb-on .hp-stat,
.hp-topbar.wb-on .hp-clock,
.hp-topbar.wb-on .hp-search input {
  border-style: solid;
  border-width: 0;
  border-color: var(--wb-color, var(--hp-border));
  border-radius: var(--wb-radius, .5rem);
}
/* content-box so a configured `width` stays the *content* width — padding and
   border extend outward instead of eating into it and clipping the label. */
.hp-topbar.wb-on .hp-stat,
.hp-topbar.wb-on .hp-clock { padding: .28rem .7rem; box-sizing: content-box; }
.hp-topbar.wb-on.wb-top    .hp-stat, .hp-topbar.wb-on.wb-top    .hp-clock, .hp-topbar.wb-on.wb-top    .hp-search input { border-top-width: 1px; }
.hp-topbar.wb-on.wb-right  .hp-stat, .hp-topbar.wb-on.wb-right  .hp-clock, .hp-topbar.wb-on.wb-right  .hp-search input { border-right-width: 1px; }
.hp-topbar.wb-on.wb-bottom .hp-stat, .hp-topbar.wb-on.wb-bottom .hp-clock, .hp-topbar.wb-on.wb-bottom .hp-search input { border-bottom-width: 1px; }
.hp-topbar.wb-on.wb-left   .hp-stat, .hp-topbar.wb-on.wb-left   .hp-clock, .hp-topbar.wb-on.wb-left   .hp-search input { border-left-width: 1px; }

/* Email dropdown (multi-account breakdown) */
.hp-email-wrapper { position: relative; }
.hp-stat.hp-email-has-dropdown { cursor: pointer; }
.hp-email-dropdown {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; z-index: 200;
  min-width: 200px; background: var(--hp-bg-2); border: 1px solid var(--hp-border);
  border-radius: .5rem; padding: .3rem 0;
  box-shadow: 0 4px 20px rgba(0,0,0,.35);
}
.hp-email-dropdown.open { display: block; }
.hp-email-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: .3rem .8rem; font-size: .82rem; color: var(--hp-text);
  text-decoration: none; gap: 1.5rem; white-space: nowrap;
}
a.hp-email-row:hover { background: var(--hp-card-hover); color: var(--hp-text); }
.hp-email-row-label { color: var(--hp-muted); }
.hp-email-row--unread .hp-email-row-label { color: var(--hp-text); font-weight: 500; }
.hp-email-row-count { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 2ch; text-align: right; }
.hp-email-row--unread .hp-email-row-count { color: var(--hp-accent); }

.hp-clock { color: var(--hp-text); font-size: 1.05rem; white-space: nowrap; }

.hp-search { position: relative; }
.hp-search input {
  background: var(--hp-card); border: 1px solid var(--hp-border); color: var(--hp-text);
  border-radius: .5rem; padding: .25rem 2.3rem .25rem .7rem; font-size: .875rem; line-height: 1.5;
  width: 260px; max-width: 50vw;
}
/* Hide the browser's native search clear (×) — our magnifier is the web-search
   trigger; the native control overlapped it and looked broken. */
.hp-search input::-webkit-search-cancel-button,
.hp-search input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
.hp-search input:focus { outline: none; border-color: var(--hp-accent); box-shadow: 0 0 0 .15rem rgba(91,141,239,.2); }
.hp-search .hp-search-go {
  position: absolute; right: 4px; top: 4px; bottom: 4px; width: 30px; border: 0; border-radius: .35rem;
  background: var(--hp-icon-bg); color: var(--hp-muted);
  display: flex; align-items: center; justify-content: center; padding: 0;
}
.hp-search .hp-search-go .hp-provider-icon { width: 17px; height: 17px; object-fit: contain; }
/* When the box has text, the provider button "lights up" and a hint appears so
   it's clear Enter / the button will do a web search (not just filter). */
.hp-search .hp-search-go { transition: box-shadow .12s ease, background .12s ease; }
.hp-search.has-text .hp-search-go { background: var(--hp-accent); box-shadow: 0 0 0 2px var(--hp-accent); }
.hp-search-hint {
  display: none; position: absolute; top: calc(100% + 5px); right: 0; z-index: 5;
  white-space: nowrap; font-size: .72rem; color: var(--hp-muted);
  background: var(--hp-card); border: 1px solid var(--hp-border);
  border-radius: .35rem; padding: .15rem .45rem;
}
.hp-search.has-text .hp-search-hint { display: inline-block; }
.hp-search-hint kbd {
  background: var(--hp-icon-bg); color: var(--hp-text); border-radius: .25rem;
  padding: 0 .3rem; font-size: .8em;
}

.hp-divider { border-color: var(--hp-border); opacity: 1; margin: 0 0 1.5rem; }

/* ---- Main section font (settings.yaml) ----------------------------------- */
/* Base family inherits to the whole section; 'section' overrides group titles,
   'items' overrides service cards, each independently. */
.hp-main { font-family: inherit; }
.hp-main .hp-group-title { font-family: var(--sec-ff, inherit); font-size: var(--sec-fs, 1.1rem); font-weight: var(--sec-fw, 500); }
.hp-main .hp-card-name { font-family: var(--item-ff, inherit); font-size: var(--item-fs, .92rem); font-weight: var(--item-fw, 600); }

/* ---- Group layout -------------------------------------------------------- */
/* Default + 'columns' = masonry (down a column, then across). 'rows' = a grid
   that flows across, then down to the next row. --cols sets the column count. */
.hp-groups { columns: 340px; column-gap: 1.75rem; }
.hp-groups.layout-columns { columns: var(--cols, 4); column-gap: 1.75rem; }
.hp-groups.layout-rows {
  columns: auto;
  display: grid;
  grid-auto-flow: row;
  grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr));
  gap: 1.75rem;
  align-items: start;
}
.hp-groups.layout-rows .hp-group { display: block; width: auto; margin-bottom: 0; }
.hp-group { break-inside: avoid; margin: 0 0 1.75rem; display: inline-block; width: 100%; }
.hp-group-title {
  font-size: 1.1rem; font-weight: 500; color: var(--hp-heading);
  margin: 0 0 .6rem; padding: 0; letter-spacing: .01em;
  display: flex; align-items: center; gap: .5rem;
}
.hp-group-title.group-toggle { cursor: pointer; user-select: none; }
.hp-group-title.group-toggle:hover { color: var(--hp-text); }
.group-chevron { font-size: .8rem; color: var(--hp-muted); transition: transform .15s ease; }
.hp-group.collapsed .group-chevron { transform: rotate(-90deg); }
.hp-group.collapsed .hp-group-items { display: none; }
/* Service card drag-and-drop */
.service-card-col[data-movable] { cursor: grab; }
.service-card-col[data-movable]:active { cursor: grabbing; }
.hp-svc-dragging { opacity: 0.35; }
.hp-svc-placeholder { height: 3px; background: var(--hp-accent); border-radius: 2px; margin: .1rem 0; flex-shrink: 0; }
.hp-svc-drop-zone { outline: 1px dashed var(--hp-accent); outline-offset: 4px; border-radius: .3rem; }
/* Weather/todo summaries shown in title only when section is collapsed */
.hp-weather-title-summary { display: none; margin-left: auto; font-size: .88rem; font-weight: 400; color: var(--hp-muted); }
.hp-group.collapsed .hp-weather-title-summary:not(:empty) { display: block; }
.hp-todo-title-summary {
  display: none; font-size: .72rem; font-weight: 500;
  color: var(--hp-accent); background: color-mix(in srgb, var(--hp-accent) 15%, transparent);
  padding: .1rem .5rem; border-radius: 1rem;
}
.hp-group.collapsed .hp-todo-title-summary:not(:empty) { display: inline-block; }
/* Calendar summary shown in title when collapsed; nav hidden when collapsed */
.hp-cal-title-summary {
  display: none; font-size: .72rem; font-weight: 500;
  color: var(--hp-accent); background: color-mix(in srgb, var(--hp-accent) 15%, transparent);
  padding: .1rem .5rem; border-radius: 1rem;
}
.hp-group.collapsed .hp-cal-title-summary:not(:empty) { display: inline-block; }
.hp-group.collapsed .hp-cal-title-nav,
.hp-group.collapsed .hp-cal-month-label { display: none !important; }

/* Item count badge — shown on service groups when collapsed */
.hp-group-count-badge {
  display: none; font-size: .72rem; font-weight: 500;
  color: var(--hp-muted); background: color-mix(in srgb, var(--hp-muted) 12%, transparent);
  padding: .1rem .5rem; border-radius: 1rem;
}
.hp-group.collapsed .hp-group-count-badge { display: inline-block; }
.hp-group-items { display: flex; flex-direction: column; gap: .5rem; }

/* Scroll-limited service groups — JS sets max-height; this just wires overflow */
.hp-group-scroll-outer { position: relative; }
.hp-group-items-limited { overflow-y: auto; }
/* Gradient fade at the bottom when more items are below the fold */
.hp-group-scroll-fade {
  position: absolute; bottom: 0; left: 0; right: 0; height: 52px;
  background: linear-gradient(to bottom, transparent, var(--hp-card) 85%);
  pointer-events: none; opacity: 0; transition: opacity .2s;
}
.hp-group-scroll-outer.hp-group-has-more .hp-group-scroll-fade { opacity: 1; }
.hp-group.collapsed .hp-group-scroll-fade { display: none; }

/* ---- Service card (compact row, whole card is the link) ------------------ */
.hp-card {
  display: flex; align-items: center; gap: .75rem;
  padding: .6rem .85rem; border-radius: .6rem;
  background: var(--hp-card); border: 1px solid transparent;
  text-decoration: none; color: var(--hp-text);
  transition: background .12s ease, border-color .12s ease;
}
.hp-card:hover { background: var(--hp-card-hover); border-color: var(--hp-border); color: var(--hp-text); }
.hp-icon {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: .45rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--hp-icon-bg); font-size: 1.2rem; overflow: visible;
  position: relative;
}
.hp-monitor-dot {
  position: absolute; bottom: -2px; right: -2px;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--hp-muted);
  border: 2px solid var(--hp-card);
  transition: background .4s;
  z-index: 1;
}
.hp-monitor-dot.up   { background: #4ade80; }
.hp-monitor-dot.down { background: #f87171; }
.hp-icon img { width: 26px; height: 26px; object-fit: contain; }
.hp-icon .fa-solid, .hp-icon .fa-brands { color: var(--hp-muted); font-size: 1rem; }
.hp-card-text { min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.hp-card-name { font-weight: 600; font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-card-desc { color: var(--hp-muted); font-size: .8rem; overflow: hidden; text-overflow: ellipsis; }
.hp-shared-dot { color: var(--hp-accent); font-size: .6rem; margin-left: .35rem; vertical-align: middle; }

/* ---- Bookmarks ----------------------------------------------------------- */
.hp-bookmarks { margin-top: .5rem; columns: 340px; column-gap: 1.75rem; }
.hp-bm {
  display: flex; align-items: center; gap: .75rem; padding: .5rem .75rem;
  border-radius: .55rem; background: var(--hp-card); text-decoration: none; color: var(--hp-text);
  transition: background .12s ease;
}
.hp-bm:hover { background: var(--hp-card-hover); color: var(--hp-text); }
.hp-bm-abbr {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: .4rem; background: var(--hp-icon-bg);
  display: flex; align-items: center; justify-content: center; font-size: .72rem; font-weight: 700;
  color: var(--hp-muted); letter-spacing: .02em;
}
.hp-bm-name { font-weight: 500; font-size: .9rem; }
.hp-bm-host { margin-left: auto; color: var(--hp-muted); font-size: .8rem; }

/* ---- misc ---------------------------------------------------------------- */
/* Auto-dismissing flash message: slide up + fade out */
.js-flash {
  overflow: hidden; max-height: 240px;
  transition: opacity .4s ease, transform .4s ease, max-height .4s ease,
              margin .4s ease, padding .4s ease;
}
.js-flash.flash-hiding {
  opacity: 0; transform: translateY(-12px);
  max-height: 0 !important; margin-top: 0 !important; margin-bottom: 0 !important;
  padding-top: 0 !important; padding-bottom: 0 !important;
}

.hp-empty { color: var(--hp-muted); text-align: center; padding: 3rem 0; }
.tag-badge { background: var(--hp-icon-bg); color: var(--hp-muted); font-weight: 400; font-size: .7rem; }
.letter-spacing-1 { letter-spacing: .06em; }
.min-w-0 { min-width: 0; }
.theme-toggle { background: transparent; border: 1px solid var(--hp-border); color: var(--hp-muted); border-radius: .4rem; }
.theme-toggle:hover { color: var(--hp-text); }

/* ============================================================================
   Responsive / mobile
   ============================================================================ */

/* Tablets & phones: groups stack into a single column regardless of the layout
   setting (a 4-column grid is unusable on a narrow screen). */
@media (max-width: 768px) {
  .hp-groups,
  .hp-groups.layout-columns,
  .hp-groups.layout-rows {
    columns: auto;
    display: block;
    grid-template-columns: none;
  }
  .hp-bookmarks { columns: auto; }
  .hp-group,
  .hp-groups.layout-rows .hp-group { width: 100%; margin: 0 0 1.5rem; display: block; }
}

/* Phones */
@media (max-width: 576px) {
  body { font-size: 15px; }
  main.flex-grow-1 { padding-top: 1rem !important; padding-bottom: 1rem !important; }
  .container-fluid.px-4 { padding-left: .85rem !important; padding-right: .85rem !important; }

  /* Header: wrap, smaller logo, icon-only action buttons */
  #appHeader .container-fluid { flex-wrap: wrap; gap: .4rem; }
  .app-logo { height: 34px; }
  .navbar-brand .app-name { font-size: .95rem; }
  #navActions { gap: .35rem !important; flex-wrap: wrap; }
  #navActions .btn-label { display: none; }            /* show just icons */
  #navActions .btn-sm,
  #headerToggle,
  .collapsed-only .btn-sm { padding: .35rem .55rem; }
  #navActions .btn .fa-solid { margin: 0; }

  /* Top bar: stack, full-width search, let stats wrap */
  .hp-topbar { flex-direction: column; align-items: stretch; gap: .75rem; }
  .hp-topbar-right { margin-left: 0; width: 100%; flex-wrap: wrap; gap: .5rem; }
  .hp-search { flex: 1 1 100%; }
  /* !important so a configured search `width:` (applied inline by app.js for
     desktop) can't keep the box narrow on a phone where it should fill the row. */
  .hp-search input { width: 100% !important; max-width: none !important; }
  .hp-widgets { gap: .55rem 1.1rem; }
  .hp-clock { font-size: .95rem; width: 100%; }

  /* When the top bar is relocated into a collapsed header, let it wrap too */
  .header-widgets.active .hp-topbar { flex-direction: column; align-items: stretch; }
  .header-widgets.active .hp-search input { width: 100% !important; }

  /* Cards a touch tighter; bookmarks host can ellipsize */
  .hp-card { padding: .55rem .7rem; }
  .hp-group-title { font-size: 1.05rem; }
  .hp-bm-host { max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Login logo smaller */
  .login-logo { max-height: 150px; }

  /* Config editor: shorter on phones */
  .CodeMirror { min-height: 50vh; }
}

/* ---- icon style toggle (monochrome mode) ---------------------------------- */
html.icon-mono .hp-icon-img { filter: grayscale(1) opacity(.75); }
html[data-bs-theme="dark"].icon-mono .hp-icon-img { filter: grayscale(1) brightness(1.2) opacity(.8); }
html.icon-mono .hp-weather-emoji,
html.icon-mono .hp-weather-day-emoji { filter: grayscale(1) opacity(.8); }

/* ---- weather widget -------------------------------------------------------- */
.hp-weather-loading { color: var(--hp-muted); font-size: .8rem; padding: .75rem 0; }
.hp-weather { padding: .25rem 0 .5rem; display: flex; flex-direction: column; height: 100%; }
.hp-weather-location { font-size: .72rem; color: var(--hp-muted); margin-bottom: .6rem; letter-spacing: .02em; }
.hp-weather-main { display: flex; align-items: baseline; gap: .5rem; line-height: 1; }
.hp-weather-emoji { font-size: 2.4rem; line-height: 1; }
.hp-weather-temp { font-size: 2.8rem; font-weight: 300; color: var(--hp-text); }
.hp-weather-desc { font-size: .8rem; color: var(--hp-muted); margin-top: .35rem; }
.hp-weather-meta { font-size: .72rem; color: var(--hp-muted); margin-top: .2rem; }
.hp-weather-forecast { display: flex; gap: .25rem; margin-top: 1rem; }
.hp-weather-day {
  display: flex; flex-direction: column; align-items: center;
  gap: .15rem; flex: 1; min-width: 2.5rem;
  padding: .4rem .25rem; border-radius: .4rem;
  background: var(--hp-card); border: 1px solid var(--hp-border);
}
.hp-weather-day-name { font-size: .65rem; color: var(--hp-muted); text-transform: uppercase; letter-spacing: .04em; }
.hp-weather-day-emoji { font-size: 1.15rem; }
.hp-weather-day-high { font-size: .75rem; color: var(--hp-text); font-weight: 500; }
.hp-weather-day-low { font-size: .7rem; color: var(--hp-muted); }
.hp-weather-day-precip { font-size: .65rem; color: #60a5fa; }

/* multi-location compact row */
.hp-weather-multi { display: flex; flex-wrap: wrap; gap: .65rem; padding: .25rem 0 .5rem; }
.hp-weather-compact {
  display: flex; flex-direction: column; gap: .65rem;
  flex: 1; min-width: 200px;
  padding: .75rem 1rem;
  background: var(--hp-bg-2);
  border: 1px solid var(--hp-border);
  border-radius: .5rem;
}
.hp-weather-compact-top { display: flex; align-items: center; gap: .65rem; }
.hp-weather-compact-emoji { font-size: 2rem; line-height: 1; flex-shrink: 0; }
.hp-weather-compact-info { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.hp-weather-compact-temp { font-size: 1.25rem; font-weight: 500; color: var(--hp-text); line-height: 1; }
.hp-weather-compact-range { font-size: .72rem; color: var(--hp-muted); margin-left: .4rem; font-weight: 400; }
.hp-weather-compact-name { font-size: .78rem; color: var(--hp-text); font-weight: 500; margin-top: .15rem; }
.hp-weather-compact-desc { font-size: .72rem; color: var(--hp-muted); }
.hp-weather-compact-err  { font-size: .75rem; color: var(--hp-muted); }
.hp-weather-footer { font-size: .6rem; color: var(--hp-muted); opacity: .7; margin-top: auto; padding-top: .35rem; }
.hp-weather-footer.hp-weather-stale { color: #f59e0b; opacity: 1; }
.hp-weather-compact-forecast { display: flex; gap: .2rem; }
.hp-weather-compact-day {
  display: flex; flex-direction: column; align-items: center;
  gap: .12rem; flex: 1; min-width: 2rem;
  padding: .3rem .2rem; border-radius: .35rem;
  background: var(--hp-card); border: 1px solid var(--hp-border);
}
.hp-weather-compact-day-name  { font-size: .6rem; color: var(--hp-muted); text-transform: uppercase; letter-spacing: .04em; }
.hp-weather-compact-day-emoji { font-size: 1rem; }
.hp-weather-compact-day-high  { font-size: .7rem; color: var(--hp-text); font-weight: 500; }
.hp-weather-compact-day-low   { font-size: .65rem; color: var(--hp-muted); }
html.icon-mono .hp-weather-compact-emoji,
html.icon-mono .hp-weather-compact-day-emoji { filter: grayscale(1) opacity(.8); }

/* ---- calendar body widget --------------------------------------------------
   Agenda-style card. Adapts to dark/light via CSS variables.              */
.hp-cal-loading { color: var(--hp-muted); font-size: .8rem; padding: .75rem 0; }

/* Scroll-indicator wrapper for calendar days */
.hp-cal-scroll-outer { position: relative; }
.hp-cal-fade {
  position: absolute; top: 0; bottom: 0; width: 40px;
  pointer-events: none; z-index: 2;
  opacity: 0; transition: opacity .22s;
}
.hp-cal-fade-left  { left:  0; background: linear-gradient(to right, var(--hp-card) 20%, transparent); }
.hp-cal-fade-right { right: 0; background: linear-gradient(to left,  var(--hp-card) 20%, transparent); }
.hp-cal-scroll-outer.hp-cal-has-left  .hp-cal-fade-left  { opacity: 1; }
.hp-cal-scroll-outer.hp-cal-has-right .hp-cal-fade-right { opacity: 1; }

/* Calendar title-bar nav buttons */
.hp-cal-title-nav {
  margin-left: auto; display: flex; gap: .15rem; align-items: center;
}
.hp-cal-nav-btn {
  background: none; border: none; padding: .1rem .28rem;
  border-radius: .25rem; cursor: pointer; color: var(--hp-muted);
  font-size: .75rem; line-height: 1;
  transition: color .12s, background .12s;
}
.hp-cal-nav-btn:hover { background: rgba(255,255,255,.07); color: var(--hp-text); }
/* Today button: outlined pill style */
.hp-cal-nav-today {
  border: 1px solid var(--hp-border) !important;
  padding: .08rem .4rem !important;
  font-size: .7rem !important; font-weight: 500;
}
/* Dim when already at today / current month */
.hp-cal-nav-today.hp-cal-nav-today-current { opacity: .4; cursor: default; }
.hp-cal-nav-today.hp-cal-nav-today-current:hover { background: none !important; color: var(--hp-muted) !important; }
/* Current-month label shown in month view */
.hp-cal-month-label {
  font-size: .75rem; font-weight: 500; color: var(--hp-muted);
  margin-left: .5rem; white-space: nowrap;
}

/* Horizontal day columns */
.hp-cal-days {
  display: flex; gap: .85rem; align-items: flex-start;
  overflow-x: auto; padding-bottom: .15rem;
}
.hp-cal-day-col { flex: 1 1 150px; min-width: 130px; }

.hp-cal-day-empty {
  display: flex; align-items: center; justify-content: center;
  padding: 1.8rem 0; color: var(--hp-border); font-size: 1.4rem;
}

.hp-cal-day-header {
  font-size: .68rem; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--hp-muted); margin: 0 0 .3rem;
  padding-bottom: .25rem; border-bottom: 1px solid var(--hp-border);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hp-cal-day-header.hp-cal-day-today { color: var(--hp-accent); border-bottom-color: var(--hp-accent); }

.hp-cal-event {
  display: flex; align-items: flex-start; gap: .55rem;
  padding: .32rem .2rem; border-radius: .3rem;
  transition: background .1s ease;
}
.hp-cal-event:hover { background: var(--hp-card-hover); }

.hp-cal-dot {
  flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  margin-top: .28rem;
}

.hp-cal-event-body {
  display: flex; flex-direction: column; gap: .1rem; min-width: 0;
}

.hp-cal-time {
  font-size: .7rem; color: var(--hp-muted); white-space: nowrap; flex-shrink: 0;
}

.hp-cal-title {
  font-size: .88rem; font-weight: 500; color: var(--hp-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.hp-cal-location {
  font-size: .72rem; color: var(--hp-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.hp-cal-badge {
  display: inline-block; font-size: .65rem; color: var(--hp-muted);
  border: 1px solid; border-radius: .25rem;
  padding: 0 .3rem; line-height: 1.5; align-self: flex-start; margin-top: .05rem;
}

.hp-cal-empty {
  color: var(--hp-muted); font-size: .82rem; padding: .75rem 0;
}

.hp-cal-error {
  color: var(--hp-muted); font-size: .8rem; padding: .5rem 0;
}

.hp-cal-warnings { margin-bottom: .35rem; }
.hp-cal-warning-line { font-size: .72rem; color: #f59e0b; margin: 0 0 .15rem; }

/* Month calendar grid */
.hp-cal-month-grid {
  display: grid; grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.hp-cal-month-dow {
  font-size: .62rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--hp-muted);
  text-align: center; padding: .25rem 0 .3rem;
}
.hp-cal-month-cell {
  min-height: 62px; padding: .25rem .3rem;
  border-radius: .2rem; background: rgba(255,255,255,.025);
  overflow: hidden; font-size: .67rem;
}
.hp-cal-month-other { opacity: .35; }
.hp-cal-month-today {
  background: rgba(91,141,239,.12);
  outline: 1px solid var(--hp-accent);
}
.hp-cal-month-day-num {
  display: block; font-size: .7rem; color: var(--hp-muted);
  margin-bottom: .18rem; line-height: 1;
}
.hp-cal-month-today .hp-cal-month-day-num { color: var(--hp-accent); font-weight: 700; }
.hp-cal-month-ev {
  display: flex; align-items: center; gap: .22rem;
  line-height: 1.35; margin-bottom: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--hp-text);
}
.hp-cal-month-ev-dot {
  flex: 0 0 5px; width: 5px; height: 5px; border-radius: 50%;
}
.hp-cal-month-more { font-size: .6rem; color: var(--hp-muted); margin-top: 1px; }

/* Column-span helper — only has visible effect in layout-rows (CSS Grid) mode.
   On narrow screens the grid collapses to single-column so the span is moot. */
@media (min-width: 769px) {
  .hp-groups.layout-rows .hp-group[style*="grid-column"] {
    min-width: 0; /* prevent grid blowout */
  }
}

/* ---- todo body widget ------------------------------------------------------ */
.hp-todo-loading {
  color: var(--hp-muted); font-size: .8rem; padding: .75rem 0;
}
.hp-todo-empty {
  color: var(--hp-muted); font-size: .82rem; padding: .75rem 0;
}
.hp-todo-error {
  color: var(--hp-muted); font-size: .8rem; padding: .5rem 0;
}

/* [+] button in the widget title bar */
.hp-todo-title-add {
  margin-left: auto; flex-shrink: 0;
  background: none; border: none;
  color: var(--hp-muted); font-size: .78rem;
  padding: .1rem .35rem; border-radius: .25rem;
  cursor: pointer; line-height: 1;
  transition: color .12s, background .12s;
}
.hp-todo-title-add:hover { color: var(--hp-accent); background: rgba(255,255,255,.06); }

/* Add task — collapsible form */
.hp-todo-add-wrap { margin-bottom: 0; }
.hp-todo-add { display: flex; flex-direction: column; gap: .35rem; padding-bottom: .6rem; }
.hp-todo-add-hidden { display: none; }

/* Row 1: title input */
.hp-todo-add-row1 { display: flex; }
.hp-todo-add-input {
  flex: 1; min-width: 0;
  background: var(--hp-bg); color: var(--hp-text);
  border: 1px solid var(--hp-border); border-radius: .3rem;
  padding: .28rem .5rem; font-size: .85rem;
}
.hp-todo-add-input:focus {
  outline: none; border-color: var(--hp-accent);
  box-shadow: 0 0 0 .15rem rgba(91,141,239,.2);
}

/* Row 2: date + time */
.hp-todo-add-row2 { display: flex; gap: .4rem; align-items: center; }
.hp-todo-add-date {
  width: 140px;
  background: var(--hp-bg); color: var(--hp-text);
  border: 1px solid var(--hp-border); border-radius: .3rem;
  padding: .25rem .4rem; font-size: .82rem;
}
.hp-todo-add-date:focus { outline: none; border-color: var(--hp-accent); }

/* Row 3: recurrence */
.hp-todo-add-row3 { display: flex; gap: .4rem; align-items: center; }

/* Row 4: action buttons */
.hp-todo-add-row4 { display: flex; gap: .4rem; align-items: center; }
.hp-todo-add-btn {
  background: var(--hp-accent); color: #fff;
  border: 0; border-radius: .3rem;
  padding: .26rem .55rem; font-size: .82rem;
  cursor: pointer;
}
.hp-todo-add-btn:hover { opacity: .88; }
.hp-todo-add-cancel {
  background: none; color: var(--hp-muted);
  border: 1px solid var(--hp-border); border-radius: .3rem;
  padding: .26rem .5rem; font-size: .82rem;
  cursor: pointer;
}
.hp-todo-add-cancel:hover { color: var(--hp-text); border-color: var(--hp-muted); }

/* Group section header */
.hp-todo-group-hdr {
  font-size: .68rem; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--hp-muted);
  padding-bottom: .2rem; margin-top: .75rem;
  border-bottom: 1px solid var(--hp-border);
}
/* Collapse the title's bottom margin so tasks start flush under the heading */
.hp-todo-section .hp-group-title { margin-bottom: 0; }
/* First group header follows the (hidden) add-wrap — no extra top gap */
.hp-todo-add-wrap + .hp-todo-group-hdr { margin-top: 0; }
.hp-todo-group-hdr.overdue  { color: #ef4444; border-color: #ef4444; }
.hp-todo-group-hdr.today    { color: var(--hp-accent); border-color: var(--hp-accent); }
.hp-todo-group-hdr.upcoming { color: var(--hp-muted); }

/* Task row */
.hp-todo-task {
  display: flex; align-items: center; gap: .4rem;
  padding: .28rem .2rem; border-radius: .3rem;
}
.hp-todo-task:hover { background: var(--hp-card-hover); }

.hp-todo-drag-handle {
  cursor: grab; color: var(--hp-muted); opacity: 0;
  font-size: .85rem; flex: 0 0 auto; line-height: 1;
  -webkit-user-select: none; user-select: none;
}
.hp-todo-task:hover .hp-todo-drag-handle { opacity: .6; }

.hp-todo-cb {
  flex: 0 0 auto; cursor: pointer; accent-color: var(--hp-accent);
  width: 15px; height: 15px;
}

.hp-todo-task-title {
  flex: 1; font-size: .88rem; color: var(--hp-text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  cursor: pointer; min-width: 0;
  -webkit-user-select: text; user-select: text;
}
.hp-todo-task.completed .hp-todo-task-title {
  text-decoration: line-through; color: var(--hp-muted);
}

.hp-todo-task-edit {
  flex: 1; font-size: .88rem; min-width: 0;
  background: var(--hp-bg); color: var(--hp-text);
  border: 1px solid var(--hp-accent); border-radius: .25rem;
  padding: .1rem .35rem;
}
.hp-todo-task-edit:focus { outline: none; }

/* Due date badge */
.hp-todo-due-badge {
  font-size: .68rem; padding: 1px 5px;
  border-radius: 3px; white-space: nowrap;
  cursor: pointer; flex: 0 0 auto;
  background: var(--hp-border); color: var(--hp-muted);
}
.hp-todo-due-badge.overdue  { background: #ef4444; color: #fff; }
.hp-todo-due-badge.today    { background: var(--hp-accent); color: #fff; }
.hp-todo-due-badge.upcoming { background: var(--hp-border); color: var(--hp-muted); }
.hp-todo-due-badge.muted    { color: var(--hp-muted); opacity: .6; }

/* Inline date input (hidden unless editing due date) */
.hp-todo-date-inp {
  width: 120px; font-size: .8rem;
  background: var(--hp-bg); color: var(--hp-text);
  border: 1px solid var(--hp-accent); border-radius: .25rem;
  padding: .1rem .3rem;
}
.hp-todo-date-inp:focus { outline: none; }

/* Delete button */
.hp-todo-del-btn {
  opacity: 0; background: transparent; border: 0;
  color: var(--hp-muted); font-size: .82rem;
  cursor: pointer; padding: .1rem .25rem; border-radius: .2rem;
  flex: 0 0 auto; line-height: 1;
}
.hp-todo-task:hover .hp-todo-del-btn { opacity: .7; }
.hp-todo-del-btn:hover { opacity: 1 !important; color: #ef4444; }

/* Drag-and-drop visual cues */
.hp-todo-dragging { opacity: .4; }
.hp-todo-drag-over { border-top: 2px solid var(--hp-accent); }

/* Warnings */
.hp-todo-warnings { margin-top: .5rem; }
.hp-todo-warning-line { font-size: .72rem; color: #f59e0b; margin: 0 0 .15rem; }

/* Inline date + time picker wrapper */
.hp-todo-dt-wrap { display: inline-flex; gap: .25rem; align-items: center; }
.hp-todo-time-inp {
  width: 110px; font-size: .8rem;
  background: var(--hp-bg); color: var(--hp-text);
  border: 1px solid var(--hp-accent); border-radius: .25rem;
  padding: .1rem .3rem; color-scheme: dark;
}
.hp-todo-time-inp:focus { outline: none; }

/* Add-form time input */
.hp-todo-add-time {
  width: 110px; font-size: .78rem;
  background: var(--hp-card); color: var(--hp-text);
  border: 1px solid var(--hp-border); border-radius: .25rem;
  padding: .25rem .4rem; color-scheme: dark;
}
.hp-todo-add-time:focus { outline: none; border-color: var(--hp-accent); }

/* Also fix the add-form date picker */
.hp-todo-add-date { color-scheme: dark; }

/* Utility: generic hidden toggle */
.hp-hidden { display: none !important; }

/* Recurrence badge on task rows */
.hp-todo-recur-badge {
  font-size: .72rem; padding: .05rem .35rem;
  border-radius: .9rem; cursor: pointer;
  background: rgba(255,255,255,.07); color: var(--hp-muted);
  border: 1px solid var(--hp-border); flex: 0 0 auto; line-height: 1.4;
  white-space: nowrap;
  transition: background .12s, color .12s;
}
.hp-todo-recur-badge:hover { background: rgba(255,255,255,.13); color: var(--hp-text); }

/* Inline recurrence editor on task rows */
.hp-todo-recur-wrap {
  display: inline-flex; align-items: center; gap: .25rem; flex: 0 0 auto;
}
.hp-todo-recur-sel, .hp-todo-recur-unit-sel {
  font-size: .78rem;
  background: var(--hp-card); color: var(--hp-text);
  border: 1px solid var(--hp-accent); border-radius: .25rem;
  padding: .1rem .25rem; cursor: pointer;
}
.hp-todo-recur-n {
  width: 52px; font-size: .78rem;
  background: var(--hp-card); color: var(--hp-text);
  border: 1px solid var(--hp-accent); border-radius: .25rem;
  padding: .1rem .25rem;
}
.hp-todo-recur-custom-wrap { display: inline-flex; align-items: center; gap: .2rem; }
.hp-todo-recur-save, .hp-todo-recur-cancel {
  background: none; border: none; cursor: pointer; padding: .1rem .25rem;
  border-radius: .2rem; font-size: .78rem; line-height: 1;
}
.hp-todo-recur-save  { color: var(--hp-accent); }
.hp-todo-recur-cancel { color: var(--hp-muted); }
.hp-todo-recur-save:hover  { color: #fff; }
.hp-todo-recur-cancel:hover { color: var(--hp-text); }

/* Add-form recurrence select */
.hp-todo-add-recur, .hp-todo-add-recur-unit {
  font-size: .78rem;
  background: var(--hp-card); color: var(--hp-text);
  border: 1px solid var(--hp-border); border-radius: .25rem;
  padding: .25rem .4rem; cursor: pointer;
}
.hp-todo-add-recur:focus, .hp-todo-add-recur-unit:focus { outline: none; border-color: var(--hp-accent); }
.hp-todo-add-recur-custom { display: inline-flex; align-items: center; gap: .25rem; }
.hp-todo-add-recur-n {
  width: 52px; font-size: .78rem;
  background: var(--hp-card); color: var(--hp-text);
  border: 1px solid var(--hp-border); border-radius: .25rem;
  padding: .25rem .3rem;
}
.hp-todo-add-recur-n:focus { outline: none; border-color: var(--hp-accent); }

/* ---- Webhook buttons ----------------------------------------------------- */
.hp-webhook-grid { display: flex; flex-wrap: wrap; gap: .5rem; }
.hp-webhook-btn {
  display: flex; align-items: center; gap: .75rem;
  padding: .6rem .85rem; border-radius: .6rem;
  background: var(--hp-card); border: 1px solid transparent;
  color: var(--hp-text); cursor: pointer; text-align: left;
  transition: background .12s, border-color .12s, transform .08s;
  min-width: 130px;
}
.hp-webhook-btn:hover  { background: var(--hp-card-hover); border-color: var(--hp-border); }
.hp-webhook-btn:active { transform: scale(.97); }
.hp-webhook-btn:disabled { opacity: .6; cursor: not-allowed; transform: none; }
.hp-webhook-btn-icon {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: .45rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--hp-icon-bg); font-size: 1.1rem;
  color: var(--hp-muted);
  transition: color .2s;
}
.hp-webhook-btn.wh-active { border-color: var(--hp-accent); }
.hp-webhook-btn.wh-active .hp-webhook-btn-icon { color: var(--wh-color, var(--hp-accent)); }
.hp-webhook-btn.wh-ok  .hp-webhook-btn-icon { color: #4ade80; }
.hp-webhook-btn.wh-err .hp-webhook-btn-icon { color: #f87171; }
.hp-webhook-btn-text { min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.hp-webhook-btn-name { font-weight: 600; font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-webhook-btn-desc { color: var(--hp-muted); font-size: .8rem; overflow: hidden; text-overflow: ellipsis; }

/* Webhook info button in group title */
.hp-webhook-info-btn {
  background: none; border: none; padding: .1rem .3rem; margin-left: auto;
  border-radius: .25rem; cursor: pointer; color: var(--hp-muted); font-size: .78rem;
  transition: color .12s, background .12s;
}
.hp-webhook-info-btn:hover { color: var(--hp-accent); background: rgba(255,255,255,.06); }

/* Webhook callback URL modal */
.hp-wh-modal { background: var(--hp-card); border: 1px solid var(--hp-border); color: var(--hp-text); }
.hp-wh-modal-header { border-bottom-color: var(--hp-border); }
.hp-wh-modal-footer { border-top-color: var(--hp-border); }
.hp-wh-info-item { margin-bottom: 1.25rem; }
.hp-wh-info-item:last-of-type { margin-bottom: 0; }
.hp-wh-info-name { font-weight: 600; margin-bottom: .4rem; }
.hp-wh-info-row { display: flex; align-items: center; gap: .5rem; margin-bottom: .3rem; flex-wrap: wrap; }
.hp-wh-info-lbl { flex: 0 0 4.5rem; font-size: .8rem; color: var(--hp-muted); }
.hp-wh-info-url { flex: 1; font-size: .75rem; background: var(--hp-bg); border: 1px solid var(--hp-border); border-radius: .3rem; padding: .25rem .4rem; word-break: break-all; color: var(--hp-text); }
.hp-wh-copy-btn {
  flex: 0 0 auto; padding: .2rem .55rem; border-radius: .3rem; font-size: .75rem;
  background: none; border: 1px solid var(--hp-border); color: var(--hp-muted); cursor: pointer;
  transition: color .12s, border-color .12s;
}
.hp-wh-copy-btn:hover { color: var(--hp-accent); border-color: var(--hp-accent); }
.hp-wh-info-note { font-size: .82rem; color: var(--hp-muted); }

/* ---- RSS feed widget ------------------------------------------------------- */
.hp-rss-scroll-outer { position: relative; }
.hp-rss-list { max-height: 420px; overflow-y: auto; display: flex; flex-direction: column; }
.hp-rss-list::-webkit-scrollbar { width: 4px; }
.hp-rss-list::-webkit-scrollbar-track { background: transparent; }
.hp-rss-list::-webkit-scrollbar-thumb { background: var(--hp-border); border-radius: 2px; }
.hp-rss-scroll-fade {
  position: absolute; bottom: 0; left: 0; right: 0; height: 2.5rem; pointer-events: none;
  background: linear-gradient(to bottom, transparent, var(--hp-bg-2));
}
.hp-rss-load-more {
  display: block; width: 100%; padding: .5rem; background: none;
  border: none; border-top: 1px solid var(--hp-border);
  color: var(--hp-accent); font-size: .8rem; text-align: center; cursor: pointer;
  margin-top: .1rem;
}
.hp-rss-load-more:hover { background: var(--hp-bg-2); }
.hp-rss-item {
  display: flex; align-items: flex-start; gap: .6rem;
  padding: .45rem 0; border-bottom: 1px solid var(--hp-border);
  min-width: 0;
}
.hp-rss-item:last-child { border-bottom: none; }
.hp-rss-item-left { flex: 1; min-width: 0; }
.hp-rss-item-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--hp-text);
  text-decoration: none;
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.35;
}
.hp-rss-item-title:hover { color: var(--hp-accent); }
.hp-rss-item-meta { display: flex; align-items: center; gap: .35rem; margin-top: .25rem; flex-wrap: wrap; }
.hp-rss-item-favicon {
  width: 14px; height: 14px; border-radius: 2px; object-fit: contain;
  flex-shrink: 0; opacity: .85;
}
.hp-rss-item-source {
  font-size: .73rem; color: var(--hp-accent); font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 130px;
}
.hp-rss-item-time { font-size: .73rem; color: var(--hp-muted); white-space: nowrap; }
.hp-rss-item-thumb {
  flex-shrink: 0; width: 80px; height: 54px;
  object-fit: cover; border-radius: .25rem;
  background: var(--hp-border);
}
.hp-rss-loading, .hp-rss-empty { color: var(--hp-muted); font-size: .875rem; padding: .4rem 0; }
.hp-rss-error { color: #f87171; font-size: .875rem; padding: .4rem 0; }
.hp-rss-warnings { margin-bottom: .4rem; }
.hp-rss-warning { font-size: .78rem; color: #fbbf24; margin: 0 0 .15rem; }

/* ---- RSS reader modal ------------------------------------------------------ */
.hp-rss-reader-dialog { max-width: min(860px, 96vw); }
.hp-rss-reader-modal { background: var(--hp-bg); border: 1px solid var(--hp-border); color: var(--hp-text); }
.hp-rss-reader-header {
  background: var(--hp-bg-2); border-bottom: 1px solid var(--hp-border);
  align-items: flex-start; gap: .75rem; padding: 1rem 1.25rem;
}
.hp-rss-reader-header-inner { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .2rem; }
.hp-rss-reader-source { font-size: .75rem; color: var(--hp-accent); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.hp-rss-reader-title { font-size: 1.15rem; font-weight: 700; line-height: 1.3; margin: 0; color: var(--hp-text); }
.hp-rss-reader-byline { font-size: .8rem; color: var(--hp-muted); }
.hp-rss-reader-body { padding: 1.5rem 1.25rem; background: var(--hp-bg); }
.hp-rss-reader-loading { color: var(--hp-muted); padding: 2rem 0; text-align: center; }
.hp-rss-reader-footer { background: var(--hp-bg-2); border-top: 1px solid var(--hp-border); }
.hp-rss-reader-excerpt { color: var(--hp-text); font-size: .95rem; line-height: 1.65; }
.hp-rss-reader-excerpt-note { color: var(--hp-muted); font-size: .8rem; }

/* Article typography */
.hp-rss-reader-content {
  font-size: .975rem;
  line-height: 1.75;
  color: var(--hp-text);
  max-width: 68ch;
  margin: 0 auto;
}
.hp-rss-reader-content p   { margin: 0 0 1rem; }
.hp-rss-reader-content h1,
.hp-rss-reader-content h2  { font-size: 1.2rem; font-weight: 700; margin: 1.5rem 0 .6rem; color: var(--hp-heading); }
.hp-rss-reader-content h3,
.hp-rss-reader-content h4  { font-size: 1rem;   font-weight: 600; margin: 1.25rem 0 .5rem; }
.hp-rss-reader-content img { max-width: 100%; height: auto; border-radius: .35rem; margin: .75rem 0; display: block; }
.hp-rss-reader-content figure { margin: 1rem 0; }
.hp-rss-reader-content figcaption { font-size: .8rem; color: var(--hp-muted); margin-top: .3rem; }
.hp-rss-reader-content blockquote {
  border-left: 3px solid var(--hp-accent); margin: 1rem 0; padding: .5rem 1rem;
  color: var(--hp-muted); font-style: italic;
}
.hp-rss-reader-content pre  { background: var(--hp-bg-2); border-radius: .35rem; padding: .75rem 1rem; overflow-x: auto; font-size: .85rem; }
.hp-rss-reader-content code { font-size: .85em; background: var(--hp-bg-2); padding: .1em .3em; border-radius: .2rem; }
.hp-rss-reader-content pre code { background: none; padding: 0; }
.hp-rss-reader-content a    { color: var(--hp-accent); }
.hp-rss-reader-content ul,
.hp-rss-reader-content ol   { padding-left: 1.5rem; margin: 0 0 1rem; }
.hp-rss-reader-content hr   { border-color: var(--hp-border); margin: 1.5rem 0; }
.hp-rss-reader-content table { width: 100%; border-collapse: collapse; font-size: .9rem; margin: 1rem 0; }
.hp-rss-reader-content th,
.hp-rss-reader-content td   { border: 1px solid var(--hp-border); padding: .4rem .6rem; text-align: left; }

/* ---- World Clocks widget (analog grid) ----------------------------------- */
.hp-clocks-widget {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: .85rem .75rem;
  padding: .25rem 0;
  justify-items: center;
}
.hp-clock-item { display: flex; flex-direction: column; align-items: center; gap: .3rem; width: 100%; max-width: 130px; }
.hp-clock-svg  { width: 100%; height: auto; overflow: visible; }
/* Single clock: fill and centre (class added by JS) */
.hp-clocks-single {
  display: flex !important;
  justify-content: center;
  align-items: center;
}
.hp-clocks-single .hp-clock-item { width: 100%; max-width: 260px; }
.hp-clock-face { fill: var(--hp-bg-2); stroke: var(--hp-border); stroke-width: 1.5; }
.hp-clock-tick-major { stroke: var(--hp-text); stroke-width: 2.2; stroke-linecap: round; }
.hp-clock-tick-minor { stroke: var(--hp-muted); stroke-width: 1; stroke-linecap: round; opacity: .45; }
.hp-clock-hand-hour { stroke: var(--hp-text);   stroke-width: 4;   stroke-linecap: round; }
.hp-clock-hand-min  { stroke: var(--hp-text);   stroke-width: 2.5; stroke-linecap: round; }
.hp-clock-hand-sec  { stroke: var(--hp-accent); stroke-width: 1.5; stroke-linecap: round; }
.hp-clock-center    { fill: var(--hp-text); }
.hp-clock-label { font-size: .73rem; color: var(--hp-muted); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }

/* Digital clock mode */
.hp-clocks-digital { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
.hp-clock-item-digital { max-width: 200px; gap: .2rem; }
.hp-clock-digital-display {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .15rem;
  padding: .4rem .2rem .2rem;
}
.hp-clock-digital-hm {
  font-family: 'Orbitron', 'Courier New', monospace;
  font-weight: 700;
  font-size: 1.55rem;
  letter-spacing: .04em;
  color: var(--hp-text);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.hp-clock-digital-bottom {
  display: flex;
  align-items: baseline;
  gap: .3rem;
}
.hp-clock-digital-s {
  font-family: 'Orbitron', 'Courier New', monospace;
  font-weight: 400;
  font-size: .75rem;
  color: var(--hp-muted);
  font-variant-numeric: tabular-nums;
  letter-spacing: .03em;
}
.hp-clock-digital-period {
  font-family: 'Orbitron', 'Courier New', monospace;
  font-weight: 400;
  font-size: .6rem;
  color: var(--hp-accent);
  letter-spacing: .08em;
}
.hp-clock-day {
  font-size: .62rem;
  font-weight: 700;
  letter-spacing: .05em;
  text-transform: uppercase;
  text-align: center;
  min-height: .8rem;
  line-height: 1;
}
.hp-clock-day-future { color: var(--hp-accent); }
.hp-clock-day-past   { color: var(--hp-muted); opacity: .7; }

/* ---- QR Code widget ------------------------------------------------------ */
.hp-qr-widget { display: flex; flex-direction: column; gap: .65rem; padding: .15rem 0; }
.hp-qr-input {
  background: var(--hp-bg-2) !important; border: 1px solid var(--hp-border) !important;
  color: var(--hp-text) !important; border-radius: .35rem !important;
}
.hp-qr-input:focus { border-color: var(--hp-accent) !important; box-shadow: none !important; }
.hp-qr-display { display: flex; justify-content: center; }
.hp-qr-img { max-width: min(220px, 100%); border-radius: .35rem; background: #fff; padding: 4px; }

/* ---- Uptime Monitor widget ----------------------------------------------- */
.hp-monitor-widget { padding: .1rem 0; }
.hp-monitor-loading { color: var(--hp-muted); font-size: .85rem; padding: .5rem 0; }
.hp-monitor-error   { color: var(--hp-muted); font-size: .85rem; padding: .4rem 0; }
.hp-monitor-item {
  display: flex; align-items: center; gap: .65rem;
  padding: .42rem 0; border-bottom: 1px solid var(--hp-border);
}
.hp-monitor-item:last-child { border-bottom: none; }
.hp-monitor-dot {
  width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0;
  box-shadow: 0 0 0 2px transparent;
}
.hp-monitor-dot-up    { background: #22c55e; box-shadow: 0 0 0 3px rgba(34,197,94,.18); }
.hp-monitor-dot-down  { background: #ef4444; box-shadow: 0 0 0 3px rgba(239,68,68,.18); }
.hp-monitor-dot-check { background: var(--hp-muted); opacity: .5; }
.hp-monitor-info { flex: 1; min-width: 0; }
.hp-monitor-name   { font-size: .875rem; color: var(--hp-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-monitor-uptime { font-size: .72rem; color: var(--hp-muted); margin-top: .05rem; }
.hp-monitor-down-label { color: #ef4444 !important; }
.hp-monitor-meta { text-align: right; flex-shrink: 0; }
.hp-monitor-ms   { font-size: .8rem; color: var(--hp-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.hp-monitor-code { font-size: .7rem; color: var(--hp-muted); margin-top: .05rem; }

/* Bell icon in title bar */
.hp-todo-title-bell {
  background: none; border: none; padding: .1rem .3rem;
  border-radius: .25rem; cursor: pointer; line-height: 1;
  color: var(--hp-muted); font-size: .78rem;
  transition: color .12s, background .12s;
}
.hp-todo-title-bell:hover              { background: rgba(255,255,255,.06); }
.hp-todo-title-bell.hp-todo-bell-on    { color: var(--hp-accent); }
.hp-todo-title-bell.hp-todo-bell-denied { color: #ef4444; opacity: .7; cursor: default; }

/* ── Focus Timer Widget ──────────────────────────────────────────────────── */
.hp-focus-widget {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: .75rem;
  padding: .5rem 0 .25rem;
}
.hp-focus-mode-label {
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--hp-accent);
  transition: color .3s;
}
.hp-focus-mode-label.hp-focus-mode-break { color: #22c55e; }
.hp-focus-ring-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hp-focus-svg { width: 160px; height: 160px; }
.hp-focus-ring-bg   { stroke: var(--hp-border); }
.hp-focus-ring-prog { transition: stroke-dashoffset .1s linear, stroke .3s; }
.hp-focus-time {
  position: absolute;
  font-size: 2.1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--hp-text);
  letter-spacing: -.02em;
  line-height: 1;
}
.hp-focus-controls { display: flex; gap: .5rem; align-items: center; }
.hp-focus-btn {
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  padding: .35rem 1.1rem;
  border: 1px solid var(--hp-border);
  border-radius: 2rem;
  background: var(--hp-bg-2);
  color: var(--hp-text);
  font-size: .8125rem;
  cursor: pointer;
  transition: border-color .15s, background .15s;
}
.hp-focus-btn:hover { border-color: var(--hp-accent); background: var(--hp-card); }
.hp-focus-btn-start { min-width: 92px; justify-content: center; }
.hp-focus-btn-reset { color: var(--hp-muted); padding: .35rem .7rem; }
.hp-focus-btn-reset:hover { color: var(--hp-text); }
.hp-focus-dots { display: flex; gap: .4rem; }
.hp-focus-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--hp-border);
  transition: background .3s, box-shadow .3s;
}
.hp-focus-dot.done    { background: var(--hp-accent); box-shadow: 0 0 0 2px rgba(var(--hp-accent-rgb, 124,58,237),.2); }
.hp-focus-dot.current { background: var(--hp-accent); opacity: .4; }

/* ---- File Share widget --------------------------------------------------- */
.hp-fileshare-widget { display: flex; flex-direction: column; gap: .6rem; padding: .25rem 0 .5rem; }

.hp-fs-zone {
  border: 1.5px dashed var(--hp-border);
  border-radius: .5rem;
  padding: 1.1rem .75rem;
  text-align: center;
  cursor: pointer;
  transition: border-color .15s, background .15s;
  display: flex; flex-direction: column; align-items: center; gap: .4rem;
}
.hp-fs-zone:hover, .hp-fs-zone.hp-fs-zone-over { border-color: var(--hp-accent); background: rgba(99,102,241,.06); }
.hp-fs-zone.hp-fs-zone-ready { border-color: var(--hp-accent); border-style: solid; }
.hp-fs-zone-icon { font-size: 1.4rem; color: var(--hp-muted); }
.hp-fs-zone-text { font-size: .8rem; color: var(--hp-muted); }

.hp-fs-recip-row { display: flex; flex-direction: column; gap: .25rem; }
.hp-fs-recip-label { font-size: .75rem; color: var(--hp-muted); }
.hp-fs-recip-select { font-size: .8rem; background: var(--hp-bg-2); color: var(--hp-text); border-color: var(--hp-border); min-height: 62px; }

.hp-fs-upload-btn { align-self: flex-end; }

.hp-fs-status { font-size: .78rem; min-height: 1.2em; }
.hp-fs-status-busy { color: var(--hp-muted); }
.hp-fs-status-ok   { color: #22c55e; }
.hp-fs-status-err  { color: #f87171; }

.hp-fs-list { display: flex; flex-direction: column; gap: .3rem; margin-top: .1rem; }
.hp-fs-empty { font-size: .8rem; color: var(--hp-muted); text-align: center; padding: .5rem 0; }

.hp-fs-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: .5rem;
  padding: .4rem .5rem;
  border-radius: .375rem;
  background: var(--hp-bg-2);
  border: 1px solid var(--hp-border);
  font-size: .8rem;
}
.hp-fs-row-received { border-left: 3px solid var(--hp-accent); }

.hp-fs-info { display: flex; flex-direction: column; gap: .1rem; min-width: 0; flex: 1; }
.hp-fs-name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-fs-meta { font-size: .7rem; color: var(--hp-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.hp-fs-actions { display: flex; gap: .3rem; flex-shrink: 0; }
.hp-fs-dl-btn, .hp-fs-del-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border-radius: .3rem;
  border: 1px solid var(--hp-border);
  background: transparent;
  color: var(--hp-muted);
  font-size: .8rem;
  cursor: pointer;
  text-decoration: none;
  transition: color .15s, border-color .15s, background .15s;
}
.hp-fs-dl-btn:hover  { color: var(--hp-accent); border-color: var(--hp-accent); }
.hp-fs-del-btn:hover { color: #f87171; border-color: #f87171; }

.hp-fs-tabs { display: flex; gap: .3rem; }
.hp-fs-tab {
  flex: 1; padding: .2rem .4rem; font-size: .78rem;
  background: transparent; border: 1px solid var(--hp-border);
  border-radius: .25rem; color: var(--hp-muted); cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.hp-fs-tab.hp-fs-tab-active { background: var(--hp-accent); border-color: var(--hp-accent); color: #fff; }
.hp-fs-textarea { resize: vertical; min-height: 80px; font-size: .8rem; font-family: inherit; }
.hp-fs-snippet-preview {
  width: 100%; flex: 0 0 100%;
  margin-top: .4rem;
  padding: .4rem .6rem;
  background: var(--hp-bg);
  border: 1px solid var(--hp-border);
  border-radius: .25rem;
  font-size: .78rem;
  font-family: inherit;
  color: var(--hp-text);
  white-space: pre-wrap;
  word-break: break-word;
  -webkit-user-select: text;
  user-select: text;
  max-height: 12rem;
  overflow-y: auto;
  line-height: 1.5;
}

/* ---- File share: reply button + thread modal ----------------------------- */
.hp-fs-reply-btn { position: relative; }
.hp-fs-reply-count {
  position: absolute; top: -5px; right: -5px;
  min-width: 15px; height: 15px; padding: 0 3px;
  font-size: .6rem; line-height: 15px; font-weight: 700;
  background: var(--hp-accent); color: #fff;
  border-radius: 8px; text-align: center;
}

/* Thread = a chat-style transcript: received messages left, your own right. */
.hp-fs-thread { display: flex; flex-direction: column; gap: .55rem; }
.hp-fs-thread-loading { text-align: center; color: var(--hp-muted); padding: 1rem 0; }
.hp-fs-msg { display: flex; flex-direction: column; gap: .15rem; max-width: 82%; }
.hp-fs-msg-other { align-self: flex-start; align-items: flex-start; }
.hp-fs-msg-own   { align-self: flex-end;   align-items: flex-end; }
.hp-fs-msg-meta { font-size: .68rem; color: var(--hp-muted); padding: 0 .3rem; }
.hp-fs-msg-bubble {
  padding: .45rem .7rem;
  border-radius: .8rem;
  font-size: .82rem; line-height: 1.45;
  white-space: pre-wrap; word-break: break-word;
  background: var(--hp-bg-2); border: 1px solid var(--hp-border); color: var(--hp-text);
}
.hp-fs-msg-other .hp-fs-msg-bubble { border-bottom-left-radius: .2rem; }
.hp-fs-msg-own   .hp-fs-msg-bubble {
  border-bottom-right-radius: .2rem;
  background: var(--hp-accent); border-color: var(--hp-accent); color: #fff;
}
.hp-fs-msg-bubble.hp-fs-msg-root { border-style: dashed; }
.hp-fs-msg-own .hp-fs-msg-bubble.hp-fs-msg-root { background: color-mix(in srgb, var(--hp-accent) 78%, #000); }
.hp-fs-msg-file { color: inherit; text-decoration: none; font-weight: 500; }
.hp-fs-msg-file:hover { text-decoration: underline; }

/* Composer under the thread */
.hp-fs-thread-composer { flex-direction: column; align-items: stretch; gap: .5rem; }
.hp-fs-reply-bar { display: flex; align-items: center; gap: .5rem; }
.hp-fs-reply-filelabel { font-size: .75rem; color: var(--hp-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }

/* =========================================================================
   Vendor UI theming — bind liveselect + customConfirmAlert to the app palette.
   Both libraries are CSS-variable themeable. liveselect has no auto-dark and
   customConfirmAlert only auto-darks via OS prefers-color-scheme, so neither
   follows the app's manual data-bs-theme toggle on its own. These overrides map
   their tokens onto the --hp-* variables (which already switch with the theme),
   and use a higher specificity than the libraries' defaults so they win
   regardless of stylesheet load order.
   ========================================================================= */

/* liveselect — searchable combobox (drop-in <select> replacement) */
[data-bs-theme] .liveselect {
  --liveselect-font:         inherit;
  --liveselect-text:         var(--hp-text);
  --liveselect-text-muted:   var(--hp-muted);
  --liveselect-bg:           var(--hp-bg-2);
  --liveselect-surface:      var(--hp-bg-2);
  --liveselect-hover:        var(--hp-card-hover);
  --liveselect-border:       var(--hp-border);
  --liveselect-border-focus: var(--hp-accent);
  --liveselect-accent:       var(--hp-accent);
  --liveselect-radius:       .5rem;
  --liveselect-radius-sm:    .35rem;
}
/* Toolbar pickers (kind/scope) sit in tight rows — keep them compact + auto-width */
.hp-editor-toolbar .liveselect,
.hp-config-toolbar .liveselect { display: inline-flex; min-width: 160px; }

/* customConfirmAlert — dialogs + toasts. data-cd-theme (synced in head.ejs)
   flips the built-in palette; these refine the surface to the app's colours. */
:root[data-bs-theme="dark"],
:root[data-bs-theme="light"] {
  --custom-dialog-background:   var(--hp-bg-2);
  --custom-dialog-text:         var(--hp-text);
  --custom-dialog-muted-text:   var(--hp-muted);
  --custom-dialog-border:       var(--hp-border);
  --custom-dialog-input-bg:     var(--hp-bg);
  --custom-dialog-input-border: var(--hp-border);
}
