
/** stylesheets/src/variables.css **/
/* ============================================================
   AZIMUTH — Ocean Theme (night) — CANONICAL TOKEN FILE
   Dark blues palette + gold accents
   ------------------------------------------------------------
   This `:root` block is the single authority for the theme token
   catalog. It is parsed at backend startup (ThemeTokenCatalog) and
   by ThemeTokenCoverageSpec. The category markers below drive both:

     @theme:color      — themeable color tokens. A custom theme file
                         is "complete" when it overrides every one.
     @theme:structural — radius/shadow tokens. Allowed in custom
                         theme files, validated by their own value
                         grammar, never counted toward completeness.
     @theme:none       — layout/behavior tokens. Forbidden in custom
                         theme files.

   A marker applies to every declaration after it until the next
   marker. Do not add declarations above the first marker.
   ============================================================ */

/* ── CSS Variables ──────────────────────────────────────────── */
:root {
  /* @theme:color */
  --color-ocean-deepest: #050d1a;
  --color-ocean-deep: #0a1628;
  --color-ocean-mid: #0f2240;
  --color-ocean-surface: #163358;
  --color-ocean-light: #1e4a7a;
  --color-ocean-mist: #2a6099;

  --color-gold: #c9a84c;
  --color-gold-light: #e2c46a;
  --color-gold-dark: #9e7d33;
  --color-gold-subtle: rgba(201, 168, 76, 0.15);

  --color-text-primary: #e8edf5;
  --color-text-secondary: #8fa8c8;
  --color-text-muted: #4e6a8a;
  /* Tertiary deliberately aliases secondary so every UI reference to
     tertiary text renders with the secondary tone. */
  --color-text-tertiary: var(--color-text-secondary);

  --color-border: rgba(255, 255, 255, 0.08);
  --color-border-gold: rgba(201, 168, 76, 0.3);

  --color-danger: #c0392b;
  --color-danger-light: rgba(192, 57, 43, 0.15);

  --color-warning: #f39c12;
  --color-warning-light: rgba(243, 156, 18, 0.15);
  --color-warning-text: #f7c373;

  --color-success: #1a8a5a;
  --color-success-light: rgba(26, 138, 90, 0.15);

  --color-info: #5fa9d3;
  --color-info-soft: rgba(95, 169, 211, 0.18);
  --color-accent: rgba(110, 152, 239, 0.8);
  --color-accent-primary: #409eff;
  --color-ocean-accent: var(--color-info);

  /* Generic surface family: the elevation ladder used by the home
     dashboard widgets and settings rows. */
  --color-surface: rgba(255, 255, 255, 0.04);
  --surface-base: #14181f;
  --surface-elevated: #1f2630;
  --surface-elevated-strong: #2a323f;
  --surface-elevated-stronger: rgba(255, 255, 255, 0.12);
  --surface-border: rgba(255, 255, 255, 0.08);
  --surface-border-subtle: rgba(255, 255, 255, 0.04);

  /* Ring painted behind user-avatar chips so overlapping stacks stay
     separable; deliberately bright in both themes. */
  --color-avatar-ring: #ffffff;

  /* Ship's Log category accent tokens. One source of truth for every
     color used inside an event card / pill / tile. */
  --events-color-navigation: #4aa3ff;
  --events-color-fuel: var(--color-gold-light);
  --events-color-water: #48c7d9;
  --events-color-engine: #7dd3a0;
  --events-color-maintenance: #65c08a;
  --events-color-weather: #9bb3e8;
  --events-color-wildlife: #5fd2a3;
  --events-color-guests: #d59be6;
  --events-color-safety: #ff8a5c;
  --events-color-mooring: #5cc6ff;
  --events-color-provisioning: #e8b56a;
  --events-color-general: #8fa8c8;
  --events-color-checklist: #a6d4ff;

  /* @theme:structural */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;

  --shadow-card: 0 2px 16px rgba(0, 0, 0, 0.4);
  --shadow-modal: 0 8px 48px rgba(0, 0, 0, 0.7);

  /* @theme:none */
  --transition: 180ms ease;

  --font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;

  /* ── Responsive convention ─────────────────────────────────────
     CSS media queries cannot read custom properties, so the breakpoint
     values are a documented convention rather than tokens. They MUST stay
     in lockstep with the JS constants in constants.js
     (PHONE_VIEWPORT_MAX_WIDTH_PIXELS / TABLET_VIEWPORT_MAX_WIDTH_PIXELS)
     and with docs/agents/azimuth/fe.md § "RESPONSIVE & MOBILE":
       phone:  @media (max-width: 640px)   — layout changes for phones
       tablet: @media (max-width: 1024px)  — sparse tablet-portrait tweaks
       touch:  @media (pointer: coarse)    — interaction affordances ONLY
     Width queries drive layout; pointer queries drive interaction. Never
     introduce a new breakpoint value. */

  /* Minimum hit area for touch (Apple HIG 44pt). Applied to compact icon
     buttons inside the coarse-pointer media queries. */
  --touch-target-minimum-size: 44px;
  /* Inputs below 16px trigger iOS Safari's automatic focus zoom, which
     ruins the layout. forms.css/navbar.css floor input font-size to this
     value on coarse-pointer phones. */
  --touch-input-font-size: 16px;

  /* Sticky top navbar height. --navbar-total-height adds the device cutout
     inset (viewport-fit=cover in index.scala.html) so the bar itself pads
     under a notch while content below keeps its 60px offset math. */
  --navbar-height: 60px;
  --navbar-total-height: calc(var(--navbar-height) + env(safe-area-inset-top, 0px));

  /* Left vertical nav rail. JS (home.js) reads --nav-rail-active-width to size
     the dashboard canvas, so the rail width lives here as the single source of
     truth shared between CSS and JS. --nav-rail-active-width is flipped to the
     collapsed width by the [data-nav-rail="collapsed"] selector below. */
  --nav-rail-width-expanded: 220px;
  --nav-rail-width-collapsed: 64px;
  --nav-rail-active-width: var(--nav-rail-width-expanded);
  /* Main-vessel thumbnail in the rail: full inner width when expanded, this
     fixed width when collapsed (must fit the 64px rail minus its padding).
     Height follows from the 4:3 aspect-ratio in tabs.css. */
  --nav-rail-vessel-image-width-collapsed: 48px;

  /* Custom branding background layer (base.css consumes these; branding.js and
     the index.scala.html FOUC script overwrite them as INLINE style properties
     on <html> when the resolved branding defines a background for the active
     mode). The defaults render nothing. NOT user-themeable: the values are
     managed exclusively by the branding applier. */
  --app-background-image-url: none;
  --app-background-overlay: transparent;
  --app-background-blur: 0px;
}

:root[data-nav-rail="collapsed"] {
  --nav-rail-active-width: var(--nav-rail-width-collapsed);
}

/** stylesheets/src/base.css **/
/* ── Reset & Base ───────────────────────────────────────────── */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html, body {
  height: 100%;
}

body {
  font-family: var(--font-family);
  font-size: 14px;
  line-height: 1.6;
  background-color: var(--color-ocean-deepest);
  color: var(--color-text-primary);
  /* dvh tracks the actual visible viewport as mobile browser chrome shows/hides;
     the vh line is the fallback for browsers without dynamic viewport units. */
  min-height: 100vh;
  min-height: 100dvh;
  background-image: radial-gradient(ellipse at 20% 0%, rgba(30, 74, 122, 0.4) 0%, transparent 60%),
  radial-gradient(ellipse at 80% 100%, rgba(10, 22, 40, 0.8) 0%, transparent 60%);
}

/* ── Custom branding background ─────────────────────────────────
   When the user/vessel branding defines a background image for the
   active mode, the theme applier (branding.js applyEffectiveBranding)
   sets `data-custom-background="true"` on <html> plus three inline
   custom properties:
     --app-background-image-url  url("...") of the hidden-asset image
     --app-background-overlay    composed rgba() overlay wash
     --app-background-blur       blur radius, e.g. `6px`
   The image + overlay paint on a fixed `body::before` layer (NOT the
   body background) so `filter: blur()` can soften the image without
   blurring app content. The negative inset over-extends the layer by
   twice the blur radius, hiding the translucent fringe a blur leaves
   at the layer's edges. The body override kills the built-in gradient;
   its second selector (theme + attribute) out-specifies day.css's
   `html[data-theme='day'] body` gradient, which loads after this file. */
html[data-custom-background='true'] body,
html[data-theme='day'][data-custom-background='true'] body {
  background-image: none;
}

html[data-custom-background='true'] body::before,
html[data-theme='day'][data-custom-background='true'] body::before {
  content: '';
  position: fixed;
  inset: calc(var(--app-background-blur) * -2);
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(var(--app-background-overlay), var(--app-background-overlay)),
    var(--app-background-image-url);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  filter: blur(var(--app-background-blur));
}

a {
  color: var(--color-gold-light);
  text-decoration: none;
}

a:hover {
  color: var(--color-gold);
  text-decoration: underline;
}

ul {
  list-style: none;
}

/* ── Sticky-chrome scroll clearance ─────────────────────────────
   The navbar is `position: sticky; top: 0` (navbar.css), so any programmatic
   scroll-into-view (keyboard focus, anchor jumps, Playwright clicks) can land
   its target UNDERNEATH the bar where it can't be seen or hit. scroll-margin
   has no layout effect; it only pads scrollIntoView calculations. */
button, a, input, select, textarea, tr, [tabindex] {
  scroll-margin-top: calc(var(--navbar-total-height) + 0.75rem);
}

/* ── Scrollbar ──────────────────────────────────────────────── */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  background: var(--color-ocean-deep);
}

::-webkit-scrollbar-thumb {
  background: var(--color-ocean-mist);
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: var(--color-gold-dark);
}


/** stylesheets/src/navbar.css **/
/* ── Navbar ─────────────────────────────────────────────────── */
.navbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Horizontal safe-area padding keeps the brand/avatar clear of curved
     display corners in landscape (viewport-fit=cover). The top inset grows
     the bar under a notch while the content region stays --navbar-height. */
  padding: env(safe-area-inset-top, 0px) calc(2rem + env(safe-area-inset-right, 0px)) 0 calc(2rem + env(safe-area-inset-left, 0px));
  height: var(--navbar-total-height);
  background: var(--color-ocean-deep);
  border-bottom: 1px solid var(--color-border-gold);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
  position: sticky;
  top: 0;
  z-index: 100;
}

.navbar-brand {
  font-size: 1.35rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-gold-light);
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.navbar-logo {
  height: 36px;
  width: auto;
  display: block;
  object-fit: contain;
}

.navbar-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* ── Navbar search ─────────────────────────────────────────────
   A passive placeholder input that lives to the left of the account
   menu. It does not submit anywhere yet; the field exists so the layout
   is final and a future search wiring is a pure JS change. */
.navbar-search {
  display: flex;
  align-items: center;
  position: relative;
}

/* Grouped results dropdown anchored under the search input. */
.navbar-search-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  width: 380px;
  max-width: 60vw;
  max-height: 70vh;
  overflow-y: auto;
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  z-index: 1000;
  padding: 0.35rem 0;
}

.navbar-search-loading,
.navbar-search-empty {
  padding: 0.6rem 0.9rem;
  color: var(--color-text-muted);
  font-size: 0.82rem;
}

.navbar-search-section-label {
  padding: 0.4rem 0.9rem 0.2rem;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
}

.navbar-search-result {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
  color: var(--color-text-primary);
}

.navbar-search-result:hover {
  background: var(--color-ocean-light);
}

.navbar-search-result-title {
  font-size: 0.86rem;
}

.navbar-search-result-snippet {
  font-size: 0.74rem;
  color: var(--color-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Instance-disambiguating suffix on a result title (e.g. a checklist run's start date). */
.navbar-search-result-detail {
  font-size: 0.74rem;
  font-weight: normal;
  color: var(--color-text-muted);
}

/* Matched-term highlight inside search snippets (emitted by the searchSnippet
   directive). Overrides the browser default black-on-yellow <mark> so it reads
   on the dark ocean theme. Shared by the navbar dropdown and the results page. */
mark.search-highlight {
  background-color: var(--color-gold-subtle);
  color: var(--color-gold-light);
  border-radius: 2px;
  padding: 0 1px;
}

.navbar-search-see-all {
  display: block;
  width: 100%;
  text-align: center;
  background: transparent;
  border: none;
  border-top: 1px solid var(--color-border-gold);
  margin-top: 0.3rem;
  padding: 0.55rem;
  cursor: pointer;
  color: var(--color-gold);
  font-size: 0.82rem;
}

.navbar-search-see-all:hover {
  background: var(--color-ocean-light);
}

/* ── Full search results page ─────────────────────────────────────────── */
.search-page-controls {
  display: flex;
  gap: 0.6rem;
  margin-bottom: 1.2rem;
}

.search-page-input {
  -webkit-appearance: none;
  appearance: none;
  flex: 1;
  height: 40px;
  padding: 0 0.95rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-gold);
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
  font-size: 0.9rem;
}

.search-page-input:focus {
  outline: none;
  border-color: var(--color-gold);
}

.search-result-section {
  margin-bottom: 1.4rem;
}

.search-result-section-title {
  font-size: 0.95rem;
  color: var(--color-gold);
  margin-bottom: 0.4rem;
}

.search-result-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.search-result-item {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-sm);
  margin-bottom: 0.4rem;
  cursor: pointer;
  background: var(--color-ocean-surface);
}

.search-result-item:hover {
  background: var(--color-ocean-light);
}

.search-result-title {
  font-size: 0.9rem;
  color: var(--color-text-primary);
}

.search-result-snippet {
  font-size: 0.78rem;
  color: var(--color-text-muted);
}

/* Instance-disambiguating suffix on a result title (e.g. a checklist run's start date). */
.search-result-detail {
  font-size: 0.78rem;
  font-weight: normal;
  color: var(--color-text-muted);
}

/* ── @mention autocomplete + chips ────────────────────────────────────── */
.mention-autocomplete-dropdown {
  position: absolute;
  z-index: 3000;
  max-height: 260px;
  overflow-y: auto;
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-sm);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}

.mention-autocomplete-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.4rem 0.7rem;
  cursor: pointer;
  color: var(--color-text-primary);
}

.mention-autocomplete-item-active,
.mention-autocomplete-item:hover {
  background: var(--color-ocean-light);
}

.mention-autocomplete-item-title {
  font-size: 0.85rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mention-autocomplete-item-type {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
  flex-shrink: 0;
}

.mention-chip {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  border-radius: var(--radius-sm);
  background: var(--color-ocean-light);
  border: 1px solid var(--color-border-gold);
  color: var(--color-gold);
  font-size: 0.85em;
  white-space: nowrap;
}

.navbar-search-input {
  /* Chromium gives `input[type="search"]` its own user-agent border-radius and an
     inner shadow via `-webkit-appearance: searchfield`. Drop the native styling so
     our pill shape and dark background actually take effect. */
  -webkit-appearance: none;
  appearance: none;
  width: 260px;
  max-width: 32vw;
  height: 38px;
  padding: 0 0.95rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border-gold);
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
  font-size: 0.85rem;
  line-height: 1;
  transition: border-color var(--transition), background var(--transition);
}

/* Hide the WebKit "x" clear button so the input keeps a clean look. */
.navbar-search-input::-webkit-search-cancel-button,
.navbar-search-input::-webkit-search-decoration {
  -webkit-appearance: none;
  appearance: none;
}

.navbar-search-input::placeholder {
  color: var(--color-text-muted);
}

.navbar-search-input:focus {
  outline: none;
  border-color: var(--color-gold);
  background: var(--color-ocean-light);
}

/* Both search toggles are desktop-hidden; the phone media block at the END of
   this file reveals them (it must be last so it wins the cascade — see the
   comment there). */
.navbar-search-expand-toggle,
.navbar-search-collapse-toggle {
  display: none;
}

.account-menu {
  position: relative;
}

/* The trigger is intentionally chromeless: it groups the avatar, the name+title text
   block, and the down-caret into a SINGLE click target without giving them any shared
   background or border. Visually each child reads as an independent navbar item; the
   button outline only appears on keyboard focus so it stays accessible. */
.account-menu-trigger {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0;
  margin: 0;
  background: transparent;
  border: none;
  color: var(--color-text-primary);
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
}

.account-menu-trigger:focus-visible {
  outline: 2px solid var(--color-gold);
  outline-offset: 4px;
  border-radius: var(--radius-sm);
}

.account-menu-avatar {
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  border: 1px solid var(--color-border-gold);
  background: var(--color-ocean-surface);
  color: var(--color-gold-light);
  overflow: hidden;
  position: relative;
  z-index: 1;
  transition: border-color var(--transition);
}

.account-menu-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The non-image fallback is the 👤 emoji rendered as text. Without an explicit
   font-size it inherits the trigger's 0.9rem and looks like a tiny dot floating
   in the circle. Bump it up and pin line-height to 1 so the glyph is centered
   on the circle's vertical midline and visually fills the avatar. */
.account-menu-avatar > span {
  font-size: 1.45rem;
  line-height: 1;
  color: var(--color-gold-light);
}

.account-menu-trigger-identity {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45rem;
  color: var(--color-text-primary);
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 28vw;
  line-height: 1;
}

.account-menu-trigger-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--color-text-primary);
}

.account-menu-trigger-title-separator {
  color: var(--color-text-muted);
  font-weight: 400;
  flex: 0 0 auto;
}

.account-menu-trigger-title {
  color: var(--color-gold-light);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.account-menu-trigger-caret {
  flex: 0 0 auto;
  font-size: 0.7rem;
  line-height: 1;
  color: var(--color-text-muted);
}

/* Status dot sits at the bottom-right of the avatar circle — NOT at the corner of
   the (now invisible) trigger button. Position is computed relative to the trigger
   (which has position: relative), using the avatar's 38px box as the anchor. */
.vessel-websocket-status-indicator {
  position: absolute;
  left: 28px;
  top: 28px;
  width: 10px;
  height: 10px;
  border-radius: 999px;
  border: 1px solid var(--color-ocean-deep);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08);
  z-index: 3;
  pointer-events: none;
}

.vessel-websocket-status-connected {
  background: #2bc16c;
}

.vessel-websocket-status-stale {
  background: #f4a641;
}

.vessel-websocket-status-disconnected {
  background: #df4f4f;
}

@keyframes vessel-websocket-message-glow-pulse {
  0% {
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08),
    0 0 4px 0 rgba(43, 193, 108, 0.4);
  }
  50% {
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08),
    0 0 12px 2px rgba(43, 193, 108, 0.6);
  }
  100% {
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08),
    0 0 4px 0 rgba(43, 193, 108, 0.4);
  }
}

.vessel-websocket-status-indicator-with-message-glow {
  animation: vessel-websocket-message-glow-pulse 600ms ease-out;
}

/* Subtle affordances on hover. We don't add a background or border around the whole
   trigger (that would re-create the pill the user explicitly rejected); instead each
   sub-element nudges its own color so the cursor: pointer + group reaction makes the
   single-click behavior discoverable. */
.account-menu-trigger:hover .account-menu-avatar {
  border-color: var(--color-gold);
}

.account-menu-trigger:hover .account-menu-trigger-name,
.account-menu-trigger:hover .account-menu-trigger-title,
.account-menu-trigger:hover .account-menu-trigger-caret {
  color: var(--color-gold-light);
}

.account-menu-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + 0.45rem);
  min-width: 180px;
  background: var(--color-ocean-mid);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 0.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  z-index: 300;
}

.account-menu-item {
  width: 100%;
  text-align: left;
  background: transparent;
  color: var(--color-text-primary);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.6rem;
  cursor: pointer;
  font-size: 0.85rem;
}

.account-menu-section-label {
  padding: 0.3rem 0.55rem 0.15rem;
  color: var(--color-text-muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.account-menu-vessel-section {
  max-height: 40vh;
  overflow-y: auto;
  overflow-x: hidden;
}

.account-menu-vessel-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.account-menu-vessel-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-right: 0.75rem;
}

.account-menu-vessel-selected {
  color: var(--color-gold-light);
  font-size: 0.72rem;
  border: 1px solid var(--color-border-gold);
  border-radius: 999px;
  padding: 0.1rem 0.45rem;
}

.account-menu-divider {
  width: 100%;
  height: 1px;
  background: var(--color-border);
  margin: 0.25rem 0;
}

.account-menu-item:hover {
  background: var(--color-ocean-surface);
  border-color: var(--color-border);
}

.account-menu-item-danger {
  color: #f1a39e;
}

.account-menu-item-danger:hover {
  border-color: var(--color-danger);
  background: var(--color-danger-light);
}

.app-shell {
  opacity: 0;
  transition: opacity 380ms ease;
}

.app-shell-visible {
  opacity: 1;
}

.startup-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(ellipse at center, rgba(30, 74, 122, 0.18) 0%, rgba(5, 13, 26, 0.98) 65%);
  opacity: 1;
  transition: opacity 420ms ease;
}

.startup-overlay-fading {
  opacity: 0;
}

.startup-overlay-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.25rem;
}

.startup-overlay-logo {
  width: min(340px, 58vw);
  height: auto;
  filter: drop-shadow(0 6px 24px rgba(0, 0, 0, 0.45));
}

.startup-overlay-spinner {
  width: 52px;
  height: 52px;
  border-width: 4px;
}

/* ── Phone search compaction (breakpoint convention: variables.css) ──
   Below the phone breakpoint the persistent input is replaced by an icon
   toggle; tapping it expands the search into a full-width overlay bar across
   the navbar (state: app.navbarSearchExpanded, search.js).

   This block MUST stay at the END of the file: it overrides equal-specificity
   base rules declared above (e.g. .account-menu-trigger-identity's
   display: inline-flex), and in CSS the LAST equal-specificity declaration
   wins. When this block sat mid-file, the identity text stayed visible on
   phones and pushed the navbar wider than the viewport. */
@media (max-width: 640px) {
  .navbar-search-expand-toggle {
    display: inline-flex;
  }

  .navbar-search:not(.navbar-search-expanded) .navbar-search-input {
    display: none;
  }

  .navbar-search-expanded {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: var(--navbar-total-height);
    z-index: 20;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: env(safe-area-inset-top, 0px) calc(1rem + env(safe-area-inset-right, 0px)) 0 calc(1rem + env(safe-area-inset-left, 0px));
    background: var(--color-ocean-deep);
  }

  .navbar-search-expanded .navbar-search-expand-toggle {
    display: none;
  }

  .navbar-search-expanded .navbar-search-collapse-toggle {
    display: inline-flex;
  }

  .navbar-search-expanded .navbar-search-input {
    display: block;
    flex: 1 1 auto;
    width: auto;
    max-width: none;
  }

  /* Results pin edge-to-edge under the bar; fixed positioning escapes the
     absolutely-positioned overlay so the sheet spans the full viewport. */
  .navbar-search-dropdown {
    position: fixed;
    top: var(--navbar-total-height);
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
    border-radius: 0;
    border-left: none;
    border-right: none;
    max-height: calc(100vh - var(--navbar-total-height));
    max-height: calc(100dvh - var(--navbar-total-height));
  }

  /* Avatar-only account trigger on phones. */
  .account-menu-trigger-identity {
    display: none;
  }

  /* Full results page: stack the query input over the type filter. */
  .search-page-controls {
    flex-direction: column;
  }
}

/* iOS Safari auto-zooms focused inputs below 16px; floor the search font on
   touch phones (see --touch-input-font-size in variables.css). */
@media (pointer: coarse) and (max-width: 640px) {
  .navbar-search-input {
    font-size: var(--touch-input-font-size);
  }
}


/** stylesheets/src/layout.css **/
/* ── App body (nav rail + content) ──────────────────────────── */
.app-body {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
}

/* ── Main content ───────────────────────────────────────────── */
.main-content {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 1200px;
  margin: 0 auto;
  padding: 2.5rem 2rem;
}

/* Home dashboard runs as a full-bleed canvas: drop the centered-column cap and
   padding so the bento canvas can fill the area to the right of the rail. */
.main-content-fluid {
  max-width: none;
  margin: 0;
  padding: 0;
}

/* ── Section header ─────────────────────────────────────────── */
.section-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}

.section-header-action {
  margin-left: auto;
}

.section-title {
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--color-text-primary);
  letter-spacing: 0.04em;
}

/* ── Responsive (phone breakpoint — convention in variables.css) ── */
@media (max-width: 640px) {
  .navbar {
    /* Keep the safe-area top inset from navbar.css; only tighten the sides. */
    padding-left: calc(1rem + env(safe-area-inset-left, 0px));
    padding-right: calc(1rem + env(safe-area-inset-right, 0px));
  }

  /* The EXPANDED phone rail is the narrow icon-only form (labels hidden
     below). The collapsed phone state hides the rail entirely — 0px width plus
     a floating expand handle — and lives in tabs.css (which loads after this
     file and owns the rail). */
  :root {
    --nav-rail-active-width: var(--nav-rail-width-collapsed);
  }

  .view-tabs {
    padding-left: 0.4rem;
    padding-right: 0.4rem;
  }

  .view-tab {
    justify-content: center;
    gap: 0;
    padding-left: 0;
    padding-right: 0;
  }

  .view-tab-label {
    display: none;
  }

  /* The rail is forced collapsed on phones regardless of the stored
     preference, so the vessel image must shrink here too. */
  .nav-rail-vessel-image-thumbnail {
    width: var(--nav-rail-vessel-image-width-collapsed);
  }

  .main-content:not(.main-content-fluid) {
    padding: 1.5rem 1rem;
  }

  /* The single-row header (title · badges · controls · action) overflows a
     phone viewport, pushing the primary action off-screen/under later content.
     Wrap instead, with the action buttons growing to comfortable widths. */
  .section-header {
    flex-wrap: wrap;
    row-gap: 0.5rem;
  }

  .section-header-action {
    margin-left: 0;
    flex: 1 1 auto;
  }

  .form-row {
    flex-direction: column;
  }

  .relationship-form {
    flex-direction: column;
  }

  .permission-assignment-header {
    flex-direction: column;
    align-items: stretch;
  }

  .permission-assignment-row {
    grid-template-columns: 1fr;
  }

  /* Bottom-sheet / full-screen modal rules live in modals.css (which loads
     AFTER this file in the concat order — build.sbt — so its base .modal
     rules would silently win over any equal-specificity phone rules here). */

  /* Landscape-notch clearance for the icon rail. */
  .view-tabs {
    padding-left: calc(0.4rem + env(safe-area-inset-left, 0px));
  }
}


/** stylesheets/src/chrome.css **/
/* ── Environment banner ─────────────────────────────────────── */
/* Inline styles in index.scala.html render this banner before main.css
   even loads — these rules just polish the look once the stylesheet is
   live. Production renders no banner at all (the bootstrap script in
   index.scala.html early-returns when hostname === azimuth.at). */
.environment-banner {
  font-family: var(--font-family, system-ui, -apple-system, sans-serif);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(0, 0, 0, 0.2);
  border-top: none;
}

.environment-banner-stage {
  background: var(--color-warning) !important;
}

.environment-banner-local {
  background: var(--color-success) !important;
}

.environment-banner-unknown {
  background: var(--color-danger) !important;
}

/* ── Tap-tap move (touch drag-and-drop alternative) ─────────────
   Shared visual vocabulary for the two-step "arm → target" flow
   (tapTapMove.js; docs/planning/mobile-responsive.md § Phase 4). The banner
   floats above the modal stack (arming can begin inside the inventory detail
   modal) and clears the iOS home indicator via the bottom safe-area inset.
   Grips (.tap-tap-grip) are touch-only affordances, revealed at COARSE. */
.tap-tap-armed-banner {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));
  z-index: 3000;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  max-width: calc(100vw - 1.5rem);
  padding: 0.5rem 0.9rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  color: var(--color-text-primary);
  font-size: 0.85rem;
}

.tap-tap-armed-banner-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tap-tap-armed-banner-cancel {
  flex-shrink: 0;
}

/* Armed source: loud gold glow so the mid-flow state is unmissable. */
.tap-tap-armed {
  outline: 2px solid var(--color-gold);
  outline-offset: -1px;
  box-shadow: 0 0 0 3px var(--color-gold-subtle);
}

/* Eligible destination while something is armed: a quieter affordance. */
.tap-tap-target {
  outline: 1px dashed var(--color-border-gold);
  outline-offset: -1px;
  cursor: pointer;
}

/* Grip buttons that ARM a tap-tap move: touch-only (interaction affordances
   key off pointer type — convention in variables.css). */
.tap-tap-grip {
  display: none;
}

@media (pointer: coarse) {
  .tap-tap-grip {
    display: inline-flex;
  }
}

/* ── Badge ──────────────────────────────────────────────────── */
.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.15em 0.6em;
  background: var(--color-gold-subtle);
  border: 1px solid var(--color-border-gold);
  color: var(--color-gold-light);
  font-size: 0.75rem;
  font-weight: 600;
  border-radius: 20px;
}

/* ── Loading indicator ──────────────────────────────────────── */
.loading-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 4rem;
  color: var(--color-text-secondary);
  gap: 1rem;
}

.spinner {
  width: 36px;
  height: 36px;
  border: 3px solid var(--color-ocean-surface);
  border-top-color: var(--color-gold);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ── Alerts ─────────────────────────────────────────────────── */
.alert {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.85rem 1rem;
  border-radius: var(--radius-md);
  margin-bottom: 1.5rem;
  font-size: 0.875rem;
}

.alert-error {
  background: var(--color-danger-light);
  border: 1px solid var(--color-danger);
  color: #f1a39e;
}

.alert-warning {
  background: var(--color-warning-light);
  border: 1px solid var(--color-warning);
  color: var(--color-warning-text);
}

.alert-icon {
  flex-shrink: 0;
  color: var(--color-warning);
  font-size: 1rem;
  line-height: 1.3;
  margin-top: 0.1rem;
}

.alert-error .alert-icon {
  color: var(--color-danger);
}

.alert-close {
  margin-left: auto;
  background: none;
  border: none;
  color: inherit;
  font-size: 1.1rem;
  cursor: pointer;
  padding: 0 0.25rem;
  line-height: 1;
  opacity: 0.7;
}

.alert-close:hover {
  opacity: 1;
}

.error-list {
  padding-left: 1.25rem;
  list-style: disc;
}

.error-list li {
  margin-bottom: 0.2rem;
}

/* ── Empty state ────────────────────────────────────────────── */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 5rem 2rem;
  text-align: center;
  color: var(--color-text-secondary);
  gap: 1rem;
}

.empty-state-icon {
  font-size: 3.5rem;
  opacity: 0.3;
}


/** stylesheets/src/components.css **/
/* ── Component grid ─────────────────────────────────────────── */
.component-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.25rem;
}

/* ── Component card ─────────────────────────────────────────── */
.component-card {
  background: var(--color-ocean-mid);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  cursor: pointer;
  transition: transform var(--transition), border-color var(--transition), box-shadow var(--transition);
  overflow: hidden;
}

.component-card:hover {
  transform: translateY(-2px);
  border-color: var(--color-border-gold);
  box-shadow: 0 4px 24px rgba(201, 168, 76, 0.15);
}

.component-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.75rem 1rem 0;
}

.component-card-body {
  padding: 0.5rem 1rem 1rem;
}

.component-card-actions {
  display: flex;
  gap: 0.25rem;
}

.component-name {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text-primary);
  margin: 0.35rem 0 0.4rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.component-description {
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  margin: 0 0 0.5rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.component-meta {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
  font-size: 0.8rem;
}

.meta-label {
  color: var(--color-text-muted);
  min-width: 44px;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.meta-value {
  color: var(--color-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Component type badges ──────────────────────────────────── */
.component-type-badge {
  display: inline-block;
  padding: 0.18em 0.6em;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.type-vessel {
  background: rgba(21, 94, 117, 0.5);
  color: #7dd3e8;
  border: 1px solid rgba(125, 211, 232, 0.3);
}

.type-engine {
  background: rgba(120, 40, 20, 0.5);
  color: #f4a07a;
  border: 1px solid rgba(244, 160, 122, 0.3);
}

.type-tank {
  background: rgba(10, 55, 90, 0.5);
  color: #6ab8e8;
  border: 1px solid rgba(106, 184, 232, 0.3);
}

.type-filter {
  background: rgba(30, 80, 30, 0.5);
  color: #7dcc88;
  border: 1px solid rgba(125, 204, 136, 0.3);
}

.type-pump {
  background: rgba(60, 30, 100, 0.5);
  color: #b89cf5;
  border: 1px solid rgba(184, 156, 245, 0.3);
}

.type-impeller {
  background: rgba(20, 70, 100, 0.5);
  color: #7ab8e8;
  border: 1px solid rgba(122, 184, 232, 0.3);
}

.type-anode {
  background: rgba(90, 80, 10, 0.5);
  color: #e8d46a;
  border: 1px solid rgba(232, 212, 106, 0.3);
}

.type-battery {
  background: rgba(10, 70, 50, 0.5);
  color: #6adbb0;
  border: 1px solid rgba(106, 219, 176, 0.3);
}

.type-appliance {
  background: rgba(80, 50, 10, 0.5);
  color: #e8b56a;
  border: 1px solid rgba(232, 181, 106, 0.3);
}

.type-document {
  background: rgba(15, 25, 80, 0.5);
  color: #8a9ef0;
  border: 1px solid rgba(138, 158, 240, 0.3);
}

.type-other {
  background: rgba(50, 55, 70, 0.5);
  color: #a8aec8;
  border: 1px solid rgba(168, 174, 200, 0.3);
}

.type-water {
  background: rgba(8, 60, 120, 0.5);
  color: #5caee4;
  border: 1px solid rgba(92, 174, 228, 0.3);
}

.type-fire {
  background: rgba(140, 50, 0, 0.5);
  color: #ff7040;
  border: 1px solid rgba(255, 112, 64, 0.3);
}

.type-power {
  background: rgba(60, 55, 0, 0.6);
  color: #f5d840;
  border: 1px solid rgba(245, 216, 64, 0.3);
}

.type-fuel_tank {
  background: rgba(90, 60, 10, 0.5);
  color: #e8a13c;
  border: 1px solid rgba(232, 161, 60, 0.3);
}

.type-freshwater_tank {
  background: rgba(8, 60, 120, 0.5);
  color: #5caee4;
  border: 1px solid rgba(92, 174, 228, 0.3);
}

.type-grey_water_tank {
  background: rgba(60, 65, 75, 0.5);
  color: #aab2bd;
  border: 1px solid rgba(170, 178, 189, 0.3);
}

.type-blackwater_tank {
  background: rgba(50, 40, 30, 0.6);
  color: #b3937a;
  border: 1px solid rgba(179, 147, 122, 0.3);
}

.type-electronics {
  background: rgba(8, 70, 70, 0.5);
  color: #4fd1c5;
  border: 1px solid rgba(79, 209, 197, 0.3);
}

.type-transmission {
  background: rgba(70, 55, 25, 0.5);
  color: #e8c07a;
  border: 1px solid rgba(232, 192, 122, 0.3);
}

.type-drive {
  background: rgba(40, 60, 90, 0.5);
  color: #8ab6e8;
  border: 1px solid rgba(138, 182, 232, 0.3);
}

/* Secondary badge rendered next to the primary type badge in the detail modal. Neutral tone so it
   reads as a refinement of the type rather than competing with it. */
.component-subtype-badge {
  display: inline-block;
  margin-left: 0.4em;
  padding: 0.18em 0.6em;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: rgba(60, 65, 75, 0.45);
  color: #c5ccd8;
  border: 1px solid rgba(170, 178, 189, 0.25);
}

/* ── Component type icons (hierarchy + relationship tree) ────── */
/* Fixed-width Tabler-icon replacement for the textual component-type badge.
   Each instance is a square cell so adjacent component names stay aligned
   regardless of which icon a node uses. */
.component-type-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  flex: 0 0 1.5rem;
  margin: -0.15rem -0.1rem;
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  line-height: 1;
  overflow: visible;
}
.component-type-icon .ti {
  font-size: 1.875rem;
  line-height: 1;
}

/* Per-type accent colors carried over from the previous badge palette. */
.component-type-icon-vessel    { color: #7dd3e8; }
.component-type-icon-engine    { color: #f4a07a; }
.component-type-icon-transmission { color: #e8c07a; }
.component-type-icon-drive     { color: #8ab6e8; }
.component-type-icon-tank      { color: #6ab8e8; }
.component-type-icon-filter    { color: #7dcc88; }
.component-type-icon-pump      { color: #b89cf5; }
.component-type-icon-impeller  { color: #7ab8e8; }
.component-type-icon-anode     { color: #e8d46a; }
.component-type-icon-battery   { color: #6adbb0; }
.component-type-icon-appliance { color: #e8b56a; }
.component-type-icon-document  { color: #8a9ef0; }
.component-type-icon-water     { color: #5caee4; }
.component-type-icon-fire      { color: #ff7040; }
.component-type-icon-power     { color: #f5d840; }
.component-type-icon-fuel_tank       { color: #e8a13c; }
.component-type-icon-freshwater_tank { color: #5caee4; }
.component-type-icon-grey_water_tank { color: #aab2bd; }
.component-type-icon-blackwater_tank { color: #b3937a; }
.component-type-icon-electronics     { color: #4fd1c5; }
.component-type-icon-other     { color: #a8aec8; }

/* Name-driven override: any component whose name contains "heater" reads in a
   warm red regardless of its base ComponentType (e.g. "Water Heater" overrides
   the cool blue water tint). Higher specificity than the per-type rules above
   so it wins without !important. */
.component-type-icon.component-type-icon-heater {
  color: #ff7040;
}

/* Nautical port (red) / starboard (green) indicator dot.
   Glows via layered box-shadows so it reads as a status light, not just a pip. */
.component-type-side-dot {
  position: absolute;
  bottom: -0.15rem;
  right: -0.15rem;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.35);
  pointer-events: none;
}
.component-type-icon-port .component-type-side-dot {
  background: #ff4d4f;
  box-shadow:
    0 0 4px rgba(255, 77, 79, 0.95),
    0 0 10px rgba(255, 77, 79, 0.6),
    0 0 18px rgba(255, 77, 79, 0.35);
}
.component-type-icon-starboard .component-type-side-dot {
  background: #3ddc6f;
  box-shadow:
    0 0 4px rgba(61, 220, 111, 0.95),
    0 0 10px rgba(61, 220, 111, 0.6),
    0 0 18px rgba(61, 220, 111, 0.35);
}

/* ── Relationship tree ──────────────────────────────────────── */
.relationship-tree {
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 1rem;
  margin-bottom: 1rem;
  overflow-x: auto;
}

.tree-node {
  padding-left: 1.25rem;
  position: relative;
}

.tree-node::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.7em;
  bottom: 0;
  width: 1px;
  background: var(--color-border);
}

.tree-node:first-child {
  padding-left: 0;
}

.tree-node:first-child::before {
  display: none;
}

.tree-node-label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.3rem 0.6rem;
  margin-bottom: 0.4rem;
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 0.875rem;
  color: var(--color-text-primary);
  position: relative;
}

.tree-node-label-button {
  cursor: pointer;
  font: inherit;
  text-align: left;
  transition: border-color var(--transition), background var(--transition), box-shadow var(--transition);
}

.tree-node-label-button:hover {
  border-color: var(--color-border-gold);
  background: rgba(22, 51, 88, 0.95);
  box-shadow: 0 2px 12px rgba(201, 168, 76, 0.12);
}

.tree-node-label-active {
  border-color: var(--color-border-gold);
  box-shadow: inset 0 0 0 1px rgba(201, 168, 76, 0.4);
}

.tree-node-label::before {
  content: '─ ';
  color: var(--color-border);
  position: absolute;
  left: -1.1rem;
}

.tree-node:first-child > .tree-node-row > .tree-node-label::before {
  display: none;
}

.tree-node-row {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-bottom: 0.4rem;
}

.tree-node-row > .tree-node-label {
  margin-bottom: 0;
}

.tree-node-add-child {
  opacity: 0;
  transition: opacity var(--transition);
  font-size: 1rem;
  line-height: 1;
  padding: 0.2rem 0.45rem;
  color: var(--color-text-secondary);
}

.tree-node-row:hover .tree-node-add-child {
  opacity: 1;
}

/* No hover on touch devices — the affordance must be always visible
   (fe.md § RESPONSIVE & MOBILE touch rules). */
@media (pointer: coarse) {
  .tree-node-add-child {
    opacity: 1;
  }
}

.tree-node-add-child:hover {
  color: var(--color-gold);
}

.tree-children {
  margin-left: 1.25rem;
  border-left: 1px solid var(--color-border);
  padding-left: 0.75rem;
  margin-top: 0.25rem;
}

/* ── Relationship form ──────────────────────────────────────── */
.relationship-form {
  display: flex;
  gap: 0.75rem;
  align-items: flex-end;
}

/* ── Interactive Component Hierarchy view ─────────────────────────── */
.component-hierarchy {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}
.section-header-controls {
  display: flex;
  gap: 0.4rem;
  margin-left: 0.75rem;
  flex-wrap: wrap;
}
.nested-component-card {
  background: var(--color-ocean-mid);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  transition: border-color var(--transition), box-shadow var(--transition), background var(--transition);
}
.nested-component-card:hover {
  border-color: var(--color-border-gold);
}
.nested-component-card-depth-0 {
  background: var(--color-ocean-mid);
}
.nested-component-card-depth-1,
.nested-component-card-depth-3,
.nested-component-card-depth-5 {
  background: var(--color-ocean-surface);
}
.nested-component-card-depth-2,
.nested-component-card-depth-4,
.nested-component-card-depth-6 {
  background: var(--color-ocean-deep);
}
.nested-component-card-drop-target {
  border: 1px dashed var(--color-gold) !important;
  box-shadow: 0 0 0 2px rgba(201, 168, 76, 0.25), 0 4px 24px rgba(201, 168, 76, 0.18);
}
.nested-component-card-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 0.85rem;
  border-bottom: 1px solid var(--color-border);
  cursor: pointer;
  user-select: none;
}
.nested-component-card-header:active {
  cursor: grabbing;
}
.nested-component-card-header .nested-component-drag-handle {
  cursor: grab;
}
.nested-component-card-header .nested-component-drag-handle:active {
  cursor: grabbing;
}
.nested-component-drag-handle {
  color: var(--color-text-muted);
  font-size: 1.1rem;
  line-height: 1;
  user-select: none;
  letter-spacing: -2px;
}
.nested-component-toggle {
  font-size: 0.85rem;
  padding: 0.2rem 0.4rem;
}
.nested-component-name {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text-primary);
  margin: 0;
  flex: 1 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.nested-component-card-actions {
  display: flex;
  gap: 0.25rem;
  margin-left: auto;
}
.nested-component-unlink {
  color: var(--color-gold-light);
  border-color: rgba(201, 168, 76, 0.3);
}
.nested-component-unlink:hover:not(:disabled) {
  background: var(--color-gold-subtle);
  border-color: var(--color-gold);
  color: var(--color-gold);
}
.nested-component-details {
  padding: 0.6rem 0.85rem 0.85rem;
  border-bottom: 1px solid var(--color-border);
}
.nested-component-description {
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  margin: 0 0 0.6rem;
}
.nested-component-meta-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0.4rem 1rem;
  margin-bottom: 0.6rem;
}
.nested-component-images {
  margin-top: 0.6rem;
}
.nested-component-inventory {
  margin: 0.2rem 0 0.6rem;
}
.nested-component-inventory-list {
  list-style: none;
  margin: 0.2rem 0 0;
  padding: 0;
  font-size: 0.85rem;
  color: var(--color-text-secondary);
}
.nested-component-inventory-list li {
  padding: 0.1rem 0;
}
.nested-component-inventory-onhand {
  color: var(--color-text-tertiary, var(--color-text-secondary));
  font-style: italic;
  margin-left: 0.25rem;
}
.nested-component-details-with-images {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 1rem;
}
.nested-component-details-main {
  flex: 1 1 auto;
  min-width: 0;
}
.nested-component-details-images {
  flex: 0 0 auto;
  max-width: 60%;
}
.nested-component-details-images .image-carousel {
  gap: 0.4rem;
  justify-content: flex-end;
}
.nested-component-details-images .image-carousel-item {
  max-width: none;
}
.nested-component-image-thumbnail {
  /* Inline ng-style provides the actual width/height per depth + image count. */
  width: auto;
  height: auto;
}
/* Phone breakpoint (convention: variables.css — migrated from a stray 720px). */
@media (max-width: 640px) {
  .component-hierarchy {
    gap: 0.5rem;
  }

  /* The header's touch-sized icon buttons plus the grip/toggle/type-icon can
     exceed the phone card width, crushing the flex-shrinking name to zero.
     Guarantee the name a readable minimum and let the action cluster wrap
     onto its own right-aligned line instead. */
  .nested-component-card-header {
    flex-wrap: wrap;
    gap: 0.35rem;
    row-gap: 0.2rem;
    padding: 0.4rem 0.55rem;
  }

  .nested-component-name {
    flex: 1 1 6rem;
    min-width: 6rem;
  }

  .nested-component-card-actions {
    margin-left: auto;
    gap: 0.15rem;
  }

  /* Deliberate exception to the 44px .btn-icon coarse floor (buttons.css):
     with three levels of nesting, four 44px buttons dominate a phone card.
     38px keeps the tree usable while staying a workable tap target; the
     buttons sit in a sparse right-aligned cluster, not edge to edge. */
  .nested-component-card-header .btn-icon,
  .nested-component-card-header .nested-component-toggle {
    min-width: 38px;
    min-height: 38px;
  }

  /* Indentation was ~2.75rem per level (children padding-left + margin-left),
     which walked third-tier cards straight off a 390px screen. A slim 0.9rem
     step keeps the tree readable AND on-screen. */
  .nested-component-children {
    padding: 0.3rem 0.3rem 0.5rem 0.45rem;
    margin-left: 0.45rem;
    gap: 0.45rem;
  }

  .nested-component-children-toggle-row {
    padding: 0.25rem 0.55rem;
  }

  .nested-component-details {
    padding: 0.45rem 0.55rem 0.6rem;
  }

  /* ── Tier scaling: deeper components render progressively smaller ──
     Each card carries its own nested-component-card-depth-N class, so child
     combinators scope every rule to that card's OWN header (descendants keep
     their own depth class and match their own tier). */
  .nested-component-card-depth-2 > .nested-component-card-header,
  .nested-component-card-depth-3 > .nested-component-card-header,
  .nested-component-card-depth-4 > .nested-component-card-header,
  .nested-component-card-depth-5 > .nested-component-card-header,
  .nested-component-card-depth-6 > .nested-component-card-header {
    padding-top: 0.3rem;
    padding-bottom: 0.3rem;
  }

  .nested-component-card-depth-2 > .nested-component-card-header > .nested-component-name,
  .nested-component-card-depth-3 > .nested-component-card-header > .nested-component-name {
    font-size: 0.9rem;
  }

  .nested-component-card-depth-2 > .nested-component-card-header > .component-type-icon .ti,
  .nested-component-card-depth-3 > .nested-component-card-header > .component-type-icon .ti {
    font-size: 1.5rem;
  }

  .nested-component-card-depth-4 > .nested-component-card-header > .nested-component-name,
  .nested-component-card-depth-5 > .nested-component-card-header > .nested-component-name,
  .nested-component-card-depth-6 > .nested-component-card-header > .nested-component-name {
    font-size: 0.82rem;
  }

  .nested-component-card-depth-4 > .nested-component-card-header > .component-type-icon .ti,
  .nested-component-card-depth-5 > .nested-component-card-header > .component-type-icon .ti,
  .nested-component-card-depth-6 > .nested-component-card-header > .component-type-icon .ti {
    font-size: 1.25rem;
  }

  .nested-component-details-with-images {
    flex-direction: column;
  }
  .nested-component-details-images {
    max-width: 100%;
  }
  .nested-component-details-images .image-carousel {
    justify-content: flex-start;
  }
}
.nested-component-children-toggle-row {
  padding: 0.4rem 0.85rem;
}
.nested-component-children {
  padding: 0.4rem 0.85rem 0.85rem 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  border-left: 2px solid var(--color-border);
  margin-left: 1.25rem;
}
/* ── Component drop action modal ──────────────────────────────────── */
.component-drop-actions {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin: 1rem 0;
}
.component-drop-actions .btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.2rem;
  text-align: left;
  padding: 0.7rem 0.9rem;
}
.component-drop-actions .btn-help {
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--color-text-muted);
  text-transform: none;
  letter-spacing: normal;
}

/* ── Allowed measurement types checkboxes (component create/edit) ─── */
.component-measurement-type-checkboxes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  margin-top: 0.35rem;
}

.component-measurement-type-checkbox {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  cursor: pointer;
  user-select: none;
}

.component-measurement-type-checkbox input[type="checkbox"] {
  cursor: pointer;
}

/** stylesheets/src/buttons.css **/
/* ── Buttons ────────────────────────────────────────────────── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.5rem 1.1rem;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), opacity var(--transition);
  white-space: nowrap;
  line-height: 1.4;
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-primary {
  background: var(--color-gold);
  color: var(--color-ocean-deepest);
  border-color: var(--color-gold);
  font-weight: 600;
}

.btn-primary:hover:not(:disabled) {
  background: var(--color-gold-light);
  border-color: var(--color-gold-light);
}

.btn-secondary {
  background: transparent;
  color: var(--color-text-secondary);
  border-color: var(--color-border);
}

.btn-secondary:hover:not(:disabled) {
  background: var(--color-ocean-surface);
  border-color: var(--color-ocean-mist);
  color: var(--color-text-primary);
}

.btn-ghost {
  background: transparent;
  color: var(--color-gold);
  border-color: var(--color-border-gold);
  font-size: 0.8rem;
}

.btn-ghost:hover:not(:disabled) {
  background: var(--color-gold-subtle);
}

.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  font-size: 0.95rem;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}

.btn-icon:hover {
  background: var(--color-ocean-surface);
  color: var(--color-gold-light);
}

/* Touch devices need a 44px minimum hit area (Apple HIG). The glyph size is
   unchanged — only the tappable box grows. Interaction affordances key off
   pointer type, never viewport width (convention: variables.css). */
@media (pointer: coarse) {
  .btn-icon,
  .modal-close {
    min-width: var(--touch-target-minimum-size);
    min-height: var(--touch-target-minimum-size);
  }
}

.btn-danger {
  background: transparent;
  color: var(--color-danger);
  border-color: rgba(192, 57, 43, 0.3);
  font-size: 0.8rem;
}

.btn-danger:hover:not(:disabled) {
  background: var(--color-danger-light);
  border-color: var(--color-danger);
  color: #f1a39e;
}

.btn-small {
  padding: 0.2rem 0.45rem;
  font-size: 0.72rem;
}

.btn-deactivate {
  font-size: 0.8rem;
  padding: 0.3rem 0.75rem;
}

/* ── Complete-task button ────────────────────────────────────── */
.btn-complete-task {
  background: transparent;
  color: #81c784;
  border: 1px solid rgba(76, 175, 80, 0.5);
  font-weight: 500;
}

.btn-complete-task:hover:not(:disabled) {
  background: rgba(76, 175, 80, 0.15);
  border-color: #4caf50;
  color: #a5d6a7;
}

/* ── Solid danger button (used in confirm dialogs) ───────────── */
.btn-danger-solid {
  background: var(--color-danger);
  color: #fff;
  border: 1px solid var(--color-danger);
}

.btn-danger-solid:hover:not(:disabled) {
  background: #a93226;
  border-color: #a93226;
  color: #fff;
}

/* ── Task nav buttons ────────────────────────────────────────── */
.btn-task-nav {
  padding: 0.3rem 0.85rem;
  font-size: 0.8rem;
  font-weight: 500;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}

.btn-task-nav:hover:not([disabled]) {
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
  border-color: var(--color-border-gold);
}

.btn-task-nav[disabled] {
  opacity: 0.35;
  cursor: not-allowed;
}

/* ── Link button ─────────────────────────────────────────────── */
.btn-link {
  background: transparent;
  border: none;
  color: var(--color-gold-light);
  cursor: pointer;
  text-decoration: underline;
  padding: 0;
  justify-content: flex-start;
}

/* ── Google sign-in button ───────────────────────────────────── */
.btn-google {
  background: linear-gradient(180deg, #ffffff 0%, #f7f9fc 100%);
  border: 1px solid #dadce0;
  color: #3c4043;
  font-weight: 600;
  gap: 0.55rem;
}

.btn-google:hover {
  background: linear-gradient(180deg, #ffffff 0%, #eef3fb 100%);
  border-color: #b8c4d6;
}

.btn-google::before {
  content: 'G';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  font-size: 0.8rem;
  font-weight: 700;
  color: #ffffff;
  background: linear-gradient(135deg, #4285f4 0%, #34a853 45%, #fbbc05 70%, #ea4335 100%);
}


/** stylesheets/src/modals.css **/
/* ── Modal overlay ──────────────────────────────────────────── */
/* Overlays are TRANSPARENT positioning layers only. The dark, blurred dimming is painted by a
   single shared `.modal-shared-backdrop` (managed by the modalStack directive/service) that
   always sits just beneath the top-most open overlay — this prevents two stacked overlays from
   compounding the dim toward black / double-blurring. The directive assigns each overlay's
   z-index in open order; the static value below is only a pre-link fallback. */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: transparent;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  animation: fadeIn 150ms ease;
}

/* Single shared dim/blur layer for the entire modal stack. Position/inset are styled here;
   `z-index` and `display` are driven imperatively by modalStackService so the backdrop always
   sits one level below the top-most open overlay. `pointer-events: none` keeps outside-click
   dismissal working on the top overlay itself (which still owns the ng-mousedown handler). */
.modal-shared-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(5, 13, 26, 0.85);
  backdrop-filter: blur(4px);
  pointer-events: none;
  display: none;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* ── Modal ──────────────────────────────────────────────────── */
.modal {
  background: var(--color-ocean-mid);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-modal);
  width: 100%;
  max-width: 560px;
  /* dvh line wins where supported so the modal respects the real visible
     viewport on mobile; vh is the older-browser fallback. */
  max-height: 90vh;
  max-height: 90dvh;
  display: flex;
  flex-direction: column;
  animation: slideUp 180ms ease;
}

.modal-large {
  max-width: 800px;
}

/* ── Task detail modal prev/next navigation ─────────────────── */
.task-detail-nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 1.25rem;
  border-bottom: 1px solid var(--color-border);
  background: var(--color-ocean-deep);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  flex-shrink: 0;
}

.task-detail-nav-position {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  letter-spacing: 0.04em;
}

@keyframes slideUp {
  from {
    transform: translateY(16px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.modal-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 1.25rem 1.5rem 1rem;
  border-bottom: 1px solid var(--color-border);
  gap: 1rem;
  flex-shrink: 0;
}

.modal-header-actions {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.modal-title {
  font-size: 1.1rem;
  font-weight: 600;
  color: var(--color-text-primary);
  margin-top: 0.25rem;
}

.modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--color-text-muted);
  font-size: 1.3rem;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}

.modal-close:hover {
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
}

.modal-body {
  padding: 1.5rem;
  overflow-y: auto;
  flex: 1;
}

.empty-modal-text {
  color: var(--color-text-secondary);
}

/* ── Detail view ────────────────────────────────────────────── */
.detail-section {
  margin-bottom: 2rem;
}

.detail-section:last-child {
  margin-bottom: 0;
}

.detail-section-title {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-gold);
  margin-bottom: 1rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  border-bottom: 1px solid var(--color-border-gold);
  padding-bottom: 0.5rem;
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0.75rem;
}

.detail-description {
  font-size: 0.9rem;
  color: var(--color-text-secondary);
  line-height: 1.6;
  margin-bottom: 0.75rem;
}

.detail-item {
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.6rem 0.85rem;
}

.detail-item-wide {
  grid-column: 1 / -1;
}

.detail-label {
  display: block;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  margin-bottom: 0.2rem;
}

.detail-value {
  display: block;
  font-size: 0.9rem;
  color: var(--color-text-primary);
  word-break: break-word;
}

.inventory-ledger-table-wrapper {
  overflow-x: auto;
}

.inventory-ledger-location-table-section {
  margin-top: 1rem;
}

.inventory-ledger-location-table-section:first-of-type {
  margin-top: 0.75rem;
}

.inventory-ledger-location-title {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.inventory-ledger-location-count-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: rgba(76, 117, 201, 0.28);
  border: 1px solid rgba(110, 152, 239, 0.55);
  color: var(--color-text-primary);
  font-size: 0.78rem;
  line-height: 1;
}

.inventory-ledger-actions {
  margin-top: 1rem;
  display: flex;
  justify-content: flex-end;
}

.inventory-ledger-table {
  width: 100%;
  border-collapse: collapse;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.inventory-ledger-table td {
  text-align: left;
  padding: 0.55rem 0.65rem;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}

.inventory-ledger-column-header-row td {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-text-secondary);
  background: var(--color-ocean-deep);
}

.inventory-ledger-table tbody tr.inventory-ledger-entry-row:hover {
  background: rgba(255, 255, 255, 0.02);
}

.inventory-ledger-location-header-row td {
  padding: 0.15rem 0.1rem 0.5rem;
  background: transparent;
  border-top: none;
  border-bottom: none;
}

.inventory-ledger-location-header-row.inventory-ledger-location-row-draggable {
  cursor: grab;
}

.inventory-ledger-location-header-row.inventory-ledger-location-row-draggable:active {
  cursor: grabbing;
}

.inventory-ledger-location-header-row.inventory-ledger-location-row-drop-hover td {
  outline: 2px dashed var(--color-accent, rgba(110, 152, 239, 0.8));
  outline-offset: -2px;
  background: rgba(110, 152, 239, 0.08);
}

.inventory-ledger-location-spacer-row td {
  padding: 0.45rem 0;
  background: transparent;
  border-top: none;
  border-bottom: none;
}

.inventory-ledger-location-balance-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: rgba(76, 117, 201, 0.28);
  border: 1px solid rgba(110, 152, 239, 0.55);
  color: var(--color-text-primary);
  font-size: 0.78rem;
  line-height: 1;
}

.inventory-ledger-aggregate-row {
  background: rgba(76, 117, 201, 0.08);
}

.inventory-ledger-expand-button {
  margin-right: 0.5rem;
  min-width: 1.7rem;
}

.inventory-ledger-adjustment-details-row td {
  background: rgba(13, 25, 43, 0.52);
  border-bottom: 1px solid var(--color-border);
}

.inventory-ledger-adjustment-details-table {
  width: 100%;
  border-collapse: collapse;
}

.inventory-ledger-adjustment-details-table td {
  padding: 0.45rem 0.65rem;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-size: 0.85rem;
  color: var(--color-text-secondary);
}

.detail-links {
  margin-top: 0.75rem;
}

.link-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.4rem;
}

.link-chip {
  display: inline-block;
  padding: 0.25em 0.7em;
  background: var(--color-gold-subtle);
  border: 1px solid var(--color-border-gold);
  border-radius: 20px;
  color: var(--color-gold-light);
  font-size: 0.75rem;
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: background var(--transition);
}

.link-chip:hover {
  background: rgba(201, 168, 76, 0.25);
  text-decoration: none;
}

.detail-subsection {
  margin-top: 1.25rem;
}

.detail-subsection-title {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  margin-bottom: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

/* ── Modal subsection (e.g. tasks list inside schedule detail modal) ── */
.modal-subsection {
  margin-top: 2rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--color-border);
}

.modal-subsection-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}

.modal-subsection-title {
  font-size: 0.8rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-gold);
}

.empty-state-compact {
  padding: 1rem 0;
  font-size: 0.9rem;
  color: var(--color-text-muted);
}

/* ── Confirm dialog modal ────────────────────────────────────── */
/* The confirm dialog no longer needs a hard-coded z-index: it opens last, so the modalStack
   directive assigns it the top-most z-index in the stack automatically. */
.modal-confirm {
  max-width: 420px;
}

.modal-confirm-body {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  padding: 2rem 1.75rem 1.5rem;
}

.modal-confirm-message {
  font-size: 1rem;
  color: var(--color-text-primary);
  line-height: 1.6;
}

.modal-confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
}

/* ── Responsive: bottom sheets (phone breakpoint — convention in variables.css) ──
   These rules MUST live in this file, at the end: layout.css loads earlier in
   the concat order (build.sbt), so equal-specificity phone rules placed there
   are silently overridden by the base .modal-overlay/.modal rules above. */
@media (max-width: 640px) {
  .modal-overlay {
    padding: 0;
    align-items: flex-end;
  }

  .modal {
    max-width: 100%;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    /* dvh so the sheet never hides its footer behind mobile browser chrome;
       bottom safe-area padding clears the iOS home indicator. */
    max-height: 95vh;
    max-height: 95dvh;
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  /* Full-screen modal variant for phone-primary "Use" flows (checklist runs,
     task execution). Applied per-template alongside .modal. */
  .modal-fullscreen-phone {
    height: 100vh;
    height: 100dvh;
    max-height: 100vh;
    max-height: 100dvh;
    border-radius: 0;
  }
}


/** stylesheets/src/tables.css **/
/* ── Data table ─────────────────────────────────────────────── */
.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.data-table th,
.data-table td {
  text-align: left;
  padding: 0.55rem 0.85rem;
  border-bottom: 1px solid var(--color-border);
}

.data-table th {
  color: var(--color-text-muted);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  background: var(--color-ocean-deep);
}

.data-table tr:last-child td {
  border-bottom: none;
}

.data-table tbody tr:hover td {
  background: var(--color-ocean-surface);
}

/* ── Table action cell ──────────────────────────────────────── */
.table-actions {
  display: flex;
  gap: 0.25rem;
  white-space: nowrap;
}

/* ── Phone card mode (.data-table-cardable) ─────────────────────
   Below the phone breakpoint (convention: variables.css) an opted-in
   .data-table renders each row as a DENSE two-column card: the header row
   hides and every td shows a tiny caption from its data-label attribute.
   The DOM is unchanged — rows keep their ng-click handlers and test
   selectors. Density modifiers per td:
     .card-cell-primary       row identity — spans both columns, larger, no caption
     .card-cell-span          spans both columns (long text)
     .card-cell-actions       action buttons — spans both columns, laid out in a row
     .card-cell-hidden-phone  low-value column dropped entirely on phones
   Keep cards compact (target ≤ 4 grid lines): prefer hiding columns over
   letting a card grow. */
@media (max-width: 640px) {
  .data-table-cardable {
    display: block;
    border-collapse: separate;
  }

  .data-table-cardable thead {
    display: none;
  }

  .data-table-cardable tbody {
    display: block;
  }

  .data-table-cardable tbody tr {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.3rem 0.75rem;
    align-items: start;
    padding: 0.55rem 0.75rem;
    margin-bottom: 0.5rem;
    /* Near-opaque themed surface + blur: the old 4%-white --color-surface was
       effectively transparent, so cards became unreadable over a custom
       branding background image. The blur keeps text legible over any photo
       even where the tint alone would not. */
    background: color-mix(in srgb, var(--color-ocean-deep) 88%, transparent);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
  }

  .data-table-cardable tbody td {
    display: block;
    padding: 0;
    border-bottom: none;
    min-width: 0;
    overflow-wrap: break-word;
  }

  /* Row-level hover/tint replaces the per-cell paint used in table mode. */
  .data-table-cardable tbody tr:hover {
    background: var(--color-ocean-surface);
  }

  .data-table-cardable tbody tr:hover td {
    background: transparent;
  }

  .data-table-cardable tbody tr.inventory-page-row-low-supply {
    /* Danger tint mixed INTO the opaque card base (not over transparent), so
       low-supply cards stay legible over custom background images too. */
    background: color-mix(in srgb, var(--color-danger) 12%, var(--color-ocean-deep));
  }

  .data-table-cardable tbody tr.inventory-page-row-low-supply td {
    background: transparent;
  }

  .data-table-cardable tbody td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 0.62rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--color-text-muted);
    margin-bottom: 0.05rem;
  }

  .data-table-cardable tbody td.card-cell-primary {
    grid-column: 1 / -1;
    font-size: 0.95rem;
    font-weight: 600;
  }

  .data-table-cardable tbody td.card-cell-primary::before {
    display: none;
  }

  .data-table-cardable tbody td.card-cell-span {
    grid-column: 1 / -1;
  }

  .data-table-cardable tbody td.card-cell-actions {
    grid-column: 1 / -1;
    margin-top: 0.2rem;
  }

  .data-table-cardable tbody td.card-cell-actions::before {
    display: none;
  }

  .data-table-cardable tbody td.card-cell-actions .table-actions {
    justify-content: flex-end;
    flex-wrap: wrap;
    white-space: normal;
  }

  .data-table-cardable tbody td.card-cell-hidden-phone {
    display: none;
  }
}


/* ── Inventory page (list view) filters + rows ──────────────── */
.inventory-page-filters {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.inventory-page-pill-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}

.inventory-page-pill-bar-label {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--color-text-muted);
  margin-right: 0.25rem;
}

.inventory-page-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.7rem;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-text-secondary);
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.inventory-page-pill:hover:not(.inventory-page-pill-active) {
  background: var(--color-ocean-surface);
  border-color: var(--color-border-gold, #d6af5c);
  color: var(--color-text-primary);
}

.inventory-page-pill-active {
  background: #f4a23a;
  border-color: #f4a23a;
  color: #1a1d22;
  box-shadow: 0 0 0 2px rgba(244, 162, 58, 0.32);
}

.inventory-page-pill-active:hover {
  background: #ffb45a;
  border-color: #ffb45a;
  color: #1a1d22;
}

.inventory-page-pill-label {
  max-width: 10rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.inventory-page-filter-banner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.85rem;
  margin-bottom: 0.85rem;
  border-radius: 8px;
  background: rgba(244, 162, 58, 0.12);
  border: 1px solid rgba(244, 162, 58, 0.5);
  color: var(--color-text-primary);
  font-size: 0.82rem;
}

.inventory-page-filter-banner-clear {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-left: auto;
  padding: 0.2rem 0.6rem;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-text-secondary);
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
}

.inventory-page-filter-banner-clear:hover {
  color: var(--color-text-primary);
  border-color: var(--color-border-gold, #d6af5c);
}

.inventory-page-row-low-supply td {
  background: rgba(220, 76, 70, 0.08);
}

.inventory-page-level-low {
  color: #e0635c;
  font-weight: 700;
}

.inventory-page-aggregates-error {
  margin-top: 0.75rem;
  color: #e0635c;
  font-size: 0.82rem;
}

/** stylesheets/src/forms.css **/
/* ── Forms ──────────────────────────────────────────────────── */
.form-group {
  margin-bottom: 1rem;
  flex: 1;
}

.form-row {
  display: flex;
  gap: 1rem;
}

.form-label {
  display: block;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--color-text-secondary);
  margin-bottom: 0.35rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.required {
  color: var(--color-gold);
}

.form-control {
  display: block;
  width: 100%;
  padding: 0.5rem 0.75rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text-primary);
  font-size: 0.875rem;
  line-height: 1.5;
  transition: border-color var(--transition), box-shadow var(--transition);
  appearance: none;
}

.form-control:focus {
  outline: none;
  border-color: var(--color-gold-dark);
  box-shadow: 0 0 0 3px rgba(201, 168, 76, 0.15);
}

/* Make the native calendar / clock picker icon visible on dark backgrounds */
.form-control[type="datetime-local"]::-webkit-calendar-picker-indicator,
.form-control[type="date"]::-webkit-calendar-picker-indicator,
.form-control[type="time"]::-webkit-calendar-picker-indicator {
  filter: invert(0.75);
  opacity: 0.8;
  cursor: pointer;
  border-radius: var(--radius-sm);
  padding: 2px;
}

.form-control[type="datetime-local"]::-webkit-calendar-picker-indicator:hover,
.form-control[type="date"]::-webkit-calendar-picker-indicator:hover,
.form-control[type="time"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1;
  background: var(--color-gold-subtle);
}

.form-control::placeholder {
  color: var(--color-text-muted);
}

/* iOS Safari auto-zooms any focused input below 16px, wrecking the layout.
   Floor input font-size on touch phones only — desktop keeps its density.
   (Breakpoint convention: variables.css / docs/agents/azimuth/fe.md.) */
@media (pointer: coarse) and (max-width: 640px) {
  .form-control,
  .search-page-input {
    font-size: var(--touch-input-font-size);
  }
}

.inventory-template-suggestion-field {
  position: relative;
}

.inventory-template-suggestion-list {
  position: absolute;
  top: calc(100% + 0.4rem);
  left: 0;
  right: 0;
  z-index: 20;
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-md);
  background: var(--color-ocean-deep);
  box-shadow: var(--shadow-card);
  max-height: 14rem;
  overflow-y: auto;
}

.inventory-template-suggestion-loading {
  padding: 0.6rem 0.75rem;
  color: var(--color-text-muted);
  font-size: 0.8rem;
}

.inventory-template-suggestion-item {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  text-align: left;
  padding: 0.55rem 0.75rem;
  border: none;
  border-bottom: 1px solid var(--color-border);
  background: transparent;
  color: var(--color-text-primary);
  cursor: pointer;
}

.inventory-template-suggestion-item:last-child {
  border-bottom: none;
}

.inventory-template-suggestion-item:hover {
  background: var(--color-ocean-surface);
}

.inventory-template-suggestion-item-name {
  font-weight: 600;
}

.inventory-template-suggestion-item-meta {
  color: var(--color-text-muted);
  font-size: 0.75rem;
}

textarea.form-control {
  resize: vertical;
  min-height: 80px;
  font-family: inherit;
}

select.form-control {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%234e6a8a'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  padding-right: 2rem;
}

select.form-control option {
  background: var(--color-ocean-mid);
  color: var(--color-text-primary);
}

.form-fieldset {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 1rem 1.25rem;
  margin-bottom: 1rem;
}

.form-legend {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-gold);
  padding: 0 0.5rem;
}

.form-static-value {
  padding: 0.5rem 0.75rem;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  font-size: 0.9rem;
  min-height: 2.25rem;
  display: flex;
  align-items: center;
}

.link-entry {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.5rem;
}

.link-entry .form-control {
  flex: 1;
}

/* Required-inventory editor rows in the component edit modal: item select grows, quantity + unit
   stay compact, delete button sits at the end. The inner .form-group wrappers carry the margin the
   single-line layout doesn't want, so they're flattened here. */
.component-inventory-item-row {
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
  margin-bottom: 0.5rem;
}

.component-inventory-item-row .form-group {
  margin-bottom: 0;
}

.component-inventory-item-row .form-group:first-child {
  flex: 1;
}

.component-inventory-item-row .form-group:nth-child(2) {
  width: 6rem;
}

.component-inventory-item-row .form-group:nth-child(3) {
  width: 9rem;
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 0.75rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-border);
  margin-top: 1rem;
}

/* ── Admin detail actions (e.g. per-vessel search reindex) ────── */
.detail-admin-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.75rem;
  padding-top: 1rem;
  margin-top: 1rem;
  border-top: 1px solid var(--color-border);
}

.detail-admin-action-hint {
  font-size: 0.85rem;
  color: var(--color-text-secondary);
}

.detail-admin-action-hint.text-error {
  color: var(--color-danger);
}


/* ── Fieldset variant for execution notes ────────────────────── */
.form-fieldset-execution {
  border-color: rgba(122, 184, 232, 0.3);
}

.form-fieldset-execution .form-legend {
  color: #7ab8e8;
}

/* ── Form hint ──────────────────────────────────────────────── */
.form-hint {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.78rem;
  color: var(--color-text-muted);
  line-height: 1.4;
}

/* ── Custom checkbox ─────────────────────────────────────────
   Applied globally to all input[type="checkbox"] elements so
   every checkbox in the app — event-modal row includes,
   accordion includes, component measurement-type pickers, and
   any other ad-hoc checkbox — shares a consistent gold-accented
   dark-theme appearance. No HTML changes required.

   Exceptions that hide the native input behind a custom
   indicator span (e.g. .checklist-checkbox, .drive-checkbox)
   are unaffected because those inputs have opacity:0 and the
   visual rendering is delegated entirely to the sibling span.
   ──────────────────────────────────────────────────────────── */
input[type="checkbox"] {
  -webkit-appearance: none;
  appearance: none;
  display: inline-block;
  width: 1.05rem;
  height: 1.05rem;
  flex-shrink: 0;
  border: 1.5px solid var(--color-border);
  border-radius: 0.25rem;
  background: var(--color-ocean-mid);
  vertical-align: middle;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), box-shadow var(--transition);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 72%;
}

input[type="checkbox"]:hover {
  border-color: var(--color-border-gold);
  background-color: var(--color-ocean-surface);
}

input[type="checkbox"]:checked {
  background-color: var(--color-gold-subtle);
  border-color: var(--color-gold);
  /* SVG checkmark — stroke colour matches --color-gold (#c9a84c).
     The day theme redefines --color-gold but we embed the dark-theme
     hex directly here; the day-theme override block below swaps it. */
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2.5 6l2.8 2.8 4.2-4.8' stroke='%23c9a84c' stroke-width='1.8' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

input[type="checkbox"]:focus-visible {
  outline: 2px solid var(--color-gold);
  outline-offset: 2px;
}

input[type="checkbox"]:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}


.checkbox-label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--color-text-primary);
}

.checkbox-label input[type="checkbox"] {
  margin: 0;
}

/** stylesheets/src/tabs.css **/
/* ── Vertical nav rail (formerly horizontal view tabs) ───────────
   The rail lives on the left, under the sticky top navbar, and grows the
   content area to its right. Expanded shows icon + label; collapsed
   (html[data-nav-rail="collapsed"]) shows icon only at a narrower width.
   Rail width is driven by the --nav-rail-width-* variables so home.js can
   read the active width for dashboard canvas sizing. */
.view-tabs {
  flex: 0 0 var(--nav-rail-active-width);
  width: var(--nav-rail-active-width);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.75rem 0.5rem;
  box-sizing: border-box;
  background: var(--color-ocean-deep);
  border-right: 1px solid var(--color-border);
  position: sticky;
  top: var(--navbar-total-height);
  /* dvh keeps the rail sized to the real visible viewport as mobile browser
     chrome shows/hides; the vh line is the older-browser fallback. */
  height: calc(100vh - var(--navbar-total-height));
  height: calc(100dvh - var(--navbar-total-height));
  overflow-y: auto;
  overflow-x: hidden;
  transition: flex-basis var(--transition), width var(--transition);
}

.nav-rail-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 40px;
  margin-bottom: 0.5rem;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: color var(--transition), background var(--transition);
}

.nav-rail-toggle:hover {
  color: var(--color-text-primary);
  background: var(--color-gold-subtle);
}

.nav-rail-toggle-icon {
  font-size: 1.5rem;
  line-height: 1;
}

/* ── Main-vessel image (sits between the toggle and the view tabs) ── */
.nav-rail-vessel-image {
  display: flex;
  justify-content: center;
  margin-bottom: 0.5rem;
}

.nav-rail-vessel-image-thumbnail {
  width: 100%;
  /* Landscape 4:3 — boat photos read better wide than square. Must match the
     fetch dimensions in constants.js (NAV_RAIL_VESSEL_IMAGE_FETCH_*_PX). */
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  cursor: pointer;
  transition: width var(--transition), border-color var(--transition), opacity var(--transition);
}

.nav-rail-vessel-image-thumbnail:hover {
  border-color: var(--color-gold);
  opacity: 0.9;
}

.view-tab {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.85rem;
  padding: 0.6rem 0.85rem;
  background: transparent;
  border: none;
  border-left: 3px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  font-size: 0.9rem;
  font-weight: 500;
  cursor: pointer;
  letter-spacing: 0.04em;
  text-align: left;
  white-space: nowrap;
  transition: color var(--transition), background var(--transition), border-color var(--transition);
}

.view-tab-icon {
  font-size: 1.5rem;
  line-height: 1;
  flex: 0 0 auto;
}

.view-tab-label {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  overflow: hidden;
  text-overflow: ellipsis;
}

.view-tab:hover {
  color: var(--color-text-primary);
  background: var(--color-gold-subtle);
}

.view-tab-active {
  color: var(--color-gold-light);
  border-left-color: var(--color-gold);
  background: var(--color-gold-subtle);
  font-weight: 600;
}

/* Scale the badge down slightly so it sits neatly inside the tab label */
.view-tab-unread-badge {
  font-size: 0.6rem;
  min-width: 1.1rem;
  height: 1.1rem;
}

/* ── Collapsed rail: icon-only ──────────────────────────────────── */
:root[data-nav-rail="collapsed"] .view-tabs {
  padding-left: 0.4rem;
  padding-right: 0.4rem;
}

:root[data-nav-rail="collapsed"] .view-tab {
  justify-content: center;
  gap: 0;
  padding-left: 0;
  padding-right: 0;
}

:root[data-nav-rail="collapsed"] .view-tab-label {
  display: none;
}

:root[data-nav-rail="collapsed"] .nav-rail-vessel-image-thumbnail {
  width: var(--nav-rail-vessel-image-width-collapsed);
}

/* ── Phone rail collapse (breakpoint convention: variables.css) ──
   Desktop-hidden floating handle; the phone media block below reveals it while
   the rail is collapsed. Must precede that block (equal specificity — last
   declaration wins). */
.nav-rail-phone-expand {
  display: none;
}

@media (max-width: 640px) {
  /* On phones the two rail states are: expanded = icon-only 64px rail
     (layout.css forces the icon-only presentation at this breakpoint), and
     collapsed = GONE — 0px, display none — so pages like the component
     hierarchy get the full viewport width. The floating edge handle
     (.nav-rail-phone-expand, rendered in viewTabs.scala.html outside the
     rail) is then the only way back. The attribute selector outranks the
     `:root` width override in layout.css, so state still wins. */
  :root[data-nav-rail="collapsed"] {
    --nav-rail-active-width: 0px;
  }

  :root[data-nav-rail="collapsed"] .view-tabs {
    display: none;
  }

  .nav-rail-phone-expand {
    position: fixed;
    left: 0;
    bottom: calc(6rem + env(safe-area-inset-bottom, 0px));
    /* Above sticky page chrome (navbar z 100), below the modal stack (1000+)
       and the tap-tap armed banner (3000). */
    z-index: 300;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: var(--touch-target-minimum-size);
    padding: 0;
    background: var(--color-ocean-deep);
    border: 1px solid var(--color-border-gold);
    border-left: none;
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    box-shadow: var(--shadow-card);
    color: var(--color-text-secondary);
    font-size: 1.15rem;
    cursor: pointer;
  }
}

/** stylesheets/src/tasks.css **/

/* ── Task status badges ──────────────────────────────────────── */
.status-badge {
  display: inline-block;
  padding: 0.18em 0.55em;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.status-badge.status-created {
  background: rgba(76, 175, 80, 0.15);
  color: #81c784;
  border: 1px solid rgba(76, 175, 80, 0.35);
}

.status-badge.status-warn {
  background: rgba(255, 193, 7, 0.15);
  color: #ffd54f;
  border: 1px solid rgba(255, 193, 7, 0.35);
}

.status-badge.status-due {
  background: rgba(255, 152, 0, 0.15);
  color: #ffb74d;
  border: 1px solid rgba(255, 152, 0, 0.35);
}

.status-badge.status-late {
  background: rgba(239, 83, 80, 0.15);
  color: #ef9a9a;
  border: 1px solid rgba(239, 83, 80, 0.35);
}

/* ── Task progress badges ────────────────────────────────────── */
.progress-badge {
  display: inline-block;
  padding: 0.18em 0.55em;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.progress-badge.progress-unstarted {
  background: rgba(255, 255, 255, 0.04);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

.progress-badge.progress-started {
  background: rgba(122, 184, 232, 0.15);
  color: #7ab8e8;
  border: 1px solid rgba(122, 184, 232, 0.35);
}

.progress-badge.progress-dismissed {
  background: rgba(78, 106, 138, 0.12);
  color: var(--color-text-secondary);
  border: 1px solid var(--color-border);
}

.progress-badge.progress-complete {
  background: rgba(76, 175, 80, 0.15);
  color: #81c784;
  border: 1px solid rgba(76, 175, 80, 0.35);
}

/* ── Task row left-border status accent ──────────────────────── */
.task-row {
  cursor: pointer;
}

.task-row.status-created {
  border-left: 3px solid #4caf50;
}

.task-row.status-warn {
  border-left: 3px solid #ffd54f;
}

.task-row.status-due {
  border-left: 3px solid #ff9800;
}

.task-row.status-late {
  border-left: 3px solid #ef5350;
}

/* ── Breadcrumb ──────────────────────────────────────────────── */
.breadcrumb {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  font-size: 0.875rem;
}

.breadcrumb-back {
  background: none;
  border: none;
  color: var(--color-gold-light);
  cursor: pointer;
  font-size: 0.875rem;
  padding: 0;
}

.breadcrumb-back:hover {
  color: var(--color-gold);
  text-decoration: underline;
}

.breadcrumb-sep {
  color: var(--color-text-muted);
}

.breadcrumb-current {
  color: var(--color-text-primary);
  font-weight: 500;
}

/* ── Schedule active / inactive badges ───────────────────────── */
.schedule-active-badge {
  display: inline-block;
  padding: 0.18em 0.55em;
  background: rgba(76, 175, 80, 0.15);
  color: #81c784;
  border: 1px solid rgba(76, 175, 80, 0.35);
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

.schedule-inactive-badge {
  display: inline-block;
  padding: 0.18em 0.55em;
  background: rgba(78, 106, 138, 0.1);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

/* ── Show-inactive toggle ────────────────────────────────────── */
.show-inactive-toggle {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  cursor: pointer;
  margin-left: auto;
  user-select: none;
}

.show-inactive-toggle input[type="checkbox"] {
  cursor: pointer;
}

/* ── Work items inline panel ─────────────────────────────────── */
.work-items-cell {
  padding: 0 !important;
  background: var(--color-ocean-deep) !important;
  border-left: none !important;
}

.work-items-panel {
  padding: 1.25rem 1.5rem 1rem;
  border-top: 2px solid var(--color-gold-dark);
  border-bottom: 1px solid var(--color-border);
}

.work-items-panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 1rem;
  gap: 1rem;
}

.work-items-panel-title {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text-primary);
}

.work-items-panel-description {
  font-size: 0.85rem;
  color: var(--color-text-secondary);
  margin-top: 0.2rem;
  line-height: 1.5;
}

.work-items-panel-actions {
  display: flex;
  gap: 0.5rem;
  flex-shrink: 0;
  align-items: flex-start;
}

.work-items-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.work-item {
  background: var(--color-ocean-mid);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.7rem 1rem;
}

.work-item-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.work-item-progress-btn,
.work-item-progress-indicator {
  font-size: 1.2rem;
  line-height: 1;
  flex-shrink: 0;
}

.work-item-progress-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: transform var(--transition), color var(--transition);
}

.work-item-progress-indicator {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.2rem;
}

.work-item-progress-btn:hover {
  transform: scale(1.25);
}

.work-item-progress-btn.progress-unstarted,
.work-item-progress-indicator.progress-unstarted {
  color: var(--color-text-muted);
}

.work-item-progress-btn.progress-started,
.work-item-progress-indicator.progress-started {
  color: #7ab8e8;
}

.work-item-progress-btn.progress-complete,
.work-item-progress-indicator.progress-complete {
  color: #81c784;
}

.work-item-title-text {
  flex: 1;
  font-size: 0.9rem;
  color: var(--color-text-primary);
}

.work-item-title-text.complete {
  text-decoration: line-through;
  color: var(--color-text-muted);
}

.component-tag {
  display: inline-block;
  padding: 0.12em 0.5em;
  background: var(--color-gold-subtle);
  border: 1px solid var(--color-border-gold);
  border-radius: 20px;
  color: var(--color-gold-light);
  font-size: 0.7rem;
  white-space: nowrap;
}

/* ── Work item template / execution detail sections ──────────── */
.work-item-template-section {
  margin-top: 0.65rem;
  padding: 0.65rem 0.85rem;
  background: rgba(201, 168, 76, 0.05);
  border: 1px solid rgba(201, 168, 76, 0.2);
  border-radius: var(--radius-sm);
}

.work-item-execution-section {
  margin-top: 0.5rem;
  padding: 0.65rem 0.85rem;
  background: rgba(122, 184, 232, 0.05);
  border: 1px solid rgba(122, 184, 232, 0.2);
  border-radius: var(--radius-sm);
}

.work-item-section-label {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin-bottom: 0.5rem;
}

.template-section-label {
  color: var(--color-gold-dark);
}

.execution-section-label {
  color: #5a9bc0;
}

.work-item-detail-row {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.35rem;
  font-size: 0.83rem;
}

.work-item-detail-label {
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--color-text-muted);
  min-width: 85px;
  margin-top: 0.1rem;
  flex-shrink: 0;
}

.work-item-detail-value {
  color: var(--color-text-secondary);
  flex: 1;
  word-break: break-word;
}

.parts-tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  flex: 1;
}

.part-tag {
  display: inline-block;
  padding: 0.12em 0.45em;
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 0.73rem;
  color: var(--color-text-secondary);
}

.work-items-empty-state {
  padding: 1rem;
  text-align: center;
  color: var(--color-text-muted);
  font-size: 0.875rem;
}

.work-item-inline-form {
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-md);
  padding: 1rem;
  margin-top: 0.75rem;
}

.add-work-item-row {
  margin-top: 0.75rem;
}

/* ── Work item work log inline section ──────────────────────── */
.work-item-work-log-section {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--color-border);
}


/** stylesheets/src/images.css **/
/* ── Image Thumbnail Strip (edit modal) ─────────────────────── */
.image-thumbnail-strip {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.75rem;
}

.image-thumbnail-entry {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  width: 100px;
}

.image-thumbnail-container {
  position: relative;
  width: 80px;
  height: 80px;
}

.image-thumbnail {
  width: 80px;
  height: 80px;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
}

.image-thumbnail-remove {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 18px;
  height: 18px;
  padding: 0;
  font-size: 10px;
  border-radius: 50%;
  background: var(--color-danger);
  border: none;
  color: #fff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* Deliberate exception to the 44px .btn-icon touch floor (buttons.css): a
   44px circle would cover half the 80px thumbnail. 28px keeps the badge
   proportionate; the corner position keeps it clear of the nudge buttons. */
@media (pointer: coarse) {
  .image-thumbnail-remove {
    min-width: 0;
    min-height: 0;
    width: 28px;
    height: 28px;
    font-size: 13px;
  }
}

.image-thumbnail-description {
  font-size: 0.75rem;
  padding: 0.2rem 0.4rem;
  width: 100%;
  min-width: 0;
}

/* ── Image Upload Section (edit modal) ───────────────────────── */
/* Compact 3-button image-upload affordance. Every upload site across the app collapses to
   the same layout:
     [file-picker icon] [camera icon] [clipboard icon]   …status text…
   The native `<input type="file">` elements are kept in the DOM (still the actual file
   targets) but visually hidden via `.sr-only`; each visible icon-button calls
   `app.triggerHiddenFileInputById('<inputId>')` to programmatically open the native picker. */
.image-upload-section {
  margin-top: 0.5rem;
}

.image-upload-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

/* Shared chrome for all three buttons in the row — gold border, ghost background, sized so
   the row stays slim on a single line. Used as a modifier alongside `.btn .btn-ghost` so the
   base button styling (disabled state, focus ring, etc.) is inherited. */
.image-upload-icon-btn {
  flex-shrink: 0;
  font-size: 1.1rem;
  padding: 0.25rem 0.5rem;
  line-height: 1;
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-sm);
  color: var(--color-gold);
  background: transparent;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}

.image-upload-icon-btn:hover:not(:disabled) {
  background: var(--color-gold-subtle);
}

.image-upload-icon-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.image-upload-status {
  margin-top: 0.4rem;
}

.upload-success {
  color: var(--color-success);
  font-size: 0.85rem;
}

.upload-error {
  color: var(--color-danger);
  font-size: 0.85rem;
}

/* ── Screen-reader-only / visually hidden ────────────────────── */
.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;
}

.image-upload-status-warning {
  margin-top: 0.35rem;
}

.upload-warning {
  color: var(--color-gold);
  font-size: 0.85rem;
}

/* ── Paperclip popover variant ─────────────────────────────────
   Compact alternative to the inline 3-button row. Used by the checklist
   run row (and any other future row that needs the image upload to
   collapse into a single icon-button to save horizontal space). The
   paperclip-anchor wraps the trigger button + an absolutely-positioned
   popover panel that holds the file / camera / clipboard menu items.
   Visual values mirror the legacy `.checklist-run-item-popover*` rules
   so existing layouts stay unchanged while the partial decouples from
   checklist-specific class names. */
.image-upload-paperclip-anchor {
  position: relative;
  display: inline-flex;
}

.image-upload-popover {
  position: absolute;
  top: calc(100% + 0.25rem);
  right: 0;
  z-index: 20;
  min-width: 12rem;
  max-width: 18rem;
  padding: 0.4rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card);
}

.image-upload-popover-action {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.4rem 0.6rem;
  font-size: 0.85rem;
  color: var(--color-text-primary);
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-align: left;
}

.image-upload-popover-action:hover {
  background: var(--color-ocean-surface);
  color: var(--color-gold-light);
}

.inventory-image-entry {
  display: grid;
  grid-template-columns: 1fr 1fr auto auto;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.5rem;
}

.inventory-image-preview {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.inventory-image-preview .image-thumbnail {
  cursor: pointer;
}

/* ── Profile Image Upload (account menu) ──────────────────────── */
.profile-image-upload-section {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.profile-image-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}

.profile-image-preview-img {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--color-border-gold);
}

/* Note: the profile-modal upload row used to carry its own
   `.profile-image-upload-row` class for tighter spacing; now that profile
   shares the unified `imageUploadControls` partial, the `.image-upload-row`
   styles apply directly and the override has been removed. */

/* The old `.account-menu-trigger-with-image` block (a 38×38 circular button
   with its own border/background) used to live here. The new navbar treats the
   avatar circle, the name/title text, and the caret as visually independent
   children of a chromeless trigger button — see `navbar.css`
   `.account-menu-trigger` / `.account-menu-avatar`. That block was forcing the
   whole trigger to 38px round, which clipped the name and title to zero width
   whenever a profile image was set. Deleting it (rather than overriding it in
   navbar.css) keeps a single source of truth for the trigger's geometry. */

/* ── Image Carousel (detail modal) ───────────────────────────── */
.image-carousel {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}

.image-carousel-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.4rem;
  max-width: 200px;
}

.image-carousel-thumbnail {
  width: 200px;
  height: 200px;
  object-fit: cover;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  cursor: pointer;
  transition: border-color var(--transition), opacity var(--transition);
}

.image-carousel-thumbnail:hover {
  border-color: var(--color-gold);
  opacity: 0.9;
}

.image-carousel-description {
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  text-align: center;
  word-break: break-word;
}

/* ── Lightbox Overlay ─────────────────────────────────────────── */
/* Transparent positioning layer; the shared `.modal-shared-backdrop` paints the dimming and
   the modalStack directive assigns the z-index in open order (so a lightbox opened over a
   detail modal stacks correctly without compounding the backdrop). */
.lightbox-overlay {
  position: fixed;
  inset: 0;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.lightbox-content {
  position: relative;
  max-width: 90vw;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
}

.lightbox-close {
  position: absolute;
  top: -1rem;
  right: -1rem;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text-primary);
  font-size: 1.2rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}

.lightbox-close:hover {
  background: var(--color-ocean-light);
  color: var(--color-gold);
}

.lightbox-counter {
  color: rgba(255, 255, 255, 0.65);
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  align-self: center;
}

/* Wrapper is position:relative so the half-image nav zones can be placed
   absolutely over the left and right halves of the image. */
.lightbox-image-wrapper {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  user-select: none;
}

.lightbox-image {
  max-width: 90vw;
  max-height: 80vh;
  object-fit: contain;
  border-radius: var(--radius-md);
  display: block;
}

/* Each nav zone covers exactly one half of the image area. A pointer cursor
   indicates they are clickable; no background so the image shows through. */
.lightbox-nav-zone {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  cursor: pointer;
  z-index: 1;
}

.lightbox-nav-prev {
  left: 0;
}

.lightbox-nav-next {
  right: 0;
}

.lightbox-description {
  color: rgba(255, 255, 255, 0.75);
  font-size: 0.9rem;
  text-align: center;
  max-width: min(90vw, 700px);
  padding: 0 1rem;
  line-height: 1.5;
}


/** stylesheets/src/users.css **/
/* ===== ROLE UI ===== */
.role-badge-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.role-badge {
  display: inline-flex;
  align-items: center;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  border: 1px solid var(--color-border-gold);
  background: var(--color-gold-subtle);
  color: var(--color-gold-light);
  font-size: 0.74rem;
  letter-spacing: 0.03em;
  text-transform: lowercase;
}

.role-chip-selector {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0.5rem;
}

.role-chip-option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  min-height: 36px;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-ocean-deep);
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: border-color var(--transition), background var(--transition), color var(--transition), box-shadow var(--transition);
}

.role-chip-option:hover {
  border-color: var(--color-border-gold);
  color: var(--color-gold-light);
}

.role-chip-option-selected {
  border-color: var(--color-border-gold);
  background: rgba(201, 168, 76, 0.2);
  color: var(--color-gold-light);
  box-shadow: 0 0 0 1px rgba(201, 168, 76, 0.2);
}

.role-chip-check {
  font-size: 0.75rem;
}

.role-chip-label {
  text-transform: lowercase;
  letter-spacing: 0.03em;
}

.permission-assignment-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}

.permission-assignment-add-button,
.permission-assignment-remove-button {
  flex-shrink: 0;
}

.permission-assignment-empty {
  color: var(--color-text-muted);
  font-size: 0.85rem;
}

.permission-assignment-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.permission-assignment-row {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: center;
}

.permission-assignment-summary-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.permission-assignment-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: rgba(5, 13, 26, 0.22);
}

.permission-assignment-summary-name {
  color: var(--color-text-primary);
  font-size: 0.85rem;
}


/** stylesheets/src/auth.css **/
/* ===== AUTH OVERLAY ===== */
.auth-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.65);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1200;
}

.auth-modal {
  width: 100%;
  max-width: 420px;
  background: var(--color-ocean-mid);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-modal);
  padding: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.auth-modal-title {
  text-align: center;
  color: var(--color-gold-light);
  margin-bottom: 0.5rem;
}

.auth-error {
  background: var(--color-danger-light);
  border: 1px solid var(--color-danger);
  color: #f1a39e;
  border-radius: var(--radius-sm);
  padding: 0.5rem 0.75rem;
}

/* Pre-release welcome / contact block shown at the top of the signup
   modal only (see app/views/auth/overlay.scala.html). Uses the same
   gold-on-ocean palette as the surrounding auth modal so it reads as a
   first-class element of the form, not an injected banner. */
.auth-welcome {
  background: var(--color-gold-subtle);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-sm);
  padding: 0.75rem 1rem;
  color: var(--color-gold-light);
  font-size: 0.9rem;
  line-height: 1.4;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.auth-welcome p {
  margin: 0;
}

.auth-welcome-heading {
  font-weight: 600;
  color: var(--color-gold-light);
}

.auth-welcome-link {
  color: var(--color-gold-light);
  text-decoration: underline;
}

/** stylesheets/src/work-log.css **/
/* ── Work Log entries ───────────────────────────────────────── */
.work-log-entries-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.work-log-entry {
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.65rem 0.85rem;
}

.work-log-entry-header {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.work-log-entry-times {
  display: flex;
  gap: 0.75rem;
  flex: 1;
  flex-wrap: wrap;
  min-width: 0;
}

.work-log-entry-time {
  font-size: 0.8rem;
  color: var(--color-text-secondary);
  white-space: nowrap;
}

.work-log-entry-time-label {
  color: var(--color-text-muted);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.work-log-entry-actions {
  display: flex;
  gap: 0.2rem;
  margin-left: auto;
  flex-shrink: 0;
}

.work-log-entry-notes {
  margin-top: 0.45rem;
  font-size: 0.875rem;
  color: var(--color-text-secondary);
  line-height: 1.5;
}

.work-log-entry-inline-form {
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border-gold);
  border-radius: var(--radius-md);
  padding: 0.85rem 1rem;
  margin-top: 0.5rem;
}

.work-log-add-row {
  margin-bottom: 0.5rem;
}

.work-log-toggle-btn {
  margin-top: 0.5rem;
  font-size: 0.75rem;
  padding: 0.2rem 0.6rem;
  min-height: 26px;
}

/* ── Work log status badges ─────────────────────────────────── */
.work-log-status-badge {
  display: inline-block;
  padding: 0.18em 0.55em;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  flex-shrink: 0;
}

.work-log-status-badge.work-log-status-unstarted {
  background: rgba(255, 255, 255, 0.04);
  color: var(--color-text-muted);
  border: 1px solid var(--color-border);
}

.work-log-status-badge.work-log-status-started {
  background: rgba(122, 184, 232, 0.15);
  color: #7ab8e8;
  border: 1px solid rgba(122, 184, 232, 0.35);
}

.work-log-status-badge.work-log-status-completed {
  background: rgba(76, 175, 80, 0.15);
  color: #81c784;
  border: 1px solid rgba(76, 175, 80, 0.35);
}


/** stylesheets/src/onboarding.css **/
/* ── Onboarding UI ───────────────────────────────────────────── */
.onboarding-layout {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 1rem;
}

.onboarding-chat-panel,
.onboarding-tree-panel {
  background: var(--color-ocean-mid);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: 1rem;
}

.onboarding-start-help {
  color: var(--color-text-secondary);
  margin-bottom: 1rem;
}

.onboarding-start-row {
  margin-bottom: 0.75rem;
}

.onboarding-chat-card {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.onboarding-chat-toolbar {
  display: flex;
  justify-content: flex-end;
}

.onboarding-audio-toggle-button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-ocean-deep);
  color: var(--color-text-secondary);
  padding: 0.32rem 0.6rem;
  font-size: 0.8rem;
  cursor: pointer;
  transition: border-color var(--transition), background var(--transition), color var(--transition);
}

.onboarding-audio-toggle-button-enabled {
  color: #7dcc88;
  border-color: rgba(125, 204, 136, 0.45);
  background: rgba(26, 138, 90, 0.22);
}

.onboarding-audio-toggle-button-disabled {
  color: var(--color-text-muted);
  border-color: var(--color-border);
  background: rgba(78, 106, 138, 0.12);
}

.onboarding-audio-toggle-button:hover {
  border-color: var(--color-border-gold);
}

.onboarding-audio-toggle-icon {
  font-size: 0.95rem;
  line-height: 1;
}

.onboarding-messages {
  max-height: 460px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding-right: 0.25rem;
}

.onboarding-message {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.6rem 0.75rem;
  background: var(--color-ocean-surface);
}

.onboarding-message-user {
  border-color: rgba(122, 184, 232, 0.4);
}

.onboarding-message-agent {
  border-color: rgba(201, 168, 76, 0.35);
}

.onboarding-message-role {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-muted);
  margin-bottom: 0.3rem;
}

.onboarding-message-text {
  color: var(--color-text-primary);
}

.onboarding-message-media {
  margin-top: 0.4rem;
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.onboarding-message-image-carousel {
  gap: 0.4rem;
}

.onboarding-message-image-carousel .image-carousel-item {
  max-width: 90px;
}

.onboarding-message-image-carousel .image-carousel-thumbnail {
  width: 90px;
  height: 90px;
}

.onboarding-message-audio-play-button {
  padding: 0.22rem 0.6rem;
  min-height: 1.65rem;
  font-size: 0.78rem;
}

.onboarding-composer {
  border-top: 1px solid var(--color-border);
  padding-top: 0.75rem;
}

.onboarding-upload-row {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.5rem;
}

.onboarding-audio-controls {
  margin-bottom: 0.75rem;
}

.onboarding-audio-instruction {
  color: var(--color-text-secondary);
  font-size: 0.82rem;
  margin-bottom: 0.45rem;
}

.onboarding-audio-control-row {
  flex-wrap: wrap;
}

.onboarding-hold-record-button {
  min-width: 130px;
}

.onboarding-recording-indicator {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  color: #f1a39e;
  font-size: 0.82rem;
  margin-bottom: 0.5rem;
}

.onboarding-recording-dot {
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  background: #ef5350;
  box-shadow: 0 0 0 0 rgba(239, 83, 80, 0.6);
  animation: onboardingRecordPulse 1s ease-out infinite;
}

@keyframes onboardingRecordPulse {
  0% {
    box-shadow: 0 0 0 0 rgba(239, 83, 80, 0.6);
  }
  100% {
    box-shadow: 0 0 0 0.55rem rgba(239, 83, 80, 0);
  }
}

.onboarding-audio-review {
  margin-bottom: 0.5rem;
}

.onboarding-auto-upload-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  color: var(--color-text-secondary);
  font-size: 0.8rem;
  cursor: pointer;
  user-select: none;
}

.onboarding-auto-upload-toggle input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  accent-color: var(--color-gold);
  cursor: pointer;
}

.onboarding-upload-status {
  color: var(--color-text-secondary);
  font-size: 0.82rem;
  margin-bottom: 0.5rem;
}

.onboarding-actions {
  margin-top: 0.5rem;
}

.onboarding-tree-title {
  color: var(--color-gold-light);
  margin-bottom: 0.75rem;
  font-size: 0.95rem;
}

.onboarding-tree-list {
  margin-left: 1rem;
}

.onboarding-tree-node-label {
  margin-bottom: 0.3rem;
}

.onboarding-tree-node-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.onboarding-tree-node-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  margin-top: 0.35rem;
}

.onboarding-tree-node-fact {
  font-size: 0.76rem;
  color: var(--color-text-secondary);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  padding: 0.16rem 0.45rem;
}

.onboarding-tree-node-description {
  margin-top: 0.4rem;
  font-size: 0.82rem;
  color: var(--color-text-primary);
  white-space: pre-line;
}

.onboarding-tree-placeholder {
  opacity: 0.8;
  border-style: dashed;
}

/* Tablet breakpoint (convention: variables.css — migrated from a stray 980px):
   the two-pane conversation + tree preview needs real width, so it collapses
   to one column for anything narrower than a landscape tablet. */
@media (max-width: 1024px) {
  .onboarding-layout {
    grid-template-columns: 1fr;
  }
}


/** stylesheets/src/checklists.css **/
/* ── Checklists ──────────────────────────────────────────────── */
.checklist-root-filter {
  max-width: 420px;
  margin-bottom: 1rem;
}

.checklist-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 1rem;
}

.checklist-panel {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-ocean-deep);
  padding: 1rem;
}

.checklist-panel-header {
  margin-bottom: 0.75rem;
}

.checklist-list {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.checklist-list-entry {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.75rem;
  background: var(--color-ocean-mid);
}

.checklist-list-entry-actions {
  margin-top: 0.5rem;
  display: flex;
  gap: 0.5rem;
}

.checklist-template-modal,
.checklist-run-modal {
  max-width: 980px;
}

.checklist-run-item {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.65rem;
  margin-bottom: 0.4rem;
}

/* ── Checklist template item rows (create / edit modal) ──────────────────────
 * Condensed layout: each item packs into as little vertical space as possible.
 * Alternating backgrounds plus a gold left-accent make the boundary between
 * one item and the next obvious at a glance. */
.checklist-template-item-row {
  border: 1px solid var(--color-border);
  border-left: 3px solid var(--color-border-gold);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.6rem;
  margin-bottom: 0.6rem;
  background: var(--color-ocean-deepest);
}

.checklist-template-item-row:nth-of-type(even) {
  background: var(--color-ocean-mid);
}

.checklist-template-item-row .form-row {
  gap: 0.5rem;
  margin-bottom: 0;
  flex-wrap: wrap;
  align-items: flex-end;
}

.checklist-template-item-row .form-group {
  margin-bottom: 0.4rem;
  flex: 0 1 auto;
}

.checklist-template-item-row .form-label {
  margin-bottom: 0.15rem;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
}

.checklist-template-item-row .form-control {
  padding: 0.3rem 0.5rem;
  font-size: 0.8rem;
  line-height: 1.3;
}

.checklist-template-item-row select.form-control {
  padding-right: 1.5rem;
  background-position: right 0.45rem center;
}

/* Field-width tokens — keep each control only as wide as its content needs. */
.checklist-template-item-field-grow {
  flex: 1 1 12rem;
  min-width: 10rem;
}

.checklist-template-item-field-md {
  flex: 0 1 12rem;
}

.checklist-template-item-field-sm {
  flex: 0 1 9rem;
}

.checklist-template-item-field-sort {
  flex: 0 0 3rem;
}

.checklist-template-item-row-description {
  flex: 2 1 18rem;
  min-width: 14rem;
}

.checklist-template-item-row-options {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.checklist-template-item-auto-measurement-warning {
  margin: 0.3rem 0;
}

/* ── Single-row checklist run item layout ────────────────────────────────────
 * The badge cell and title cell have fixed widths so every row's title starts
 * at the same x position. The right-cluster (notes → attachment → status) is
 * pinned to the right via `margin-left: auto` on `.checklist-run-item-actions`.
 * Measurement / warning / thumbnails only render when relevant and flow in
 * between the title and the right-cluster.
 *
 * Column-width tokens — local to the checklist run row, not promoted to global
 * variables.css because nothing else in the app cares about them.
 */
.checklist-run-item-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.5rem;
  min-height: 1.85rem;
}

.checklist-run-item-title {
  /* Fixed-width title column → uniform left edge. Now a flex container
     to hold both the title text and the warning badge inline.
     align-items: baseline so the warning icon sits on the same baseline
     as the title text — feels like a glyph, not a stacked button. */
  flex: 0 0 16rem;
  width: 16rem;
  max-width: 16rem;
  display: inline-flex;
  align-items: baseline;
  gap: 0.25rem;
}

.checklist-run-item-title-text {
  font-weight: 500;
  font-size: 0.92rem;
  color: var(--color-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The warning badge is now inside the title container. Make it bigger. */
.checklist-run-item-warning {
  flex-shrink: 0;
}

/* ── Title leading icon ─────────────────────────────────────────────────────
 * Resolved at runtime from componentType + title keywords. Sits at the start
 * of the title cell and takes a fixed width so titles align across rows even
 * when icons differ. Critical items get a soft glow via drop-shadow. */
.checklist-run-item-title-icon {
  font-size: 1rem;
  width: 1.25rem;
  text-align: center;
  flex-shrink: 0;
  color: var(--color-text-secondary);
}

.checklist-run-item-title-icon-critical {
  filter: drop-shadow(0 0 0.25rem currentColor);
}

/* Tone classes — applied to .checklist-run-item-title-icon when the title text
 * matches a keyword. Color hierarchy (first match wins):
 *   port      → danger red
 *   starboard → success green
 *   fire      → warning orange
 *   fuel      → gold (matches the fuel tank semantics elsewhere in the app)
 *   water     → ocean blue
 *   battery   → warning yellow-ish
 */
.checklist-run-item-title-icon-tone-port      { color: var(--color-danger); }
.checklist-run-item-title-icon-tone-starboard { color: var(--color-success); }
.checklist-run-item-title-icon-tone-fire      { color: var(--color-warning); }
.checklist-run-item-title-icon-tone-fuel      { color: var(--color-gold-light); }
.checklist-run-item-title-icon-tone-water     { color: var(--color-ocean-accent, var(--color-info, #4aa3df)); }
.checklist-run-item-title-icon-tone-battery   { color: var(--color-warning); }

.checklist-run-item-badges {
  /* Fixed-width badge cell sized for up to 3 symmetrical FontAwesome icons.
     Math: 3 icons × 1rem + 2 gaps × 0.1rem = 3.2rem. */
  flex: 0 0 3.2rem;
  width: 3.2rem;
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.1rem;
}

.checklist-run-item-badges .badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  font-size: 0.65rem;
  font-weight: 600;
  line-height: 1;
  flex-shrink: 0;
}

.checklist-run-item-badges .badge-critical {
  background: var(--color-danger-light);
  color: var(--color-danger);
  border: 1px solid var(--color-danger);
}

.checklist-run-item-badges .badge-type-measurement {
  background: var(--color-gold-subtle);
  color: var(--color-gold-light);
  border: 1px solid var(--color-border-gold);
}

/* Badge icon — used by the warning triangle badge.
 *
 * Deliberately NOT wrapped in a flex container with explicit width/height: when an
 * inline-flex element has fixed dimensions its "baseline" becomes the bottom of the
 * box, which makes the icon float above the text it sits next to. By letting the
 * icon flow as a native inline element (just an <i> with a font-size) its baseline
 * follows the surrounding text glyph baseline. Combined with `align-items: baseline`
 * on the parent flex container, the icon sits like the next letter in the title.
 */
.checklist-run-item-badge-icon {
  display: inline-block;
  font-size: 1.05rem;
  line-height: 1;
  flex-shrink: 0;
}

.checklist-run-item-badge-icon-warning {
  color: var(--color-warning);
}

/* Status icon strip — one button per status; active gets tone-tinted background */
.checklist-run-item-status-strip {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  flex-shrink: 0;
}

.checklist-run-item-status-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.65rem;
  height: 1.65rem;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--color-text-muted);
  font-size: 0.95rem;
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}

.checklist-run-item-status-icon:hover {
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
}

.checklist-run-item-status-icon-active.checklist-run-item-status-tone-neutral {
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
  border-color: var(--color-border);
}

.checklist-run-item-status-icon-active.checklist-run-item-status-tone-success {
  background: var(--color-success-light);
  color: var(--color-success);
  border-color: var(--color-success);
}

.checklist-run-item-status-icon-active.checklist-run-item-status-tone-danger {
  background: var(--color-danger-light);
  color: var(--color-danger);
  border-color: var(--color-danger);
}

.checklist-run-item-status-icon-active.checklist-run-item-status-tone-warning {
  background: var(--color-warning-light);
  color: var(--color-warning);
  border-color: var(--color-warning);
}

.checklist-run-item-status-icon-active.checklist-run-item-status-tone-muted {
  background: var(--color-ocean-surface);
  color: var(--color-text-secondary);
  border-color: var(--color-border);
  opacity: 0.85;
}

/* Compact measurement value group */
.checklist-run-item-measurement {
  /* No auto margin here — the row uses .checklist-run-item-spacer to consume
     free space immediately after the title, which pushes the measurement (and
     the right-cluster after it) to the right edge of the row. */
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  flex-shrink: 0;
}

.checklist-run-item-value-group {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
}

.checklist-run-item-value-input {
  width: 5.5rem;
  height: 1.75rem;
  padding: 0.1rem 0.4rem;
  font-size: 0.85rem;
  text-align: right;
}

.checklist-run-item-value-input-narrow {
  width: 2.75rem;
  text-align: center;
}

.checklist-run-item-value-separator {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  margin: 0 0.05rem;
}

.checklist-run-item-unit-pill {
  /* Renders as plain text alongside the measurement value, not a pill. Reserves a fixed
     MIN width so the title column starts at the same x position across rows with no
     capacity, but lets the pill grow to accommodate the optional `/<capacity>` suffix
     (e.g. "gal/100") on tank rows without truncating it. Widest base abbreviation is
     "psi"/"gal"/"h:m" at 3 chars; the suffix appends up to a few more digits. */
  display: inline-flex;
  align-items: baseline;
  flex: 0 0 auto;
  min-width: 2.25rem;
  padding: 0 0.15rem;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--color-text-secondary);
  background: transparent;
  border: none;
  border-radius: 0;
  cursor: default;
  white-space: nowrap;
}

/* Capacity suffix on the unit pill, rendered slightly de-emphasized so the primary
   unit symbol still reads as the main label. */
.checklist-run-item-unit-pill-capacity {
  margin-left: 0.05rem;
  color: var(--color-text-muted);
  font-weight: 400;
}

/* Right-cluster: notes → attachment → status. `margin-left: auto` pins it to
 * the right edge so the status strip is always last regardless of what
 * (measurement / warning / thumbnails) renders before it. */
/* Right-cluster: notes → attachment → status. Sits flush against the measurement
 * (or the spacer / thumbnails when no measurement is present). The row's spacer
 * does the right-alignment work; this cluster carries no margin-left auto so it
 * always packs directly against whatever element precedes it. */
.checklist-run-item-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex-shrink: 0;
}

/* Flex spacer between the title and the measurement / right-cluster. Consumes
 * all free space so everything to its right is pinned to the row's right edge,
 * regardless of which optional pieces (thumbnails, measurement) are rendering.
 * Has zero intrinsic size so it doesn't add any visible gap. */
.checklist-run-item-spacer {
  flex: 1 1 auto;
  min-width: 0;
}

/* Visual divider between the notes/attachment pair and the status strip so the
 * status group reads as a distinct cluster from the meta-action icons. */
.checklist-run-item-actions .checklist-run-item-status-strip {
  margin-left: 0.25rem;
  padding-left: 0.4rem;
  border-left: 1px solid var(--color-border);
}

/* Notes button — dot indicator when notes exist */
.checklist-run-item-notes-trigger {
  position: relative;
}

.checklist-run-item-notes-trigger-active {
  color: var(--color-gold-light);
}

.checklist-run-item-notes-dot {
  position: absolute;
  top: 0.15rem;
  right: 0.15rem;
  width: 0.4rem;
  height: 0.4rem;
  background: var(--color-gold);
  border-radius: 50%;
}

/* Warning icon — orange triangle, inherits .alert-icon palette via direct color */
.checklist-run-item-warning {
  position: relative;
  display: inline-flex;
  align-items: center;
  /* The wrapper anchors the popover; it must not add any visual chrome of its own
     so the warning icon sits flush with the critical/measurement icons. */
  flex-shrink: 0;
}

.checklist-run-item-warning-trigger {
  /* Strip all native button chrome so this button looks identical to the plain
     <i> badge icons. The visible bounds come from the icon's own font-size.
     display: inline (not inline-flex) so the button's baseline IS the icon's
     glyph baseline — that's what makes it sit on the same baseline as text. */
  display: inline;
  padding: 0;
  margin: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  font: inherit;
}

.checklist-run-item-warning-trigger:hover .checklist-run-item-badge-icon-warning {
  filter: brightness(1.2);
}

/* Warning popover panel — anchored bottom-right of its trigger.
   Mirrors the geometry of `.image-upload-popover` (shared upload partial)
   but with a distinct warning palette (orange border / warning-light
   background) so the auto-measurement caution reads as advisory rather
   than as an action menu. The attachment popover lives in images.css now
   that it uses the shared `imageUploadPaperclipMenu` partial. */
.checklist-run-item-popover {
  position: absolute;
  top: calc(100% + 0.25rem);
  right: 0;
  z-index: 20;
  min-width: 12rem;
  max-width: 18rem;
  padding: 0.4rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card);
}

.checklist-run-item-warning-popover {
  border-color: var(--color-warning);
  background: var(--color-warning-light);
  max-width: 22rem;
}

.checklist-run-item-popover-text {
  margin: 0;
  font-size: 0.78rem;
  color: var(--color-warning-text);
  line-height: 1.35;
}

.checklist-run-item-error {
  margin-top: 0.4rem;
  margin-bottom: 0;
  font-size: 0.78rem;
  padding: 0.4rem 0.6rem;
}

/* ── Phone layout for run items (breakpoint convention: variables.css) ──
   The desktop single-line row wraps into two lines: full-width title on top,
   then measurement (left) + action cluster (right). The title un-truncates —
   on deck you must be able to read the whole item. The run modal itself goes
   full-screen via .modal-fullscreen-phone (layout.css). */
@media (max-width: 640px) {
  /* The 320px card minimum can exceed a padded phone viewport — one column. */
  .checklist-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .checklist-run-item-row {
    flex-wrap: wrap;
    row-gap: 0.35rem;
  }

  .checklist-run-item-title {
    flex: 1 1 100%;
    width: auto;
    max-width: none;
  }

  .checklist-run-item-title-text {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }

  .checklist-run-item-spacer {
    display: none;
  }

  .checklist-run-item-measurement {
    margin-right: auto;
  }

  .checklist-run-item-actions {
    margin-left: auto;
  }

  /* Template authoring rows: the width-token fields (md/sm/grow) stack
     full-width instead of wrapping into ragged partial rows. Authoring on a
     phone is accepted as functional-not-optimal (mobile-responsive.md). */
  .checklist-template-item-field-grow,
  .checklist-template-item-field-md,
  .checklist-template-item-field-sm,
  .checklist-template-item-row-description {
    flex: 1 1 100%;
    min-width: 0;
  }
}

/* Comfortable touch sizing for the per-item controls. Pointer-based (not
   width-based) so a tablet gets the same treatment. */
@media (pointer: coarse) {
  .checklist-run-item-status-icon {
    width: 2.2rem;
    height: 2.2rem;
    font-size: 1.05rem;
  }

  .checklist-run-item-value-input {
    height: 2.4rem;
  }
}

/* Inline clamp warning surfaced beneath the row when the user types a value that exceeds
 * the row's effective `[min, max]` bounds (linked-component capacity OR the 0..100 percent
 * envelope). Inherits the chrome-wide `.alert-warning` palette (orange icon + tinted bg)
 * for visual parity with every other warning in the app; the overrides below just tighten
 * the geometry to match `.checklist-run-item-error` so the warning fits the compact
 * one-line run-item layout without pushing the next row down by an unreasonable amount. */
.checklist-run-item-clamp-warning {
  margin-top: 0.4rem;
  margin-bottom: 0;
  font-size: 0.78rem;
  padding: 0.4rem 0.6rem;
  align-items: center;
  gap: 0.4rem;
  line-height: 1.3;
}

.checklist-run-item-clamp-warning .fa-triangle-exclamation {
  flex: 0 0 auto;
}

.checklist-run-item-notes-modal {
  max-width: 540px;
}

/* Images indicator — concise single-icon affordance with a count badge that lives in the
 * row's action cluster between notes and attachment. Mirrors the notes-trigger geometry so
 * the icons line up visually; the badge sits in the upper-right and shows the count rather
 * than a dot so the user knows at-a-glance how many images are attached without opening
 * the modal. Only rendered when count > 0 — empty rows never carry the icon. */
.checklist-run-item-images-trigger {
  position: relative;
}

.checklist-run-item-images-trigger:hover {
  color: var(--color-gold-light);
}

.checklist-run-item-images-count {
  position: absolute;
  top: -0.2rem;
  right: -0.35rem;
  min-width: 0.95rem;
  height: 0.95rem;
  padding: 0 0.2rem;
  background: var(--color-gold);
  color: var(--color-ocean-deep);
  font-size: 0.6rem;
  font-weight: 700;
  line-height: 0.95rem;
  text-align: center;
  border-radius: 0.6rem;
  pointer-events: none;
}

/* Images modal — same geometry envelope as the notes modal so the two feel like a pair. */
.checklist-run-item-images-modal {
  max-width: 540px;
}

.checklist-run-item-images-modal-empty {
  padding: 1rem 0.25rem;
  color: var(--color-text-muted);
  font-size: 0.85rem;
  text-align: center;
}

.checklist-run-item-images-modal-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-height: 60vh;
  overflow-y: auto;
}

/* One row per image: thumbnail | description input | remove button. The description input
 * is the flex-grower so it eats the leftover horizontal space; thumbnail and remove button
 * stay at intrinsic size. */
.checklist-run-item-images-modal-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.4rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-ocean-deep);
}

.checklist-run-item-images-modal-thumbnail img {
  display: block;
  width: 3.5rem;
  height: 3.5rem;
  object-fit: cover;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  cursor: pointer;
}

.checklist-run-item-images-modal-description {
  flex: 1 1 auto;
  min-width: 0;
}

.checklist-run-item-images-modal-remove {
  flex-shrink: 0;
}

/* Tone the whole card subtly based on the active status so a scanning user picks up state. */
.checklist-run-item-status-complete {
  border-color: rgba(26, 138, 90, 0.45);
  background-color: rgba(26, 138, 90, 0.06);
}

.checklist-run-item-status-failed,
.checklist-run-item-status-cannot_complete {
  border-color: rgba(192, 57, 43, 0.4);
  background-color: rgba(192, 57, 43, 0.06);
}

.checklist-run-item-status-issue_found {
  border-color: rgba(243, 156, 18, 0.45);
  background-color: rgba(243, 156, 18, 0.06);
}

/* Striped "marked done but still missing a measurement" overlay. Applied on top of the
   status-tone background above via repeating-linear-gradient so the row reads as "user
   clicked the status icon but never filled in the number — still needs work". The stripe
   color comes from the same tone palette as the solid backgrounds so the meaning is:
     solid green   = complete AND measured
     striped green = marked complete BUT measurement still missing.
   The `!important` overrides the solid status-tone background only when both classes
   coexist; no other rule in this file uses `!important` on `background`. */
.checklist-run-item-marked-done-but-incomplete.checklist-run-item-status-complete {
  background: repeating-linear-gradient(
    -45deg,
    rgba(26, 138, 90, 0.18),
    rgba(26, 138, 90, 0.18) 10px,
    rgba(26, 138, 90, 0.05) 10px,
    rgba(26, 138, 90, 0.05) 20px
  ) !important;
}

.checklist-run-item-marked-done-but-incomplete.checklist-run-item-status-failed,
.checklist-run-item-marked-done-but-incomplete.checklist-run-item-status-cannot_complete {
  background: repeating-linear-gradient(
    -45deg,
    rgba(192, 57, 43, 0.18),
    rgba(192, 57, 43, 0.18) 10px,
    rgba(192, 57, 43, 0.05) 10px,
    rgba(192, 57, 43, 0.05) 20px
  ) !important;
}

.checklist-run-item-marked-done-but-incomplete.checklist-run-item-status-issue_found {
  background: repeating-linear-gradient(
    -45deg,
    rgba(243, 156, 18, 0.22),
    rgba(243, 156, 18, 0.22) 10px,
    rgba(243, 156, 18, 0.06) 10px,
    rgba(243, 156, 18, 0.06) 20px
  ) !important;
}

/* ── Section header rows (run modal) ─────────────────────────────────────────
 * A section header is a structural grouping row: name + addressed/total progress
 * bar + one count badge per non-complete marked status. It governs every
 * non-header item after it (by sortOrder, id) until the next header. The
 * container also carries `.checklist-run-item-status-pending` from the shared
 * status ng-class — headers stay pending forever, so the override below keeps
 * them visually distinct from actionable rows. */
.checklist-run-item.checklist-run-section-header {
  margin-top: 0.85rem;
  border-left: 3px solid var(--color-border-gold);
  background: var(--color-ocean-deepest);
}

.checklist-run-section-header-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: 0.6rem;
  min-height: 1.85rem;
}

.checklist-run-section-header-title {
  flex: 0 1 auto;
  min-width: 0;
  font-weight: 600;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  color: var(--color-text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.checklist-run-section-header-badges {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  flex-shrink: 0;
}

/* Count badge: status icon + member count, toned with the same palette as the
   per-item status strip so "failed badge" and "failed icon" read identically. */
.checklist-run-section-header-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.05rem 0.4rem;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.3;
}

.checklist-run-section-header-badge-count {
  font-variant-numeric: tabular-nums;
}

.checklist-run-section-header-badge-tone-danger {
  background: var(--color-danger-light);
  color: var(--color-danger);
  border-color: var(--color-danger);
}

.checklist-run-section-header-badge-tone-warning {
  background: var(--color-warning-light);
  color: var(--color-warning);
  border-color: var(--color-warning);
}

.checklist-run-section-header-badge-tone-muted {
  background: var(--color-ocean-surface);
  color: var(--color-text-secondary);
  border-color: var(--color-border);
}

/* Progress bar — same silhouette as the home checklist widget's row progress so
   the two surfaces read identically. Fill = addressed/total; green only when
   every member is complete. */
.checklist-run-section-header-progress {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1 1 8rem;
  min-width: 6rem;
  margin-left: auto;
}

.checklist-run-section-header-progress-bar {
  position: relative;
  flex: 1 1 auto;
  height: 4px;
  background: var(--color-ocean-surface);
  border-radius: 2px;
  overflow: hidden;
}

.checklist-run-section-header-progress-bar-fill {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: var(--events-color-navigation);
  transition: width 200ms ease;
}

.checklist-run-section-header-progress-bar-fill-complete {
  background: var(--color-success);
}

.checklist-run-section-header-progress-text {
  flex-shrink: 0;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
}

.checklist-run-section-header-progress-text-complete {
  color: var(--color-success);
}

/* ── Section header rows (template create/edit modal) ────────────────────────
 * Compact single-line row; the gold accent flips to a full-width top emphasis so
 * the editor mirrors the run modal's visual grouping. */
.checklist-template-item-row-section-header {
  border-left-color: var(--color-gold-light);
  background: var(--color-ocean-deep);
}

.checklist-template-item-row.checklist-template-item-row-section-header:nth-of-type(even) {
  background: var(--color-ocean-deep);
}

/* Realtime presence avatar strip in the modal header. One chip per distinct user; chips
   are deduped server-side so two devices for the same human render as a single circle. */
.checklist-run-viewer-strip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: 1rem;
  flex-wrap: wrap;
}

.checklist-run-viewer-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  color: #ffffff;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  box-shadow: 0 0 0 2px var(--color-avatar-ring);
  user-select: none;
  overflow: hidden; /* Clip the avatar <img> to the circle */
}

/* When the chip wraps a real profile photo, drop the tinted background entirely and let the
   image fill the circle. The wrapper still owns the border-radius / box-shadow so the photo
   and the initials fallback render identically aside from the contents. */
.checklist-run-viewer-chip-with-image {
  background-color: transparent;
}

.checklist-run-viewer-chip-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.checklist-run-viewer-chip-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/* Remote-update glow — one-shot keyframe driven by a JS class toggle. The keyframe starts
   with a vivid ring + tint and fades to none over the duration; the CSS lasts exactly
   `CHECKLIST_RUN_ITEM_REMOTE_UPDATE_GLOW_DURATION_MILLISECONDS` in checklists.js so the
   class can be cleared at the same moment the animation finishes. Restart-on-reapply is
   handled by a JS clear-then-set-across-microtask trick — CSS alone cannot restart a
   keyframe on a class re-application without removing it for one render frame. */
@keyframes checklist-run-item-remote-update-glow-keyframes {
  0%   {
    box-shadow: 0 0 0 3px rgba(58, 134, 255, 0.6);
    background-color: rgba(58, 134, 255, 0.15);
  }
  60%  {
    box-shadow: 0 0 0 2px rgba(58, 134, 255, 0.3);
    background-color: rgba(58, 134, 255, 0.05);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(58, 134, 255, 0);
    background-color: transparent;
  }
}

.checklist-run-item-remote-update-glow {
  animation: checklist-run-item-remote-update-glow-keyframes 1500ms ease-out;
  /* Lift this row above the static striped/solid status background so the keyframe's
     transient `background-color` actually paints visibly. */
  position: relative;
  z-index: 1;
}


.checklist-signature-list {
  margin-top: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.checklist-signature-row {
  display: flex;
  justify-content: space-between;
  color: var(--color-text-secondary);
}

.checklist-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  cursor: pointer;
}

.checklist-checkbox input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.checklist-checkbox-indicator {
  width: 1rem;
  height: 1rem;
  border: 1px solid var(--color-border);
  border-radius: 0.2rem;
  background: var(--color-ocean-mid);
  display: inline-block;
  position: relative;
}

.checklist-checkbox input[type="checkbox"]:checked + .checklist-checkbox-indicator {
  background: var(--color-ocean-light);
  border-color: var(--color-ocean-light);
}

.checklist-checkbox input[type="checkbox"]:checked + .checklist-checkbox-indicator::after {
  content: '';
  position: absolute;
  left: 0.3rem;
  top: 0.08rem;
  width: 0.25rem;
  height: 0.55rem;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}


/** stylesheets/src/chat.css **/
/* Chat */
.chat-layout {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 1rem;
  min-height: 520px;
}

.chat-section .section-header {
  align-items: center;
}

.chat-channel-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.4rem;
}

.chat-channel-group {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.chat-channel-group + .chat-channel-group {
  margin-top: 0.5rem;
}

.chat-channel-group-header {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-secondary);
  padding: 0.25rem 0.25rem 0.1rem;
}

.chat-sidebar {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-ocean-deep);
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  max-height: 70vh;
  overflow: auto;
}

.chat-channel-item {
  width: 100%;
  text-align: left;
  border: 1px solid var(--color-border);
  background: var(--color-ocean-mid);
  color: var(--color-text-primary);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.7rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.4rem;
}

.chat-channel-item-unread {
  font-weight: 700;
}

/* Unread message count badge shown on sidebar channel rows */
.chat-unread-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 0.35rem;
  background: var(--color-gold-subtle);
  border: 1px solid var(--color-border-gold);
  color: var(--color-gold-light);
  font-size: 0.65rem;
  font-weight: 700;
  border-radius: 20px;
  flex-shrink: 0;
}

.chat-channel-item-active {
  border-color: var(--color-ocean-light);
  box-shadow: 0 0 0 1px var(--color-ocean-light) inset;
}

.chat-channel-settings-button {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  width: 2.1rem;
  background: var(--color-ocean-mid);
  color: var(--color-text-primary);
}

.chat-thread {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-ocean-deep);
  display: flex;
  flex-direction: column;
  /* dvh keeps the composer above the on-screen keyboard / browser chrome. */
  min-height: 70vh;
  min-height: 70dvh;
}

.chat-thread-header {
  padding: 0.8rem 1rem;
  border-bottom: 1px solid var(--color-border);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

/* Phone-only back affordance in the thread header (revealed in the phone
   media query below). */
.chat-thread-back {
  display: none;
}

/* ── Phone single-column mode (breakpoint convention: variables.css) ──
   The 280px sidebar + thread grid becomes one column showing EITHER the
   channel list OR the active thread. `.chat-layout-channel-active` is bound
   from the template (`!!app.chatActiveChannel`); the thread header's back
   button deselects the channel to return to the list. */
@media (max-width: 640px) {
  .chat-layout {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }

  .chat-layout-channel-active .chat-sidebar {
    display: none;
  }

  .chat-sidebar {
    max-height: none;
  }

  .chat-thread-back {
    display: inline-flex;
  }

  .chat-thread-header {
    justify-content: flex-start;
    gap: 0.5rem;
  }

  .chat-thread-header-actions {
    margin-left: auto;
  }
}

.chat-thread-header-actions {
  display: flex;
  gap: 0.4rem;
}

.chat-messages {
  padding: 0.8rem 1rem;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  flex: 1;
}

.chat-message-row {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.6rem;
  background: var(--color-ocean-mid);
  position: relative;
}

.chat-message-row-own {
  background: rgba(162, 116, 22, 0.18);
  border-color: rgba(162, 116, 22, 0.42);
}

.chat-message-row-own .chat-message-meta {
  color: var(--color-gold-light);
}

.chat-message-meta {
  display: flex;
  justify-content: space-between;
  color: var(--color-text-secondary);
  margin-bottom: 0.25rem;
  font-size: 0.86rem;
}

.chat-message-text {
  margin: 0;
  white-space: pre-wrap;
}

.chat-message-deleted {
  margin: 0;
  color: var(--color-text-secondary);
  font-style: italic;
}

.chat-message-menu-button {
  position: absolute;
  top: 0.3rem;
  right: 0.3rem;
  border: 0;
  background: transparent;
  color: var(--color-text-secondary);
  font-size: 1rem;
}

.chat-message-menu {
  position: absolute;
  top: 1.8rem;
  right: 0.4rem;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-ocean-deep);
  z-index: 2;
}

.chat-composer {
  border-top: 1px solid var(--color-border);
  padding: 0.8rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.chat-typing-indicator {
  padding: 0 1rem 0.55rem;
  color: var(--color-text-secondary);
  font-size: 0.82rem;
  font-style: italic;
}

.chat-composer .form-control {
  border-radius: 0.7rem;
  border-width: 2px;
  min-height: 4.5rem;
}

.chat-composer-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

.chat-send-button {
  width: 2.3rem;
  height: 2.3rem;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
}

.chat-modal {
  max-width: 560px;
}

.chat-modal .modal-body {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}

.chat-modal .modal-body h3 {
  margin: 0;
}

.chat-modal .modal-footer {
  margin-top: 0.35rem;
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}

.chat-invite-list {
  margin-top: 0.75rem;
  max-height: 320px;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.chat-role-selector {
  margin-top: 0.55rem;
  margin-bottom: 0.55rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.chat-invite-row {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-ocean-mid);
  color: var(--color-text-primary);
  padding: 0.45rem 0.55rem;
  text-align: left;
  display: flex;
  justify-content: space-between;
  gap: 0.7rem;
}
/* ── Chat read receipts ──────────────────────────────────────── */
/* Displayed below own messages only.  The ::before pseudo-element renders
   the checkmark character(s); using ::before instead of inline text means
   the span itself has zero width and the cursor stays as default (not text). */
.chat-read-receipt {
  display: block;
  text-align: right;
  font-size: 0.7rem;
  color: var(--color-text-secondary);
  cursor: default;
  user-select: none;
  margin-top: 0.15rem;
  line-height: 1;
}
/* Single grey check = sent (received by server, not yet read by anyone else). */
.chat-read-receipt::before {
  content: '✓';
  letter-spacing: -0.05em;
}
/* Double gold check = read by at least one other active channel member. */
.chat-read-receipt-read::before {
  content: '✓✓';
  color: var(--color-gold-light);
}

/** stylesheets/src/event.css **/
/* ============================================================
   Events ("Ship's Log") feature — Ocean theme base styles
   ------------------------------------------------------------
   Layout primitives are organized top-down to match the visual
   layout of app/views/event/section.scala.html:
     1. Maritime Bridge   — control bar (grid + time + omnibox + filters)
     2. Maritime Feed     — timeline list of events
     3. Per-category accents (left border, badge tint, icon tint)
   ============================================================ */

/* ------------------------------------------------------------
   Category accent tokens (`--events-color-*`) live in the
   canonical token file, variables.css, with their day overrides
   in day.css — one source of truth for the theme token catalog.
   ------------------------------------------------------------ */

/* ------------------------------------------------------------
   Section frame
   ------------------------------------------------------------ */
.events-view {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

/* ============================================================
   1. Maritime Bridge — sticky cohesive control bar
   ============================================================ */
.events-bridge {
  position: sticky;
  top: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  padding: 0.85rem 1rem 0.95rem;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--color-ocean-mid) 96%, transparent) 0%,
    color-mix(in srgb, var(--color-ocean-deep) 96%, transparent) 100%);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  backdrop-filter: blur(8px);
}

/* ------------------------------------------------------------
   Action Grid — wrapping pill button row
   ------------------------------------------------------------ */
.events-action-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

.events-action-tile {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.95rem;
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-text-primary);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition), border-color var(--transition),
              color var(--transition), transform var(--transition),
              box-shadow var(--transition);
}

.events-action-tile:hover:not(:disabled) {
  background: var(--color-ocean-light);
  border-color: var(--color-border-gold);
  transform: translateY(-1px);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.25);
}

.events-action-tile:active:not(:disabled) {
  transform: translateY(0);
}

.events-action-tile:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.events-action-tile-icon {
  font-size: 0.92rem;
  line-height: 1;
  width: 1.1em;
  display: inline-flex;
  justify-content: center;
}

.events-action-tile-label {
  white-space: nowrap;
}

/* Per-category accent on the tile icon. */
.event-tile-navigation   .events-action-tile-icon { color: var(--events-color-navigation); }
.event-tile-fuel         .events-action-tile-icon { color: var(--events-color-fuel); }
.event-tile-water        .events-action-tile-icon { color: var(--events-color-water); }
.event-tile-engine       .events-action-tile-icon { color: var(--events-color-engine); }
.event-tile-maintenance  .events-action-tile-icon { color: var(--events-color-maintenance); }
.event-tile-weather      .events-action-tile-icon { color: var(--events-color-weather); }
.event-tile-wildlife     .events-action-tile-icon { color: var(--events-color-wildlife); }
.event-tile-guests       .events-action-tile-icon { color: var(--events-color-guests); }
.event-tile-safety       .events-action-tile-icon { color: var(--events-color-safety); }
.event-tile-mooring      .events-action-tile-icon { color: var(--events-color-mooring); }
.event-tile-provisioning .events-action-tile-icon { color: var(--events-color-provisioning); }
.event-tile-general      .events-action-tile-icon { color: var(--events-color-general); }

/* ------------------------------------------------------------
   Hybrid Time row + Omnibox in a single line
   ------------------------------------------------------------ */
.events-write-row {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
}

.events-time-row {
  display: inline-flex;
  gap: 0.3rem;
  padding: 0.3rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  flex-wrap: wrap;
}

.events-time-button {
  padding: 0.35rem 0.8rem;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 999px;
  color: var(--color-text-secondary);
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}

.events-time-button:hover:not(.events-time-button-active) {
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
}

.events-time-button-active {
  background: var(--color-gold-subtle);
  border-color: var(--color-border-gold);
  color: var(--color-gold-light);
}

.events-omnibox {
  flex: 1 1 320px;
  display: flex;
  align-items: stretch;
  gap: 0.35rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.25rem 0.4rem 0.25rem 0.85rem;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.events-omnibox:focus-within {
  border-color: var(--color-border-gold);
  box-shadow: 0 0 0 3px var(--color-gold-subtle);
}

.events-omnibox-icon {
  align-self: center;
  color: var(--color-text-secondary);
  font-size: 0.85rem;
}

.events-omnibox-input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: none;
  color: var(--color-text-primary);
  font-size: 0.9rem;
  padding: 0.45rem 0.25rem;
}

.events-omnibox-input::placeholder {
  color: var(--color-text-muted);
}

.events-omnibox-save {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.45rem 0.95rem;
  font-size: 0.82rem;
  border-radius: var(--radius-md);
  flex-shrink: 0;
}

/* ------------------------------------------------------------
   Pill bar — category filters
   ------------------------------------------------------------ */
.events-pill-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}

.events-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.32rem 0.75rem;
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-text-secondary);
  font-size: 0.74rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
  white-space: nowrap;
}

.events-pill i {
  font-size: 0.78rem;
}

.events-pill:hover:not(.events-pill-active) {
  background: var(--color-ocean-surface);
  border-color: var(--color-border-gold);
  color: var(--color-text-primary);
}

.events-pill-active {
  background: var(--color-ocean-light);
  border-color: var(--color-border-gold);
  color: var(--color-gold-light);
}

/* Per-pill accent when active. */
.events-pill-navigation.events-pill-active   { color: var(--events-color-navigation);   border-color: color-mix(in srgb, var(--events-color-navigation) 50%, transparent); }
.events-pill-fuel.events-pill-active         { color: var(--events-color-fuel);         border-color: color-mix(in srgb, var(--events-color-fuel) 50%, transparent); }
.events-pill-water.events-pill-active        { color: var(--events-color-water);        border-color: color-mix(in srgb, var(--events-color-water) 50%, transparent); }
.events-pill-engine.events-pill-active       { color: var(--events-color-engine);       border-color: color-mix(in srgb, var(--events-color-engine) 50%, transparent); }
.events-pill-maintenance.events-pill-active  { color: var(--events-color-maintenance);  border-color: color-mix(in srgb, var(--events-color-maintenance) 50%, transparent); }
.events-pill-weather.events-pill-active      { color: var(--events-color-weather);      border-color: color-mix(in srgb, var(--events-color-weather) 50%, transparent); }
.events-pill-wildlife.events-pill-active     { color: var(--events-color-wildlife);     border-color: color-mix(in srgb, var(--events-color-wildlife) 50%, transparent); }
.events-pill-guests.events-pill-active       { color: var(--events-color-guests);       border-color: color-mix(in srgb, var(--events-color-guests) 50%, transparent); }
.events-pill-safety.events-pill-active       { color: var(--events-color-safety);       border-color: color-mix(in srgb, var(--events-color-safety) 50%, transparent); }
.events-pill-mooring.events-pill-active      { color: var(--events-color-mooring);      border-color: color-mix(in srgb, var(--events-color-mooring) 50%, transparent); }
.events-pill-provisioning.events-pill-active { color: var(--events-color-provisioning); border-color: color-mix(in srgb, var(--events-color-provisioning) 50%, transparent); }
.events-pill-general.events-pill-active      { color: var(--events-color-general);      border-color: color-mix(in srgb, var(--events-color-general) 50%, transparent); }

/* ============================================================
   2. Maritime Feed — timeline list
   ============================================================ */
.events-feed {
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  list-style: none;
  padding: 0;
  margin: 0;
}

.events-entry {
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.85rem 1rem 0.95rem 1rem;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), transform var(--transition);
}

.events-entry:hover {
  background: var(--color-ocean-light);
  transform: translateX(2px);
}

.events-entry-expanded {
  background: var(--color-ocean-light);
}

/* Category accent on the left border + the badge tint. */
.events-entry-category-navigation    { border-left-color: var(--events-color-navigation); }
.events-entry-category-fuel          { border-left-color: var(--events-color-fuel); }
.events-entry-category-water         { border-left-color: var(--events-color-water); }
.events-entry-category-engine        { border-left-color: var(--events-color-engine); }
.events-entry-category-maintenance   { border-left-color: var(--events-color-maintenance); }
.events-entry-category-weather       { border-left-color: var(--events-color-weather); }
.events-entry-category-wildlife      { border-left-color: var(--events-color-wildlife); }
.events-entry-category-guests        { border-left-color: var(--events-color-guests); }
.events-entry-category-safety        { border-left-color: var(--events-color-safety); }
.events-entry-category-mooring       { border-left-color: var(--events-color-mooring); }
.events-entry-category-provisioning  { border-left-color: var(--events-color-provisioning); }
.events-entry-category-general       { border-left-color: var(--events-color-general); }
.events-entry-category-checklist_completed { border-left-color: var(--events-color-checklist); }

/* ------------------------------------------------------------
   Entry header
   ------------------------------------------------------------ */
.events-entry-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}

.events-entry-time {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  color: var(--color-text-primary);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.events-entry-time i {
  color: var(--color-text-secondary);
}

.events-entry-date {
  margin-left: 0.35rem;
  color: var(--color-text-secondary);
  font-weight: 500;
  font-size: 0.75rem;
}

.events-entry-category-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.2em 0.7em;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
}

/* Tint the badge icon by category. */
.events-entry-category-navigation    .events-entry-category-badge { color: var(--events-color-navigation);   border-color: color-mix(in srgb, var(--events-color-navigation) 30%, transparent); }
.events-entry-category-fuel          .events-entry-category-badge { color: var(--events-color-fuel);         border-color: color-mix(in srgb, var(--events-color-fuel) 30%, transparent); }
.events-entry-category-water         .events-entry-category-badge { color: var(--events-color-water);        border-color: color-mix(in srgb, var(--events-color-water) 30%, transparent); }
.events-entry-category-engine        .events-entry-category-badge { color: var(--events-color-engine);       border-color: color-mix(in srgb, var(--events-color-engine) 30%, transparent); }
.events-entry-category-maintenance   .events-entry-category-badge { color: var(--events-color-maintenance);  border-color: color-mix(in srgb, var(--events-color-maintenance) 30%, transparent); }
.events-entry-category-weather       .events-entry-category-badge { color: var(--events-color-weather);      border-color: color-mix(in srgb, var(--events-color-weather) 30%, transparent); }
.events-entry-category-wildlife      .events-entry-category-badge { color: var(--events-color-wildlife);     border-color: color-mix(in srgb, var(--events-color-wildlife) 30%, transparent); }
.events-entry-category-guests        .events-entry-category-badge { color: var(--events-color-guests);       border-color: color-mix(in srgb, var(--events-color-guests) 30%, transparent); }
.events-entry-category-safety        .events-entry-category-badge { color: var(--events-color-safety);       border-color: color-mix(in srgb, var(--events-color-safety) 30%, transparent); }
.events-entry-category-mooring       .events-entry-category-badge { color: var(--events-color-mooring);      border-color: color-mix(in srgb, var(--events-color-mooring) 30%, transparent); }
.events-entry-category-provisioning  .events-entry-category-badge { color: var(--events-color-provisioning); border-color: color-mix(in srgb, var(--events-color-provisioning) 30%, transparent); }
.events-entry-category-general       .events-entry-category-badge { color: var(--events-color-general);      border-color: color-mix(in srgb, var(--events-color-general) 30%, transparent); }
.events-entry-category-checklist_completed .events-entry-category-badge { color: var(--events-color-checklist); border-color: color-mix(in srgb, var(--events-color-checklist) 30%, transparent); }

/* ------------------------------------------------------------
   Entry content — per-category bodies
   ------------------------------------------------------------ */
.events-entry-content {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.events-headline {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--color-text-primary);
  font-size: 1rem;
}

.events-headline strong {
  font-weight: 600;
}

.events-headline i {
  color: var(--color-text-secondary);
  font-size: 0.95rem;
}

.events-notes {
  color: var(--color-text-secondary);
  font-size: 0.875rem;
  line-height: 1.45;
  margin: 0.15rem 0 0 0;
}

.events-notes-prose {
  color: var(--color-text-primary);
  font-size: 0.95rem;
}

/* The big gold metric used for fuel volumes — readable across spray and glare. */
.events-metric {
  margin-top: 0.15rem;
  font-size: 1.5rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-gold-light);
  letter-spacing: 0.01em;
  line-height: 1.1;
}

.events-metric-unit {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--color-text-secondary);
  margin-left: 0.25rem;
}

/* ------------------------------------------------------------
   Entry chevron
   ------------------------------------------------------------ */
.events-entry-chevron {
  margin-left: auto;
  color: var(--color-text-muted);
  font-size: 0.75rem;
  flex-shrink: 0;
  transition: color var(--transition);
}

.events-entry:hover .events-entry-chevron,
.events-entry-expanded .events-entry-chevron {
  color: var(--color-text-secondary);
}

/* ------------------------------------------------------------
   Expanded detail panel
   ------------------------------------------------------------ */
.events-entry-detail {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
}

.events-detail-section {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.events-detail-label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.events-detail-text {
  font-size: 0.875rem;
  color: var(--color-text-secondary);
  line-height: 1.5;
  margin: 0;
}

.events-detail-grid {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.events-detail-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.875rem;
}

.events-detail-row-name {
  color: var(--color-text-primary);
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-shrink: 0;
}

.events-detail-row-type {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  font-weight: 500;
}

.events-detail-row-value {
  color: var(--color-text-primary);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.events-detail-row-unit {
  font-weight: 400;
  color: var(--color-text-secondary);
  margin-left: 0.2rem;
}

/* Checklist run-item status badge (shared by the full Ship's Log view and the home widget). */
.events-item-status-badge {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.45rem;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  background: var(--color-border);
  color: var(--color-text-muted);
}

.events-item-status-badge.events-item-status-complete {
  background: var(--color-success-light);
  color: var(--color-success);
}

.events-item-status-badge.events-item-status-failed,
.events-item-status-badge.events-item-status-cannot_complete {
  background: var(--color-danger-light);
  color: var(--color-danger);
}

.events-item-status-badge.events-item-status-issue_found {
  background: var(--color-warning-light);
  color: var(--color-warning-text);
}

/* "Open live record" action row inside a completion entry's detail panel. */
.events-detail-actions,
.home-ship-log-widget-detail-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 0.25rem;
}

.events-detail-open-record,
.home-ship-log-widget-open-record {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.events-detail-meta-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0.5rem 1rem;
}

.events-detail-meta {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

.events-detail-meta-full {
  grid-column: 1 / -1;
}

.events-detail-meta-label {
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--color-text-muted);
}

.events-detail-meta-value {
  font-size: 0.875rem;
  color: var(--color-text-primary);
}

/* ============================================================
   3. Empty / loading states
   ============================================================ */
.events-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 3rem 1rem;
  text-align: center;
}

.events-empty-icon {
  font-size: 2.5rem;
  color: var(--color-text-muted);
  margin-bottom: 0.4rem;
}

.events-empty-hint {
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

/* ============================================================
   4. Universal Log Modal — accordion sections
   ============================================================ */
.events-universal-modal {
  max-width: 720px;
  width: 100%;
}

.events-universal-modal .modal-title {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
}

.events-universal-modal .modal-title i {
  color: var(--color-gold-light);
  font-size: 1.05rem;
}

.events-universal-modal-body {
  max-height: 75vh;
  overflow-y: auto;
}

.events-universal-prefill-spinner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.85rem;
  margin-bottom: 0.85rem;
}

.events-universal-modal-hint {
  font-size: 0.82rem;
  color: var(--color-text-secondary);
  margin: 0 0 0.85rem 0;
}

.events-universal-modal-hint strong {
  color: var(--color-gold-light);
  text-transform: capitalize;
}

.events-universal-modal-actions {
  position: sticky;
  bottom: 0;
  background: var(--color-ocean-mid);
  padding-top: 0.85rem;
  margin-top: 1rem;
  border-top: 1px solid var(--color-border);
}

/* ── Accordion ────────────────────────────────────────────── */
.events-accordion {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}

.events-accordion-section {
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: border-color var(--transition);
}

.events-accordion-section-included {
  border-color: var(--color-border-gold);
}

.events-accordion-section-expanded {
  background: var(--color-ocean-surface);
}

/* The header IS the click target — full row, large enough for touch. */
.events-accordion-header {
  display: grid;
  grid-template-columns: auto auto 1fr auto;
  align-items: center;
  gap: 0.65rem;
  width: 100%;
  min-height: 52px;
  padding: 0.65rem 0.95rem;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--color-text-primary);
  font-family: inherit;
  font-size: 0.95rem;
  text-align: left;
  transition: background var(--transition);
}

.events-accordion-header:hover,
.events-accordion-header:focus-visible {
  background: var(--color-ocean-light);
  outline: none;
}

.events-accordion-header-chevron {
  display: inline-flex;
  width: 1.2em;
  justify-content: center;
  color: var(--color-text-secondary);
  transition: transform var(--transition);
}

.events-accordion-section-expanded .events-accordion-header-chevron {
  color: var(--color-gold-light);
}

.events-accordion-header-icon {
  display: inline-flex;
  width: 1.3em;
  justify-content: center;
  color: var(--color-text-secondary);
}

.events-accordion-section-included .events-accordion-header-icon {
  color: var(--color-gold-light);
}

.events-accordion-header-label {
  font-weight: 600;
}

.events-accordion-header-included {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.6rem;
  border-radius: var(--radius-sm);
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  font-size: 0.75rem;
  color: var(--color-text-secondary);
  cursor: pointer;
  transition: border-color var(--transition), color var(--transition);
}

.events-accordion-header-included:has(input[type='checkbox']:checked) {
  border-color: var(--color-border-gold);
  color: var(--color-gold-light);
}

.events-accordion-header-included input[type='checkbox'] {
  width: 0.85rem;
  height: 0.85rem;
}

.events-accordion-body {
  padding: 0.95rem 1rem 1.05rem 1rem;
  border-top: 1px solid var(--color-border);
}

/* ── Shared row styling for engines, tanks ────────────────── */
.events-engine-row,
.events-tank-row {
  display: grid;
  grid-template-columns: auto 1fr minmax(220px, 2fr);
  align-items: center;
  gap: 0.85rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--color-border);
}

.events-engine-row:last-child,
.events-tank-row:last-child {
  border-bottom: 0;
}

.events-row-include input[type='checkbox'] {
  width: 1.15rem;
  height: 1.15rem;
}

.events-row-label strong {
  color: var(--color-text-primary);
  font-weight: 600;
}

.events-row-control {
  min-width: 0;
}

.events-tank-row {
  grid-template-columns: auto 1fr minmax(220px, 2fr);
}

.events-tank-row-meta {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.events-tank-row-type-and-unit {
  display: flex;
  gap: 0.4rem;
}

.form-control-compact {
  padding: 0.25rem 0.45rem;
  font-size: 0.78rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  color: var(--color-text-primary);
}

.form-control-compact option {
  background: var(--color-ocean-deep);
  color: var(--color-text-primary);
}

/* ── Wildlife rows ────────────────────────────────────────── */
.events-wildlife-species-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 0.4rem;
  margin-bottom: 0.8rem;
}

.events-species-quick-pick {
  padding: 0.55rem 0.65rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text-primary);
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}

.events-species-quick-pick:hover {
  background: var(--color-ocean-light);
  border-color: var(--color-border-gold);
}

.events-species-quick-pick-custom {
  border-style: dashed;
  color: var(--color-text-secondary);
}

.events-wildlife-sighting-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) minmax(110px, auto) minmax(70px, auto) auto;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0;
  border-bottom: 1px dashed var(--color-border);
}

.events-wildlife-sighting-row:last-of-type {
  border-bottom: 0;
}

.events-wildlife-sighting-species input,
.events-wildlife-sighting-quantity input,
.events-wildlife-sighting-action select {
  width: 100%;
}

.events-wildlife-row-remove {
  color: var(--color-text-muted);
  background: transparent;
  border: 0;
  cursor: pointer;
  padding: 0.25rem 0.45rem;
}

.events-wildlife-row-remove:hover {
  color: var(--events-color-safety);
}

/* ── Weather / Location grids ─────────────────────────────── */
.events-form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.85rem;
}

.events-form-grid .events-form-grid-full {
  grid-column: 1 / -1;
}

/* ── Location section: geolocation status indicator ───────── */
.events-location-geolocation-status {
  margin-top: 0.75rem;
  font-size: 0.85rem;
}

.events-location-geolocation-status p {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.events-location-geolocation-pending {
  color: var(--color-text-secondary);
}

.events-location-geolocation-captured {
  color: var(--color-success, #4caf50);
}

.events-location-geolocation-failed {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
  color: var(--events-color-safety, #d97757);
}

.events-location-retry-gps {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

/* ── Misc helpers ─────────────────────────────────────────── */
.events-section-empty-state {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  font-style: italic;
  margin: 0;
  padding: 0.5rem 0;
}

.events-add-row-button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

/* ============================================================
   5. <scroll-wheel-input> directive
   ------------------------------------------------------------
   Layout:
     .scroll-wheel-input              ← outer container
       .unit-pill-bar                ← always visible row of pills
         .unit-pill                  ← inactive pill
         .unit-pill-active           ← (modifier) currently-selected pill
       .scroll-wheel-input-desktop-row  (rendered on fine pointer / wide viewport)
         <input> or <input>:<input>  ← native number / time inputs
         .scroll-wheel-input-previous-hint
       .scroll-wheel-input-touch-row    (rendered on coarse pointer / narrow viewport)
         .scroll-wheel-input-touch-typed  ← typed <input> mirroring the wheels
         .scroll-wheel-touch-wheels       ← one or two scroll wheels
           .scroll-wheel-pair
             .scroll-wheel              ← scroll-snappable column
               .scroll-wheel-center-mark  (decorative)
               .scroll-wheel-item       ← every selectable value
             .scroll-wheel-separator    ← "." or ":"
   ============================================================ */
.scroll-wheel-input {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  width: 100%;
}

/* ------------------------------------------------------------
   Unit pill bar — Ocean theme: inactive pills sit on the ocean
   surface and gain a gold-light text + outlined background when
   selected. The bar wraps freely so a 4–5 pill list (Engine,
   Fluid) still fits on a phone-width viewport.
   ------------------------------------------------------------ */
.unit-pill-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}

.unit-pill {
  appearance: none;
  background: var(--color-ocean-surface);
  border: 1px solid var(--color-border);
  border-radius: 999px;
  color: var(--color-text-secondary);
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 500;
  padding: 0.35rem 0.85rem;
  min-height: 32px;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.unit-pill:hover {
  background: var(--color-ocean-light);
  color: var(--color-text-primary);
}

.unit-pill-active {
  background: color-mix(in srgb, var(--color-gold-light) 14%, var(--color-ocean-deep));
  border-color: var(--color-gold-light);
  color: var(--color-gold-light);
  font-weight: 600;
}

/* ------------------------------------------------------------
   Desktop branch
   ------------------------------------------------------------ */
.scroll-wheel-input-desktop-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.scroll-wheel-input-numeric {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.scroll-wheel-input-input {
  flex: 0 1 140px;
  min-width: 100px;
  max-width: 220px;
  font-variant-numeric: tabular-nums;
  font-size: 0.95rem;
}

.scroll-wheel-input-time-row {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}

.scroll-wheel-input-time-hours {
  flex: 0 0 100px;
  min-width: 90px;
  text-align: center;
}

.scroll-wheel-input-time-minutes {
  flex: 0 0 70px;
  min-width: 60px;
  text-align: center;
}

.scroll-wheel-input-time-separator {
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--color-gold-light);
}

.scroll-wheel-input-unit-suffix {
  color: var(--color-text-secondary);
  font-size: 0.85rem;
  font-weight: 500;
}

.scroll-wheel-input-previous-hint {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.75rem;
  color: var(--color-text-muted);
}

.scroll-wheel-input-previous-hint-touch {
  margin: 0;
  text-align: center;
}

.scroll-wheel-input-reset-link {
  background: transparent;
  border: 0;
  color: var(--color-gold-light);
  font-size: 0.75rem;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
  padding: 0;
}

/* Clamp-warning banner. Surfaced by the directive the instant a typed entry is reduced
   to the active pill's bounds, so the user always sees the cause of the snap rather than
   a silent rewrite. Takes its own row inside the flex container so it doesn't squeeze
   the input + previous-hint pair on a narrow desktop. */
.scroll-wheel-input-clamp-warning {
  flex-basis: 100%;
  margin-top: 0.25rem;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--color-danger, #ff8a5c);
  line-height: 1.3;
}

/* ------------------------------------------------------------
   Touch branch — typed input on top, wheels below
   ------------------------------------------------------------ */
.scroll-wheel-input-touch-row {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
}

.scroll-wheel-input-touch-typed {
  display: flex;
  justify-content: center;
}

.scroll-wheel-touch-wheels {
  display: flex;
  justify-content: center;
}

.scroll-wheel-pair {
  display: inline-flex;
  align-items: stretch;
  gap: 0.35rem;
  padding: 0.35rem 0.5rem;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  position: relative;
}

.scroll-wheel-separator,
.scroll-wheel-suffix {
  align-self: center;
  font-size: 1.4rem;
  font-weight: 700;
  color: var(--color-gold-light);
}

/* ------------------------------------------------------------
   The wheels themselves — native scroll-snap. The fixed item
   height (44px) MUST match WHEEL_ITEM_HEIGHT_PX in the directive
   so the scroll-snap math agrees with the model commit math.
   ------------------------------------------------------------ */
.scroll-wheel {
  position: relative;
  width: 72px;
  height: 220px;             /* 5 × 44px */
  overflow-y: scroll;
  scroll-snap-type: y mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;     /* Firefox */
}

.scroll-wheel::-webkit-scrollbar {
  display: none;
}

.scroll-wheel-spacer {
  /* (220 - 44) / 2 = 88px — pads the list so the centre slot lines
     up with the centre mark. */
  height: 88px;
}

.scroll-wheel-item {
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  scroll-snap-align: center;
  font-size: 1.05rem;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
  transition: color var(--transition), font-weight var(--transition);
}

.scroll-wheel-item-active {
  color: var(--color-gold-light);
  font-weight: 700;
  font-size: 1.25rem;
}

.scroll-wheel-center-mark {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
  border-top: 1px solid color-mix(in srgb, var(--color-gold-light) 35%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--color-gold-light) 35%, transparent);
  pointer-events: none;
}

/* ------------------------------------------------------------
   Tank capacity hint — shown next to each tank-row name when the
   underlying component has attributes.capacity / capacityUnit set.
   ------------------------------------------------------------ */
.events-tank-row-capacity {
  margin: 0.1rem 0 0;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  font-style: italic;
}

.events-tank-row-type {
  margin-top: 0.4rem;
}

.events-tank-row-type-label {
  display: inline-block;
  padding: 0.18em 0.65em;
  border-radius: var(--radius-sm);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  background: rgba(201, 168, 76, 0.12);
  color: var(--color-gold-light);
  border: 1px solid rgba(201, 168, 76, 0.3);
  user-select: none;
}

/* ============================================================
   6. Settings modal
   ============================================================ */

/* ── Two-pane shell: left section nav, right content pane ─────────────
   The modal grew too many sections for one skinny column. The left nav
   ng-repeats over the stable `app.settingsSections` array (auth.js); the
   right pane renders only the ng-if-selected section. Colors are tokens
   only — the theme ratchet forbids new literals. */
.settings-modal {
  max-width: 1040px;
  height: min(85vh, 900px);
}

.settings-modal-body {
  display: flex;
  align-items: stretch;
  padding: 0;
  overflow: hidden;
}

.settings-nav {
  flex: 0 0 230px;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 1rem 0.75rem;
  border-right: 1px solid var(--color-border);
  background: var(--color-ocean-deep);
  border-radius: 0 0 0 var(--radius-lg);
  overflow-y: auto;
}

.settings-nav-item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  padding: 0.55rem 0.75rem;
  border: none;
  background: transparent;
  border-radius: var(--radius-sm);
  color: var(--color-text-secondary);
  font-size: 0.9rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition), color var(--transition);
}

.settings-nav-item:hover {
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
}

.settings-nav-item-active,
.settings-nav-item-active:hover {
  background: var(--color-ocean-surface);
  color: var(--color-text-primary);
  font-weight: 600;
}

.settings-nav-item-icon {
  width: 1.2rem;
  text-align: center;
  color: var(--color-gold-light);
  flex-shrink: 0;
}

.settings-content {
  flex: 1;
  min-width: 0;
  padding: 1.5rem;
  overflow-y: auto;
}

/* Narrow viewports: the nav collapses to a wrapping pill row above the content.
   (Phone breakpoint convention: variables.css.) */
@media (max-width: 640px) {
  /* Full-screen sheet on phones (Setup surface — functional over pretty). */
  .settings-modal {
    height: 100vh;
    height: 100dvh;
    max-height: 100vh;
    max-height: 100dvh;
    border-radius: 0;
  }

  .settings-modal-body {
    flex-direction: column;
  }

  /* The section list becomes one horizontally scrollable pill strip instead
     of a multi-line wrap that eats vertical space. */
  .settings-nav {
    flex: 0 0 auto;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-right: none;
    border-bottom: 1px solid var(--color-border);
    border-radius: 0;
  }

  .settings-nav-item {
    width: auto;
    flex-shrink: 0;
    white-space: nowrap;
  }
}

.settings-section {
  margin-bottom: 1.5rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--color-border);
}

.settings-section:last-child {
  border-bottom: 0;
  margin-bottom: 0;
  padding-bottom: 0;
}

.settings-section-title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1rem;
  font-weight: 600;
  margin: 0 0 0.35rem 0;
  color: var(--color-text-primary);
}

.settings-section-hint {
  font-size: 0.82rem;
  color: var(--color-text-secondary);
  margin: 0 0 0.65rem 0;
}

.settings-wildlife-textarea {
  width: 100%;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.85rem;
}

.settings-section-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 0.65rem;
  justify-content: flex-end;
}

.settings-section-saved-message {
  margin-top: 0.4rem;
  font-size: 0.75rem;
  color: var(--color-text-muted);
  text-align: right;
}

.settings-section-error-message {
  margin-top: 0.4rem;
  font-size: 0.8rem;
  color: var(--color-danger, #ff8a5c);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  text-align: left;
}

/* ── Settings modal — Appearance & Branding section ─────────────────────
   Controls for theme file selection, per-mode background + overlay, logo,
   and AI theme generation (branding.js + brandingSettings.scala.html).
   Colors are tokens only — the theme ratchet forbids new literals. */
.branding-tier-block {
  margin-top: 1rem;
  padding-top: 0.75rem;
  border-top: 1px dashed var(--color-border);
}

.branding-tier-title {
  margin: 0 0 0.25rem 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--color-text-primary);
}

.branding-mode-row {
  margin: 0.65rem 0;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.branding-mode-row-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  margin-bottom: 0.45rem;
}

.branding-mode-row-label {
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--color-text-primary);
}

.branding-mode-row-current {
  font-size: 0.78rem;
  color: var(--color-text-secondary);
}

.branding-mode-row-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.branding-theme-select {
  flex: 1;
  min-width: 180px;
}

.branding-background-controls {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-top: 0.55rem;
}

.branding-overlay-control {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.78rem;
  color: var(--color-text-secondary);
}

.branding-overlay-opacity-control input[type='range'] {
  width: 110px;
}

.branding-overlay-opacity-value {
  min-width: 2.2em;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.branding-generation-description {
  width: 100%;
  margin-top: 0.5rem;
}

.branding-generation-mode-select {
  max-width: 180px;
}

.branding-generation-actions {
  align-items: center;
  flex-wrap: wrap;
}

.branding-generation-save-name {
  max-width: 220px;
}

.branding-generation-result {
  margin-top: 0.6rem;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.branding-generation-findings {
  margin: 0.35rem 0;
  padding-left: 1.1rem;
  font-size: 0.78rem;
  color: var(--color-text-secondary);
}

.branding-tier-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.branding-tier-reset-button {
  flex-shrink: 0;
}

.branding-generation-reference-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.25rem 0.5rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: 0.78rem;
  color: var(--color-text-secondary);
}

.branding-generation-reference-remove {
  padding: 0 0.2rem;
  line-height: 1;
}

.branding-generation-assets {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin: 0.6rem 0;
}

.branding-generation-asset {
  margin: 0;
  font-size: 0.72rem;
  color: var(--color-text-secondary);
  text-align: center;
}

.branding-generation-asset-background {
  display: block;
  width: 192px;
  height: 108px;
  object-fit: cover;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
}

.branding-generation-asset-logo {
  display: block;
  width: 64px;
  height: 64px;
  object-fit: contain;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background: var(--color-surface);
}

.branding-generation-overlay-summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.branding-generation-overlay-swatch {
  display: inline-block;
  width: 16px;
  height: 16px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
}

.settings-feature-toggle-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 0.35rem 1rem;
}

.settings-feature-toggle-row {
  display: flex;
  align-items: center;
}

.settings-feature-toggle-label {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--color-text-primary);
}

.settings-feature-toggle-label input[type="checkbox"] {
  margin: 0;
}

/* ============================================================
   5. Responsive tweaks (phone breakpoint convention: variables.css)
   ============================================================ */
@media (max-width: 640px) {
  .events-bridge {
    padding: 0.7rem 0.75rem 0.8rem;
  }

  .events-write-row {
    flex-direction: column;
    align-items: stretch;
  }

  .events-omnibox {
    width: 100%;
  }

  .events-metric {
    font-size: 1.3rem;
  }

  /* Engine / tank accordion rows: [icon | meta | control(≥220px)] does not fit
     a phone. Keep icon + meta side-by-side and drop the control (scroll wheel /
     input group, the 3rd child) to its own full-width line. */
  .events-engine-row,
  .events-tank-row {
    grid-template-columns: auto minmax(0, 1fr);
  }

  .events-engine-row > :nth-child(3),
  .events-tank-row > :nth-child(3) {
    grid-column: 1 / -1;
  }

  /* Wildlife sighting rows: five grid columns can't fit — let the pieces wrap
     naturally instead. */
  .events-wildlife-sighting-row {
    display: flex;
    flex-wrap: wrap;
  }

  /* Weather / location form grids collapse to one column. */
  .events-form-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/** stylesheets/src/expenses.css **/
/* ============================================================
   Expenses report feature — Ocean theme
   ------------------------------------------------------------
   Read-only spend report rendered by app/views/expenses/section.scala.html.
   Layout (top-down):
     1. Section frame + headline total badge
     2. Range controls (All time / Year / Custom + date picker)
     3. Breakdown cards (total, by source, by cost type, by component)
   ============================================================ */

.expenses-view {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.expenses-total-badge {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------
   Range controls
   ------------------------------------------------------------ */
.expenses-range-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1rem;
  padding: 0.75rem 1rem;
  background: var(--color-surface, rgba(255, 255, 255, 0.04));
  border: 1px solid var(--color-border, rgba(255, 255, 255, 0.08));
  border-radius: 0.5rem;
}

.expenses-range-modes {
  display: inline-flex;
  gap: 0.5rem;
}

.expenses-range-mode-btn {
  min-width: 5.5rem;
}

.expenses-range-year,
.expenses-range-custom {
  display: inline-flex;
  align-items: flex-end;
  gap: 0.75rem;
}

.expenses-range-field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.expenses-range-label {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.7;
}

/* ------------------------------------------------------------
   Async / error / empty states
   ------------------------------------------------------------ */
.expenses-loading,
.expenses-empty-state {
  padding: 1.5rem;
  text-align: center;
  opacity: 0.8;
}

/* ------------------------------------------------------------
   Breakdown cards
   ------------------------------------------------------------ */
.expenses-breakdowns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
}

.expenses-card {
  padding: 1rem 1.25rem;
  background: var(--color-surface, rgba(255, 255, 255, 0.04));
  border: 1px solid var(--color-border, rgba(255, 255, 255, 0.08));
  border-radius: 0.5rem;
}

.expenses-card-title {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.7;
  margin-bottom: 0.75rem;
}

.expenses-card-total {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.expenses-card-total-amount {
  font-size: 2rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--color-gold-light, #e8b56a);
}

.expenses-table {
  width: 100%;
  border-collapse: collapse;
}

.expenses-table td {
  padding: 0.4rem 0;
  border-bottom: 1px solid var(--color-border, rgba(255, 255, 255, 0.06));
}

.expenses-table tr:last-child td {
  border-bottom: none;
}

.expenses-table-label {
  text-align: left;
}

.expenses-table-amount {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  padding-left: 1rem;
}

/* ------------------------------------------------------------
   Universal Log Modal — Expenses section cost-line rows
   ------------------------------------------------------------ */
.events-expense-row {
  display: grid;
  grid-template-columns: 7rem 7rem 1fr 1fr auto;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.5rem;
}

.events-expense-add {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 0.5rem;
}

.events-expense-total {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.events-expense-row-remove-btn {
  padding: 0.25rem 0.5rem;
}

@media (max-width: 640px) {
  .events-expense-row {
    grid-template-columns: 1fr 1fr;
  }
}

/* ------------------------------------------------------------
   Maintenance task / work-item cost-line editor
   ------------------------------------------------------------ */
.cost-line-row {
  display: grid;
  grid-template-columns: 8rem 8rem 1fr auto;
  gap: 0.5rem;
  align-items: center;
  margin-bottom: 0.5rem;
}

.cost-line-row .form-group {
  margin-bottom: 0;
}

.cost-lines-footer {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 0.25rem;
}

.cost-lines-subtotal {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 640px) {
  .cost-line-row {
    grid-template-columns: 1fr 1fr;
  }
}

/* ------------------------------------------------------------
   Read-only cost-line display (task / work-item detail modals)
   ------------------------------------------------------------ */
.cost-lines-display {
  margin-top: 0.5rem;
}

.cost-lines-display-title {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.7;
  margin-bottom: 0.35rem;
}

.cost-lines-display-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.cost-lines-display-row {
  display: grid;
  grid-template-columns: 6rem 1fr auto;
  gap: 0.5rem;
  align-items: baseline;
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--color-border, rgba(255, 255, 255, 0.06));
}

.cost-lines-display-row:last-child {
  border-bottom: none;
}

.cost-lines-display-note {
  opacity: 0.75;
}

.cost-lines-display-amount,
.cost-lines-display-subtotal-amount,
.cost-lines-grand-total-amount {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.cost-lines-display-subtotal {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.35rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.cost-lines-grand-total {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  align-items: baseline;
  margin-top: 0.75rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--color-border, rgba(255, 255, 255, 0.12));
  font-weight: 700;
}

.cost-lines-grand-total-amount {
  font-size: 1.1rem;
  color: var(--color-gold-light, #e8b56a);
}

@media (max-width: 640px) {
  .cost-lines-display-row {
    grid-template-columns: 5rem 1fr auto;
  }
}

/** stylesheets/src/gpx.css **/
/* ── GPX Viewer ──────────────────────────────────────────────── */
.gpx-view {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}

.gpx-controls {
  align-items: center;
  flex-wrap: wrap;
}

.gpx-control-item {
  margin-bottom: 0;
}

.gpx-file-input {
  max-width: 260px;
}

.gpx-upload-trigger {
  min-width: 170px;
}

.gpx-select {
  width: 110px;
}

.gpx-range {
  width: 130px;
}

.gpx-dashboard {
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.8rem 1rem;
  min-height: 42px;
  display: flex;
  align-items: center;
}

.gpx-dashboard-empty-state {
  color: var(--color-text-secondary);
  font-style: italic;
}

.locked-badge {
  background: #e74c3c;
  color: #ffffff;
  border-radius: var(--radius-sm);
  padding: 0.12rem 0.4rem;
  font-size: 0.72rem;
  font-weight: 700;
  margin-right: 0.45rem;
}

.gpx-map {
  height: 450px;
  width: 100%;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  cursor: crosshair;
  overflow: hidden;
}

.gpx-histogram {
  height: 220px;
  width: 100%;
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.4rem;
}

.gpx-histogram-empty {
  color: var(--color-text-secondary);
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-style: italic;
}

.gpx-bar {
  cursor: pointer;
  transition: opacity 120ms ease;
}

.gpx-bar:hover {
  opacity: 1;
}

/* ── Phone layout (breakpoint convention: variables.css) ─────────────────
   The map yields to the controls + dashboard + histogram instead of eating
   the whole viewport. Hover inspection needs no touch-specific work: both the
   Leaflet segments and the D3 bars already carry `click` handlers that LOCK
   the tapped point into the dashboard line — taps get the same inspector the
   mouse gets. Deep analysis remains desktop-first by design. */
@media (max-width: 640px) {
  .gpx-map {
    height: min(450px, 55vh);
    height: min(450px, 55dvh);
  }

  .gpx-file-input,
  .gpx-upload-trigger {
    max-width: none;
    flex: 1 1 100%;
  }
}


/** stylesheets/src/drive.css **/
/* ── drive ────────────────────────────────────────────── */
.drive-toolbar {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
}

.drive-toolbar label {
  color: var(--color-text-secondary);
  min-width: 110px;
}

.drive-toolbar .input {
  max-width: 360px;
}

.drive-root-component-select {
  min-width: 280px;
  max-width: 420px;
  background: rgba(10, 24, 43, 0.7);
  border-color: var(--color-border);
  color: var(--color-text-primary);
}

.drive-layout {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.drive-summary {
  display: flex;
  align-items: center;
  gap: 1rem;
  color: var(--color-text-secondary);
}

/* Drive storage quota indicator: horizontal bar whose fill color reflects
 * how close the scope is to its quota. Width is set inline via ng-attr-style,
 * tone is set via a modifier class. Hover/focus exposes the exact
 * "Used 3.8 MB / 1.0 GB" string via the wrapper's title attribute. */
.drive-storage-indicator {
  flex: 1 1 240px;
  min-width: 180px;
  max-width: 360px;
  cursor: help;
}

.drive-storage-bar {
  position: relative;
  width: 100%;
  height: 0.6rem;
  background: var(--color-ocean-deepest, rgba(0, 0, 0, 0.35));
  border: 1px solid var(--color-border);
  border-radius: 999px;
  overflow: hidden;
}

.drive-storage-bar-fill {
  height: 100%;
  border-radius: inherit;
  transition: width 250ms ease-out, background-color 200ms ease-out;
}

.drive-storage-bar-fill-blue   { background: var(--color-ocean-mist); }
.drive-storage-bar-fill-orange { background: var(--color-warning); }
.drive-storage-bar-fill-red    { background: var(--color-danger); }

.drive-storage-indicator-fallback {
  color: var(--color-text-secondary);
}

.drive-breadcrumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.drive-bulk-actions {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.drive-bulk-actions-summary {
  color: var(--color-text-secondary);
  min-width: 86px;
}

.drive-bulk-destination-select {
  min-width: 280px;
  max-width: 420px;
}

.drive-content {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: 1rem;
}

.drive-panel {
  background: var(--color-ocean-deep);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  padding: 0.75rem;
}

.drive-panel h3 {
  margin-bottom: 0.5rem;
}

.drive-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-bottom: 0.5rem;
}

.drive-panel-header h3 {
  margin-bottom: 0;
}

.drive-upload-status {
  margin-bottom: 0.6rem;
  font-size: 0.82rem;
  color: var(--color-text-secondary);
}

.drive-upload-status-success {
  color: var(--color-success);
}

.drive-upload-status-error {
  color: var(--color-danger);
}

.drive-upload-queue {
  margin-bottom: 0.6rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.55rem;
  background: rgba(5, 13, 26, 0.18);
}

.drive-upload-queue-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.4rem;
  font-size: 0.78rem;
  color: var(--color-text-secondary);
}

.drive-upload-queue-list {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.drive-upload-queue-progress {
  margin-bottom: 0.35rem;
  font-size: 0.74rem;
  color: var(--color-gold-light);
}

.drive-upload-queue-item {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.76rem;
  min-width: 0;
}

.drive-upload-queue-name {
  color: var(--color-text-primary);
  max-width: 320px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.drive-upload-queue-status {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
}

.drive-upload-queue-status-uploading {
  color: var(--color-gold-light);
}

.drive-upload-queue-status-success {
  color: var(--color-success);
}

.drive-upload-queue-status-error {
  color: var(--color-danger);
}

.drive-upload-queue-message {
  color: var(--color-text-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.drive-upload-queue-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-left: auto;
}

.drive-upload-hint {
  margin-bottom: 0.6rem;
  font-size: 0.76rem;
  color: var(--color-text-muted);
}

.drive-file-controls {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.6rem;
}

.drive-file-search {
  min-width: 220px;
  max-width: 320px;
}

.drive-file-sort,
.drive-file-sort-direction {
  min-width: 140px;
  max-width: 180px;
}

.drive-select-all-visible {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--color-text-secondary);
  font-size: 0.8rem;
}

.drive-checkbox {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  cursor: pointer;
}

.drive-checkbox input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.drive-checkbox-indicator {
  width: 1rem;
  height: 1rem;
  border: 1px solid rgba(148, 163, 184, 0.75);
  border-radius: 0.2rem;
  background: rgba(8, 18, 33, 0.7);
  position: relative;
}

.drive-checkbox input[type="checkbox"]:checked + .drive-checkbox-indicator {
  border-color: var(--color-gold-light);
  background: rgba(201, 168, 76, 0.2);
}

.drive-checkbox input[type="checkbox"]:checked + .drive-checkbox-indicator::after {
  content: '';
  position: absolute;
  left: 0.28rem;
  top: 0.04rem;
  width: 0.28rem;
  height: 0.58rem;
  border: solid var(--color-gold-light);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.drive-checkbox-compact {
  justify-content: center;
}

.drive-file-preview-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  cursor: pointer;
  color: var(--color-text-secondary);
  font-size: 0.78rem;
}

.drive-file-preview-toggle input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.drive-file-preview-toggle-slider {
  width: 2.1rem;
  height: 1.2rem;
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.35);
  position: relative;
  transition: background 0.2s ease;
}

.drive-file-preview-toggle-slider::after {
  content: '';
  width: 0.9rem;
  height: 0.9rem;
  border-radius: 50%;
  background: #fff;
  position: absolute;
  top: 0.15rem;
  left: 0.15rem;
  transition: transform 0.2s ease;
}

.drive-file-preview-toggle input[type="checkbox"]:checked + .drive-file-preview-toggle-slider {
  background: rgba(201, 168, 76, 0.55);
}

.drive-file-preview-toggle input[type="checkbox"]:checked + .drive-file-preview-toggle-slider::after {
  transform: translateX(0.9rem);
}

.drive-panel-drag-active {
  border-color: var(--color-border-gold);
  box-shadow: inset 0 0 0 1px rgba(201, 168, 76, 0.35);
  background: rgba(22, 51, 88, 0.4);
}

.drive-directory-tree {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.drive-directory-tree-node {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.drive-directory-tree-row {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  min-width: 0;
  border-radius: var(--radius-sm);
}

.drive-directory-tree-row-selected {
  background: rgba(74, 120, 181, 0.18);
  box-shadow: inset 0 0 0 1px rgba(133, 170, 230, 0.28);
}

.drive-directory-tree-toggle,
.drive-directory-tree-toggle-spacer {
  width: 1.5rem;
  min-width: 1.5rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.drive-directory-tree-toggle {
  border: none;
  background: transparent;
  color: var(--color-text-muted);
  border-radius: var(--radius-sm);
  cursor: pointer;
  padding: 0.25rem;
}

.drive-directory-tree-toggle:hover {
  background: rgba(255, 255, 255, 0.04);
  color: var(--color-text-primary);
}

.drive-directory-tree-label {
  flex: 1 1 auto;
  min-width: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  border: none;
  background: transparent;
  color: var(--color-text-primary);
  text-align: left;
  padding: 0.35rem 0.4rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.drive-directory-tree-label:hover {
  background: rgba(255, 255, 255, 0.04);
}

.drive-directory-tree-row-selected .drive-directory-tree-label {
  color: var(--color-gold-light);
}

.drive-directory-tree-folder-icon {
  width: 1.2rem;
  min-width: 1.2rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.drive-directory-tree-actions {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  margin-left: auto;
  padding-right: 0.1rem;
}

.drive-directory-tree-children {
  margin-left: 0.8rem;
  padding-left: 0.7rem;
  border-left: 1px solid rgba(148, 163, 184, 0.18);
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.drive-directory-tree-files {
  margin-left: 0.8rem;
  padding-left: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
}

.drive-directory-file-node {
  border: none;
  background: transparent;
  color: var(--color-text-secondary);
  text-align: left;
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.22rem 0.25rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
}

.drive-directory-file-node:hover {
  background: rgba(255, 255, 255, 0.04);
  color: var(--color-text-primary);
}

.drive-directory-file-icon {
  width: 1rem;
  min-width: 1rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.drive-file-preview-cell {
  min-width: 220px;
}

.drive-file-preview-image-shell {
  width: 210px;
}

.drive-file-preview-image {
  width: 100%;
  height: auto;
  display: block;
}

.drive-file-preview-status {
  color: var(--color-text-muted);
  font-size: 0.74rem;
}

.drive-preview-modal {
  width: min(92vw, 1040px);
}

.drive-preview-modal-body {
  min-height: min(70vh, 680px);
}

.drive-preview-image-shell {
  width: 100%;
  min-height: min(68vh, 640px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: rgba(7, 18, 34, 0.88);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.drive-preview-image {
  width: 100%;
  max-height: min(68vh, 640px);
  object-fit: contain;
  display: block;
}

.drive-folder-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.drive-folder-actions {
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.drive-file-table {
  width: 100%;
  border-collapse: collapse;
}

.drive-file-table th,
.drive-file-table td {
  text-align: left;
  padding: 0.45rem;
  border-bottom: 1px solid var(--color-border);
  vertical-align: top;
}

.drive-file-table th {
  color: var(--color-text-secondary);
  font-weight: 600;
}

.drive-file-actions {
  display: flex;
  gap: 0.4rem;
  align-items: flex-start;
  flex-wrap: wrap;
}

.drive-file-name {
  color: var(--color-text-primary);
}

/* Theme-file validation badge (metadata.themeValidation, branding.js). Token colors only. */
.drive-file-theme-badge {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.05rem 0.4rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--color-border);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-secondary);
  vertical-align: middle;
}

.drive-file-theme-badge-complete,
.drive-file-theme-badge-compatible {
  color: var(--color-success);
  border-color: var(--color-success);
}

.drive-file-theme-badge-incompatible {
  color: var(--color-danger);
  border-color: var(--color-danger);
}

.drive-file-info-line {
  margin-top: 0.18rem;
  color: var(--color-text-muted);
  font-size: 0.72rem;
  line-height: 1.35;
}

/* ── Phone layout (breakpoint convention: variables.css) ─────────────────
   The two-pane [tree | files] grid stacks: folders above files, with the
   tree capped to a scrollable band so the file list stays within a thumb's
   reach. The file table renders as cards via .data-table-cardable
   (tables.css); the one drive-specific addition is pinning the selection
   checkbox to the card's top-right corner so bulk move/delete stays
   write-possible on phones. */
@media (max-width: 640px) {
  .drive-content {
    grid-template-columns: minmax(0, 1fr);
  }

  .drive-directory-tree {
    max-height: 35vh;
    max-height: 35dvh;
    overflow-y: auto;
  }

  .drive-bulk-destination-select {
    min-width: 0;
    width: 100%;
    max-width: none;
  }

  .drive-file-search,
  .drive-file-sort,
  .drive-file-sort-direction {
    min-width: 0;
    flex: 1 1 40%;
    max-width: none;
  }

  .drive-file-table.data-table-cardable tbody tr {
    position: relative;
  }

  .drive-file-select-cell {
    position: absolute;
    top: 0.55rem;
    right: 0.75rem;
  }

  /* Keep the file name clear of the pinned checkbox. */
  .drive-file-table.data-table-cardable tbody td.card-cell-primary {
    padding-right: 2.2rem;
  }
}


/** stylesheets/src/charters.css **/
/* Admin charters section styling. Concatenated into main.css. Reuses the app's existing data-table, modal,
   and form-fieldset components; only the additions specific to charters live here. */

/* Drag-to-reorder handle on the shared editable image thumbnail strip. */
.image-thumbnail-drag-handle {
  position: absolute;
  top: 4px;
  left: 4px;
  z-index: 2;
  cursor: grab;
  font-size: 13px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  user-select: none;
}
.image-thumbnail-drag-handle:active { cursor: grabbing; }

/* Touch reorder alternative: bottom-corner nudge buttons, revealed only on
   coarse pointers (the drag handle is mouse-only). Interaction affordances
   key off pointer type — convention in variables.css. */
.image-thumbnail-nudge {
  display: none;
  position: absolute;
  bottom: 4px;
  z-index: 2;
  padding: 0 6px;
  font-size: 16px;
  line-height: 1.4;
  border-radius: 4px;
  /* Same on-image scrim look as the drag handle above, via theme tokens. */
  background: color-mix(in srgb, var(--color-ocean-deepest) 65%, transparent);
  color: var(--color-text-primary);
}
.image-thumbnail-nudge-left { left: 4px; }
.image-thumbnail-nudge-right { right: 4px; }

@media (pointer: coarse) {
  .image-thumbnail-nudge {
    display: inline-flex;
    /* Deliberate exception to the 44px .btn-icon touch floor (buttons.css):
       two 44px buttons cannot fit an 80px thumbnail. 32px on opposite corners
       keeps the targets apart, which matters more here than raw size. */
    min-width: 0;
    min-height: 0;
    width: 32px;
    height: 32px;
    align-items: center;
    justify-content: center;
  }
}

/* Repeatable YouTube video rows in the charter form. */
.charter-video-rows {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.charter-video-row {
  display: flex;
  gap: 8px;
  align-items: center;
}

.charter-video-row .charter-video-id {
  font-family: monospace;
  font-size: 12px;
  white-space: nowrap;
}

.charter-video-add-row {
  display: flex;
  gap: 8px;
  margin-top: 8px;
}

.image-thumbnail-published {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  font-size: 0.8rem;
}

.image-thumbnail-share {
  display: block;
  width: 100%;
  margin-top: 6px;
}

.image-carousel-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  margin-top: 6px;
}

.image-carousel-published {
  font-size: 0.75rem;
  color: var(--color-text-secondary);
  letter-spacing: 0.2px;
}

.charter-price-row {
  display: flex;
  gap: 8px;
}

.charter-price-row .form-control { flex: 1; }

/* Wider modal for the charter form/detail (lots of fields). */
.modal.modal-lg { max-width: 820px; width: 92%; }

.detail-list {
  margin: 0;
  padding-left: 18px;
}
.detail-list li { margin: 4px 0; }

.form-label-hint {
  font-weight: 400;
  font-size: 0.75rem;
  color: var(--color-text-secondary);
  letter-spacing: 0.2px;
}

.charter-description-textarea {
  font-family: "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 0.82rem;
  line-height: 1.5;
}

/* Markdown preview inside the admin charter detail modal (rendered by markdown-view).
   Mirrors the public brochure look using the app's Ocean/gold theme variables. */
.charter-description.markdown-body {
  color: var(--color-text-primary);
  font-size: 0.92rem;
  line-height: 1.7;
  white-space: normal;
}
.charter-description.markdown-body > :first-child { margin-top: 0; }
.charter-description.markdown-body p { margin: 0 0 0.9em; }
.charter-description.markdown-body h1,
.charter-description.markdown-body h2,
.charter-description.markdown-body h3,
.charter-description.markdown-body h4 {
  font-family: Georgia, "Times New Roman", serif;
  color: var(--color-gold-light);
  line-height: 1.25;
  margin: 1.1em 0 0.45em;
}
.charter-description.markdown-body h1 { font-size: 1.5em; }
.charter-description.markdown-body h2 {
  font-size: 1.28em;
  padding-bottom: 0.3em;
  border-bottom: 1px solid var(--color-border-gold);
}
.charter-description.markdown-body h3 { font-size: 1.12em; color: var(--color-gold); }
.charter-description.markdown-body strong { color: var(--color-gold-light); }
.charter-description.markdown-body em { font-style: italic; }
.charter-description.markdown-body a { color: var(--color-gold-light); text-decoration: underline; }
.charter-description.markdown-body ul,
.charter-description.markdown-body ol { margin: 0 0 1em; padding-left: 0; list-style: none; }
.charter-description.markdown-body li { position: relative; padding-left: 1.5em; margin: 0 0 0.45em; }
.charter-description.markdown-body ul > li::before {
  content: "\25C6";
  position: absolute;
  left: 0;
  top: 0.05em;
  font-size: 0.7em;
  line-height: 1.9;
  color: var(--color-gold);
}
.charter-description.markdown-body ol { counter-reset: charter-admin-ol; }
.charter-description.markdown-body ol > li { counter-increment: charter-admin-ol; }
.charter-description.markdown-body ol > li::before {
  content: counter(charter-admin-ol) ".";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--color-gold);
  font-weight: 600;
}
.charter-description.markdown-body blockquote {
  margin: 1.1em 0;
  padding: 10px 16px;
  border-left: 3px solid var(--color-gold);
  border-radius: 0 8px 8px 0;
  background: var(--color-gold-subtle);
  font-style: italic;
}
.charter-description.markdown-body blockquote p { margin: 0; }
.charter-description.markdown-body hr {
  border: 0;
  height: 1px;
  margin: 1.6em 0;
  background: linear-gradient(90deg, transparent, var(--color-border-gold), transparent);
}

/** stylesheets/src/home.css **/
/* ── Home dashboard (bento-box widget canvas) ──────────────────────────────
   Free-form positioning canvas. The canvas itself is sized to an integer
   number of grid blocks via inline width/height set by `home.js`
   (`app.homeCanvasPixelStyle()`), then centered horizontally and
   top-aligned within the viewport. Widgets are absolutely positioned
   inside the canvas in pixel space derived from that same block grid.
*/

.home-section {
  /* The home view renders inside .main-content.main-content-fluid, which drops
     the 1200px column cap and padding so this section already fills the area to
     the right of the nav rail. No viewport breakout needed; just fill the
     parent and let .home-canvas center itself via margin:auto. */
  position: relative;
  width: 100%;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.home-canvas {
  /* Width/height come from app.homeCanvasPixelStyle() so the canvas always
     measures an integer number of grid blocks. Margin auto centers it
     horizontally; vertically it sits at the top of the section, which is
     itself directly under the view tabs. */
  position: relative;
  margin: 0 auto;
  box-sizing: border-box;
  background-image:
    linear-gradient(to right, var(--surface-border-subtle, rgba(255, 255, 255, 0.04)) 1px, transparent 1px),
    linear-gradient(to bottom, var(--surface-border-subtle, rgba(255, 255, 255, 0.04)) 1px, transparent 1px);
  background-size: 150px 150px;
  border: 1px solid var(--surface-border-subtle, rgba(255, 255, 255, 0.06));
  border-radius: 8px;
  overflow: hidden;
}

.home-widget {
  position: absolute;
  display: flex;
  flex-direction: column;
  background: var(--surface-elevated, #1f2630);
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  overflow: hidden;
  transition: box-shadow 120ms ease, border-color 120ms ease;
}

.home-widget-invalid {
  border-color: #e34a4a;
  box-shadow: 0 0 0 2px rgba(227, 74, 74, 0.6), 0 4px 12px rgba(0, 0, 0, 0.25);
}

.home-widget-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--surface-elevated-strong, #2a323f);
  border-bottom: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  cursor: move;
  user-select: none;
  font-weight: 600;
}

.home-widget-header-icon {
  font-size: 1rem;
}

.home-widget-header-title {
  flex: 1 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.home-widget-body {
  flex: 1 1 auto;
  padding: 12px;
  color: var(--color-text-muted);
  font-size: 0.85rem;
  overflow: hidden;
}

.home-widget-resize {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 18px;
  height: 18px;
  cursor: nwse-resize;
  background:
    linear-gradient(
      135deg,
      transparent 0%,
      transparent 50%,
      var(--surface-border, rgba(255, 255, 255, 0.4)) 50%,
      var(--surface-border, rgba(255, 255, 255, 0.4)) 60%,
      transparent 60%,
      transparent 70%,
      var(--surface-border, rgba(255, 255, 255, 0.4)) 70%,
      var(--surface-border, rgba(255, 255, 255, 0.4)) 80%,
      transparent 80%
    );
}

/* Phone-only header adornments (revealed in the phone media query below):
   collapse caret + the one-line summary a collapsed widget shows. */
.home-widget-phone-collapse-caret,
.home-widget-header-phone-summary {
  display: none;
}

/* ── Phone stacked mode (breakpoint convention: variables.css) ───────────
   Below the phone breakpoint the free-form pixel canvas becomes a plain
   full-width column: home.js stops emitting inline left/top/width/height
   (only a flex `order` derived from the desktop y/x), drag + resize are
   disabled, and each widget header becomes a collapse toggle with per-device
   persisted state. Widgets are natural-height, capped so one long feed can't
   consume the whole page. */
@media (max-width: 640px) {
  .home-canvas {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    background-image: none;
    border: none;
    overflow: visible;
  }

  .home-widget {
    position: static;
  }

  .home-widget-header {
    cursor: pointer;
  }

  .home-widget-phone-collapse-caret {
    display: inline-block;
    color: var(--color-text-muted);
    font-size: 0.75rem;
    flex-shrink: 0;
  }

  .home-widget-header-phone-summary {
    display: inline-block;
    color: var(--color-text-muted);
    font-size: 0.72rem;
    font-weight: 500;
    white-space: nowrap;
    flex-shrink: 0;
  }

  .home-widget-body {
    max-height: 70vh;
    max-height: 70dvh;
    overflow-y: auto;
  }

  .home-widget-resize {
    display: none;
  }

  /* Auto-height calendar cells collapse to nothing without a floor. */
  .home-calendar-widget-day {
    min-height: 2.2rem;
  }
}

/* ── Saved-layouts list (rendered in the Settings modal) ─────────────────
   The dashboard saves an ordered list of named layouts. The settings modal
   renders that list using these classes, letting the user rename or delete
   individual entries.
*/
.settings-home-layout-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.settings-home-layout-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 12px;
  background: var(--surface-elevated, #1f2630);
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  border-radius: 6px;
}

.settings-home-layout-row-active {
  border-color: var(--color-gold, #d6af5c);
  box-shadow: 0 0 0 1px var(--color-gold, #d6af5c);
}

.settings-home-layout-row-summary {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  flex: 1 1 auto;
  min-width: 0;
}

.settings-home-layout-row-name-input {
  flex: 1 1 220px;
  min-width: 0;
  padding: 6px 10px;
  background: var(--surface-base, #14181f);
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  border-radius: 4px;
  color: inherit;
  font: inherit;
  font-weight: 600;
}

.settings-home-layout-row-name-input:focus {
  outline: none;
  border-color: var(--color-gold, #d6af5c);
}

.settings-home-layout-row-count {
  color: var(--color-text-muted);
  font-size: 0.85rem;
  flex-shrink: 0;
}

.settings-home-layout-row-current-badge {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--color-gold-subtle, rgba(214, 175, 92, 0.18));
  color: var(--color-gold, #d6af5c);
  flex-shrink: 0;
}

.settings-home-layout-row-delete {
  flex-shrink: 0;
}

/* ── Drive widget ────────────────────────────────────────────────────────
   Compact file-browser tile that lives inside a `.home-widget-body`. The
   widget body sets its own pixel height/width (computed from the bento
   block grid), so the drive widget fills that with a vertical layout:
   toolbar on top, scrollable content below.
*/
.home-widget-body-drive {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}

.home-drive-widget {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  font-size: 0.78rem;
  color: var(--color-text-primary);
}

.home-drive-widget-toolbar {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--surface-border, rgba(255, 255, 255, 0.06));
  margin-bottom: 0.4rem;
}

.home-drive-widget-breadcrumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.15rem;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
}

.home-drive-widget-breadcrumbs-segment-wrap {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
}

.home-drive-widget-breadcrumbs-segment {
  border: none;
  background: transparent;
  color: var(--color-text-secondary);
  cursor: pointer;
  padding: 0.1rem 0.25rem;
  font-size: 0.74rem;
  line-height: 1.2;
  border-radius: var(--radius-sm);
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.home-drive-widget-breadcrumbs-segment:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.06);
  color: var(--color-text-primary);
}

.home-drive-widget-breadcrumbs-segment-current {
  color: var(--color-gold-light);
  font-weight: 600;
  cursor: default;
  /* The current segment is rendered as `<button disabled>` so the user can't
     click it. Browsers default disabled buttons to the system GrayText / lower
     opacity, which on the day-theme's light background made the label look
     completely invisible. Lock the appearance to our explicit colors. */
  opacity: 1;
}

.home-drive-widget-breadcrumbs-segment-current:hover {
  background: transparent;
  color: var(--color-gold-light);
}

.home-drive-widget-breadcrumbs-separator {
  color: var(--color-text-muted);
  font-size: 0.74rem;
}

.home-drive-widget-view-toggles {
  display: inline-flex;
  gap: 0.2rem;
  flex-shrink: 0;
}

.home-drive-widget-view-toggle {
  padding: 0.2rem 0.4rem;
  line-height: 1;
  font-size: 0.78rem;
}

.home-drive-widget-content {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

.home-drive-widget-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  padding: 1rem 0.5rem;
  color: var(--color-text-muted);
  font-size: 0.78rem;
  text-align: center;
}

.home-drive-widget-empty-icon {
  font-size: 1.6rem;
}

.home-drive-widget-loading {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--color-text-muted);
  font-size: 0.78rem;
  padding: 0.4rem;
}

.home-drive-widget-loading-spinner {
  margin-right: 0.3rem;
}

/* ── List view ───────────────────────────────────────────────────────── */
.home-drive-widget-list {
  width: 100%;
  /* `table-layout: fixed` is REQUIRED for `overflow: hidden` + `text-overflow:
     ellipsis` to work on `<td>` cells. Without it the table sizes columns to
     content and the Name cell keeps expanding instead of truncating, so the
     filename gets clipped by the row width while the icon (start) and the
     date column (end) stay visible. */
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 0.74rem;
}

.home-drive-widget-list thead th {
  position: sticky;
  top: 0;
  background: var(--surface-elevated-strong, #2a323f);
  color: var(--color-text-secondary);
  font-weight: 600;
  text-align: left;
  padding: 0.25rem 0.35rem;
  cursor: pointer;
  user-select: none;
  border-bottom: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  white-space: nowrap;
}

.home-drive-widget-list thead th:hover {
  color: var(--color-text-primary);
}

.home-drive-widget-list-column-active {
  color: var(--color-gold-light);
}

.home-drive-widget-list-sort-indicator {
  font-size: 0.7rem;
  margin-left: 0.15rem;
}

.home-drive-widget-list tbody tr {
  cursor: pointer;
}

.home-drive-widget-list tbody tr:hover {
  background: rgba(255, 255, 255, 0.04);
}

.home-drive-widget-list tbody td {
  padding: 0.25rem 0.35rem;
  border-bottom: 1px solid var(--surface-border-subtle, rgba(255, 255, 255, 0.04));
  vertical-align: middle;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.home-drive-widget-list-cell-name {
  /* Stay a normal `display: table-cell` so the cell's bottom border lines up
     pixel-perfectly with the Size/Created cells in the same row. The flex
     layout for [icon][label] lives on the inner wrapper below, NOT on the
     `<td>` itself — mixing `display: flex` with `display: table-cell` siblings
     causes a ~1–2px height mismatch and a jagged row separator. */
  min-width: 0;
}

.home-drive-widget-list-cell-name-inner {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
}

.home-drive-widget-list-name-label {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.home-drive-widget-list-icon {
  font-size: 0.95rem;
  color: var(--color-text-secondary);
  flex-shrink: 0;
}

.home-drive-widget-list-row-folder .home-drive-widget-list-icon {
  color: var(--color-gold-light);
}

.home-drive-widget-list-cell-muted {
  color: var(--color-text-muted);
}

/* In `table-layout: fixed`, column widths come from the first row (header).
   Pin Size + Created to small fixed widths so Name absorbs the remaining
   horizontal space (and its `text-overflow: ellipsis` actually has somewhere
   to truncate at). */
.home-drive-widget-list-column-name {
  width: auto;
}

.home-drive-widget-list-column-size,
.home-drive-widget-list-cell-size {
  width: 4.5rem;
  text-align: right;
}

.home-drive-widget-list-column-created-at,
.home-drive-widget-list-cell-created-at {
  width: 5.5rem;
  text-align: right;
}

/* ── Preview (tile) view ─────────────────────────────────────────────── */
.home-drive-widget-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(78px, 1fr));
  gap: 0.4rem;
  padding: 0.1rem 0.05rem;
}

.home-drive-widget-tile {
  border: 1px solid transparent;
  background: transparent;
  color: var(--color-text-primary);
  padding: 0.3rem 0.2rem;
  border-radius: var(--radius-sm);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  text-align: center;
  min-width: 0;
}

.home-drive-widget-tile:hover {
  background: rgba(255, 255, 255, 0.04);
  border-color: var(--surface-border, rgba(255, 255, 255, 0.08));
}

.home-drive-widget-tile-thumbnail {
  width: 100%;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(7, 18, 34, 0.55);
  border-radius: var(--radius-sm);
  overflow: hidden;
}

.home-drive-widget-tile-icon {
  font-size: 2rem;
  color: var(--color-text-secondary);
}

.home-drive-widget-tile-folder .home-drive-widget-tile-icon {
  color: var(--color-gold-light);
}

.home-drive-widget-tile-icon-loading {
  opacity: 0.5;
}

.home-drive-widget-tile-image-shell {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.home-drive-widget-tile-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.home-drive-widget-tile-label {
  width: 100%;
  font-size: 0.7rem;
  line-height: 1.15;
  color: var(--color-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Ship's Log widget ───────────────────────────────────────────────────
   Compact, filterable, expand/collapse feed of the same `app.eventState.events`
   the full /event view consumes. Reuses the per-category color classes
   (`events-pill-<key>` and `events-pill-active`) defined in event.css so a
   category recolor only needs to happen in one place.
*/
.home-widget-body-ship-log {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}

.home-ship-log-widget {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  font-size: 0.78rem;
  color: var(--color-text-primary);
  gap: 0.35rem;
  overflow: hidden;
}

.home-ship-log-widget-loading,
.home-ship-log-widget-no-vessel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem;
  color: var(--color-text-muted);
  font-size: 0.78rem;
}

.home-ship-log-widget-spinner {
  width: 0.9rem;
  height: 0.9rem;
}

.home-ship-log-widget-no-vessel-icon {
  font-size: 1.1rem;
}

/* Compact override of the standard `.events-pill` look so 11 pills fit
   inside a 2×2 tile without horizontal overflow. The base padding / colour
   rules still come from event.css; we only override what we need to make
   the pill tighter. */
.home-ship-log-widget-pill-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--surface-border, rgba(255, 255, 255, 0.06));
  flex-shrink: 0;
}

.home-ship-log-widget-pill.events-pill {
  padding: 0.15rem 0.4rem;
  font-size: 0.66rem;
  font-weight: 600;
  gap: 0.2rem;
  line-height: 1.1;
}

.home-ship-log-widget-pill.events-pill i {
  font-size: 0.7rem;
}

.home-ship-log-widget-pill-label {
  /* When the widget is squeezed narrow there's room for an icon but not the
     label; the `title` attribute keeps the meaning discoverable on hover. */
  max-width: 6rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.home-ship-log-widget-feed {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

.home-ship-log-widget-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  padding: 1rem 0.5rem;
  color: var(--color-text-muted);
  font-size: 0.78rem;
  text-align: center;
}

.home-ship-log-widget-empty-icon {
  font-size: 1.4rem;
}

.home-ship-log-widget-entry {
  background: var(--color-ocean-surface, rgba(7, 18, 34, 0.4));
  border: 1px solid var(--color-border, rgba(255, 255, 255, 0.08));
  border-left: 3px solid var(--color-border, rgba(255, 255, 255, 0.16));
  border-radius: var(--radius-sm);
  padding: 0.35rem 0.45rem;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}

.home-ship-log-widget-entry:hover {
  background: var(--color-ocean-light, rgba(74, 120, 181, 0.08));
}

.home-ship-log-widget-entry-expanded {
  background: var(--color-ocean-light, rgba(74, 120, 181, 0.1));
}

/* Per-category left-border accent — mirrors the full /event view's
   `events-entry-category-<key>` colors via the same CSS variables. */
.home-ship-log-widget-entry-category-navigation   { border-left-color: var(--events-color-navigation); }
.home-ship-log-widget-entry-category-fuel         { border-left-color: var(--events-color-fuel); }
.home-ship-log-widget-entry-category-engine       { border-left-color: var(--events-color-engine); }
.home-ship-log-widget-entry-category-maintenance  { border-left-color: var(--events-color-maintenance); }
.home-ship-log-widget-entry-category-weather      { border-left-color: var(--events-color-weather); }
.home-ship-log-widget-entry-category-wildlife     { border-left-color: var(--events-color-wildlife); }
.home-ship-log-widget-entry-category-guests       { border-left-color: var(--events-color-guests); }
.home-ship-log-widget-entry-category-safety       { border-left-color: var(--events-color-safety); }
.home-ship-log-widget-entry-category-mooring      { border-left-color: var(--events-color-mooring); }
.home-ship-log-widget-entry-category-provisioning { border-left-color: var(--events-color-provisioning); }
.home-ship-log-widget-entry-category-general      { border-left-color: var(--events-color-general); }
.home-ship-log-widget-entry-category-checklist_completed { border-left-color: var(--events-color-general); }

.home-ship-log-widget-entry-row {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  min-width: 0;
  font-size: 0.72rem;
}

.home-ship-log-widget-entry-time {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  color: var(--color-text-secondary);
  font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
}

.home-ship-log-widget-entry-time-icon {
  font-size: 0.7rem;
}

.home-ship-log-widget-entry-date {
  color: var(--color-text-muted);
  font-weight: 400;
  margin-left: 0.15rem;
}

.home-ship-log-widget-entry-category {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 0.78rem;
  color: var(--color-text-secondary);
  flex-shrink: 0;
}

.home-ship-log-widget-entry-summary {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-text-primary);
}

.home-ship-log-widget-entry-expanded .home-ship-log-widget-entry-summary {
  white-space: normal;
  text-overflow: clip;
}

.home-ship-log-widget-entry-chevron {
  color: var(--color-text-muted);
  font-size: 0.7rem;
  flex-shrink: 0;
}

/* ── Expanded detail panel ─────────────────────────────────────────── */
.home-ship-log-widget-entry-detail {
  margin-top: 0.35rem;
  padding-top: 0.35rem;
  border-top: 1px dashed var(--surface-border, rgba(255, 255, 255, 0.08));
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.7rem;
}

.home-ship-log-widget-detail-section {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.home-ship-log-widget-detail-section-label {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--color-text-muted);
}

.home-ship-log-widget-detail-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.7rem;
  line-height: 1.3;
}

.home-ship-log-widget-detail-row-meta .home-ship-log-widget-detail-meta-label {
  color: var(--color-text-muted);
}

.home-ship-log-widget-detail-row-meta .home-ship-log-widget-detail-meta-value {
  color: var(--color-text-primary);
  text-align: right;
}

.home-ship-log-widget-detail-row-name {
  color: var(--color-text-secondary);
  display: inline-flex;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
}

.home-ship-log-widget-detail-row-type {
  font-size: 0.6rem;
  color: var(--color-text-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.home-ship-log-widget-detail-row-value {
  color: var(--color-text-primary);
  text-align: right;
  white-space: nowrap;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.home-ship-log-widget-detail-row-unit {
  color: var(--color-text-muted);
  margin-left: 0.15rem;
}

.home-ship-log-widget-detail-text {
  margin: 0;
  color: var(--color-text-primary);
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── Layout-selector strip (above the canvas) ────────────────────────────
   One dot per saved layout, plus a "+" button. The highlighted dot is the
   active layout — clicking another dot switches; clicking + appends a new
   layout seeded with the bundled default widgets and switches to it.
*/
.home-layout-selector {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 8px 0;
  margin: 0 auto 8px;
}

.home-layout-selector-dot {
  width: 14px;
  height: 14px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.25));
  background: var(--surface-elevated, #1f2630);
  cursor: pointer;
  transition: background 120ms ease, transform 120ms ease, border-color 120ms ease;
}

.home-layout-selector-dot:hover {
  transform: scale(1.15);
  border-color: var(--color-gold, #d6af5c);
}

.home-layout-selector-dot-active {
  background: var(--color-gold, #d6af5c);
  border-color: var(--color-gold, #d6af5c);
  box-shadow: 0 0 0 2px rgba(214, 175, 92, 0.25);
}

.home-layout-selector-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border-radius: 50%;
  border: 1px dashed var(--surface-border, rgba(255, 255, 255, 0.35));
  background: transparent;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease, transform 120ms ease;
}

.home-layout-selector-add:hover {
  color: var(--color-gold, #d6af5c);
  border-color: var(--color-gold, #d6af5c);
  transform: scale(1.1);
}

.home-layout-selector-add i {
  font-size: 0.7rem;
}

/* ── Ship's Log + widget ─────────────────────────────────────────────────
   Compact "write half" of the Ship's Log feature. Reuses the same
   `.events-action-tile`, `.events-time-button`, `.events-omnibox` base
   styles as the full /event view's Maritime Bridge; this section only
   contains the widget-specific overrides (tighter padding, smaller fonts)
   so 10-15 pills + a time row + an omnibox can fit inside a 2×2 tile.
*/
.home-widget-body-ship-log-create {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  /* `container-type: inline-size` turns this body into a query container so
     the pill grid + omnibox styles below can scale their font/padding off
     the widget's CURRENT rendered width (set by the bento layout), not the
     viewport. Without this, a 2×2 widget and a 6×4 widget would render
     identical pill sizes. */
  container-type: inline-size;
  container-name: shiplogcreate;
}

.home-ship-log-create-widget {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  gap: 0.4rem;
  overflow: hidden;
  font-size: 0.78rem;
  color: var(--color-text-primary);
}

.home-ship-log-create-widget-settings-button {
  position: absolute;
  top: 0;
  right: 0;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 50%;
  color: var(--color-text-muted);
  cursor: pointer;
  transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}

.home-ship-log-create-widget-settings-button:hover {
  color: var(--color-gold, #d6af5c);
  border-color: var(--color-gold, #d6af5c);
  background: var(--color-gold-subtle, rgba(214, 175, 92, 0.12));
}

.home-ship-log-create-widget-settings-button i {
  font-size: 0.72rem;
}

/* Pill grid: tighter than the /event default (smaller padding/font, narrow
   wrap gap) so more pills fit per row inside the widget. The action-tile
   per-category icon colour still comes from event.css.

   Pills use `flex-grow: 1` with a small flex-basis so they EXPAND to fill
   their wrap row when there are few of them (instead of clustering on the
   left and leaving empty space), and SHRINK to wrap when there are many.
   `flex-basis` is intentionally smaller than the natural pill width so the
   browser's wrap algorithm only triggers when the natural row would overflow. */
.home-ship-log-create-widget-action-grid {
  flex: 1 1 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  padding-right: 1.6rem; /* leave room for the absolutely-positioned gear */
  overflow-y: auto;
  align-content: flex-start;
}

.home-ship-log-create-widget-tile.events-action-tile {
  /* `flex: 1 1 5.5rem` — grow to fill row, shrink as needed, basis ~5.5rem.
     Combined with `max-width` this gives "fill the row when there's space,
     wrap and stay legible when there isn't". */
  flex: 1 1 5.5rem;
  min-width: 4.5rem;
  max-width: 14rem;
  justify-content: center;
  padding: 0.28rem 0.55rem;
  font-size: 0.7rem;
  font-weight: 600;
  gap: 0.3rem;
  line-height: 1.1;
}

.home-ship-log-create-widget-tile.events-action-tile .events-action-tile-icon {
  font-size: 0.72rem;
}

.home-ship-log-create-widget-tile.events-action-tile .events-action-tile-label {
  /* Let labels truncate when the pill is at its minimum (many-pills case);
     when the pill grows (few-pills case) the label has room to render in full. */
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Container-query scaling: bump pill font/padding when the widget itself
   is rendered wider, so a 6-block-wide widget doesn't show pills the same
   tiny size as a 2-block-wide widget. Breakpoints are in container-relative
   `cqw`/`px` to track the WIDGET, not the viewport. */
@container shiplogcreate (min-width: 360px) {
  .home-ship-log-create-widget-tile.events-action-tile {
    flex-basis: 6.5rem;
    font-size: 0.78rem;
    padding: 0.35rem 0.7rem;
  }
  .home-ship-log-create-widget-tile.events-action-tile .events-action-tile-icon {
    font-size: 0.8rem;
  }
}

@container shiplogcreate (min-width: 560px) {
  .home-ship-log-create-widget-tile.events-action-tile {
    flex-basis: 7.5rem;
    font-size: 0.86rem;
    padding: 0.45rem 0.85rem;
  }
  .home-ship-log-create-widget-tile.events-action-tile .events-action-tile-icon {
    font-size: 0.9rem;
  }
}

@container shiplogcreate (min-width: 800px) {
  .home-ship-log-create-widget-tile.events-action-tile {
    flex-basis: 8.5rem;
    font-size: 0.95rem;
    padding: 0.55rem 1.05rem;
  }
  .home-ship-log-create-widget-tile.events-action-tile .events-action-tile-icon {
    font-size: 1rem;
  }
}

/* Empty-state — surfaces a deep-link to Settings when every pill is hidden. */
.home-ship-log-create-widget-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 0.5rem;
  color: var(--color-text-muted);
  font-size: 0.75rem;
  text-align: center;
}

.home-ship-log-create-widget-empty-icon {
  font-size: 1.2rem;
}

.home-ship-log-create-widget-empty-action {
  font-size: 0.7rem;
}

/* Hybrid time row — smaller pill buttons than the /event default so 5
   presets fit on one line at typical widget widths. */
.home-ship-log-create-widget-time-row {
  flex-shrink: 0;
  padding: 0.2rem;
  gap: 0.2rem;
}

.home-ship-log-create-widget-time-row .events-time-button {
  padding: 0.22rem 0.55rem;
  font-size: 0.66rem;
}

/* Omnibox — keep its full-width look but shrink the padding so the Log
   button and input still fit at the widget's narrowest size.

   IMPORTANT: the base `.events-omnibox` rule sets `flex: 1 1 320px`, which is
   correct in the full /event view (where the omnibox sits in a ROW flex
   parent and that means "width-basis 320px"). Inside the home widget the
   omnibox sits in a COLUMN flex parent, so the same shorthand is interpreted
   as "HEIGHT-basis 320px + grow to fill remaining height" — making the
   single-row text input render as a ~320px-tall slab. We MUST reset the
   shorthand here, not just `flex-shrink`, to undo the unwanted height grow. */
.home-ship-log-create-widget-omnibox {
  flex: 0 0 auto;
  align-items: center;
  padding: 0.18rem 0.3rem 0.18rem 0.55rem;
}

.home-ship-log-create-widget-omnibox .events-omnibox-input {
  /* `align-self: center` (via parent `align-items: center` above) keeps the
     input vertically centered without stretching to the row's intrinsic
     height. The fixed `line-height` + padding produces a stable ~1.6rem
     single-row input. */
  flex: 1 1 auto;
  font-size: 0.78rem;
  line-height: 1.2;
  padding: 0.32rem 0.2rem;
}

.home-ship-log-create-widget-omnibox .events-omnibox-save {
  flex: 0 0 auto;
  padding: 0.32rem 0.65rem;
  font-size: 0.72rem;
}

/* ── Settings modal — Ship's Log pill button reorder list ────────────────
   Drag-to-reorder list of all known action tiles with a per-row visibility
   checkbox. Reuses the same `settings-section-*` outer styling other
   sections in the modal use; only the row layout + drag-handle styling
   lives here.
*/
.settings-ship-log-pill-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.settings-ship-log-pill-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: var(--surface-elevated, #1f2630);
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  border-radius: 6px;
  transition: border-color 120ms ease, background 120ms ease, opacity 120ms ease;
}

.settings-ship-log-pill-row-disabled {
  opacity: 0.55;
}

.settings-ship-log-pill-row-dragging {
  opacity: 0.4;
}

.settings-ship-log-pill-row-drop-target {
  border-color: var(--color-gold, #d6af5c);
  background: var(--color-gold-subtle, rgba(214, 175, 92, 0.12));
}

.settings-ship-log-pill-row-drag-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 4px;
  color: var(--color-text-muted);
  cursor: grab;
  flex-shrink: 0;
  user-select: none;
}

.settings-ship-log-pill-row-drag-handle:hover {
  color: var(--color-text-primary);
  background: rgba(255, 255, 255, 0.04);
}

.settings-ship-log-pill-row-drag-handle:active {
  cursor: grabbing;
}

/* Touch reorder alternative: the drag handle is mouse-only, so coarse
   pointers get up/down nudge buttons instead (revealed below). */
.settings-ship-log-pill-row-nudges {
  display: none;
  gap: 0.25rem;
  flex-shrink: 0;
  margin-left: auto;
}

@media (pointer: coarse) {
  .settings-ship-log-pill-row-nudges {
    display: inline-flex;
  }
}

.settings-ship-log-pill-row-label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  cursor: pointer;
}

.settings-ship-log-pill-row-label input[type="checkbox"] {
  flex-shrink: 0;
}

/* The "tile preview" mirrors the actual pill the user sees in the widget,
   minus the click affordance — same `.event-tile-*` category accent class
   is applied so colours stay consistent. */
.settings-ship-log-pill-row-tile-preview {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.32rem 0.7rem;
  background: var(--color-ocean-surface, #1f2630);
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
}

.settings-ship-log-pill-row-tile-icon {
  font-size: 0.85rem;
}

.settings-ship-log-pill-row-tile-text {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 12rem;
}

/* Inherit the per-category icon accent from event.css by applying the same
   class names on the preview wrapper (e.g. `event-tile-navigation`). */
.settings-ship-log-pill-row-tile-preview.event-tile-navigation   .settings-ship-log-pill-row-tile-icon { color: var(--events-color-navigation); }
.settings-ship-log-pill-row-tile-preview.event-tile-fuel         .settings-ship-log-pill-row-tile-icon { color: var(--events-color-fuel); }
.settings-ship-log-pill-row-tile-preview.event-tile-engine       .settings-ship-log-pill-row-tile-icon { color: var(--events-color-engine); }
.settings-ship-log-pill-row-tile-preview.event-tile-maintenance  .settings-ship-log-pill-row-tile-icon { color: var(--events-color-maintenance); }
.settings-ship-log-pill-row-tile-preview.event-tile-weather      .settings-ship-log-pill-row-tile-icon { color: var(--events-color-weather); }
.settings-ship-log-pill-row-tile-preview.event-tile-wildlife     .settings-ship-log-pill-row-tile-icon { color: var(--events-color-wildlife); }
.settings-ship-log-pill-row-tile-preview.event-tile-guests       .settings-ship-log-pill-row-tile-icon { color: var(--events-color-guests); }
.settings-ship-log-pill-row-tile-preview.event-tile-safety       .settings-ship-log-pill-row-tile-icon { color: var(--events-color-safety); }
.settings-ship-log-pill-row-tile-preview.event-tile-mooring      .settings-ship-log-pill-row-tile-icon { color: var(--events-color-mooring); }
.settings-ship-log-pill-row-tile-preview.event-tile-provisioning .settings-ship-log-pill-row-tile-icon { color: var(--events-color-provisioning); }
.settings-ship-log-pill-row-tile-preview.event-tile-general      .settings-ship-log-pill-row-tile-icon { color: var(--events-color-general); }

.settings-ship-log-pill-row-visibility-hint {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  flex-shrink: 0;
}

/* ── Inventory widget ────────────────────────────────────────────────────
   Two stacked sections (low supply + all items) with an optional
   per-location pill bar at the top. When a location pill is active, a
   LOUD orange banner pins itself above the lists so the user can never
   miss that they're looking at a sub-total instead of vessel-wide
   numbers. Every quantity number shows its unit so unit-confusion is
   impossible.
*/
.home-widget-body-inventory {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}

.home-inventory-widget {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  font-size: 0.78rem;
  color: var(--color-text-primary);
  gap: 0.35rem;
  overflow: hidden;
}

.home-inventory-widget-loading,
.home-inventory-widget-no-vessel,
.home-inventory-widget-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem;
  color: var(--color-text-muted);
  font-size: 0.78rem;
  text-align: center;
}

.home-inventory-widget-spinner {
  width: 0.9rem;
  height: 0.9rem;
}

.home-inventory-widget-no-vessel-icon,
.home-inventory-widget-empty-icon {
  font-size: 1.1rem;
}

.home-inventory-widget-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: 0.4rem;
  overflow: hidden;
}

/* The "you are looking at a sub-count" banner. Saturated background +
   left border keep this readable even when the widget is rendered very
   small. The user explicitly asked for this to be visually obvious so
   they don't mistake a sub-count for vessel-wide. */
.home-inventory-widget-filter-banner {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.45rem 0.6rem;
  background: rgba(229, 122, 31, 0.18); /* warm amber wash */
  border: 1px solid rgba(229, 122, 31, 0.55);
  border-left: 4px solid #f4a23a;
  border-radius: 6px;
  color: #f9d8a8;
  font-size: 0.78rem;
  font-weight: 600;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(229, 122, 31, 0.18);
}

.home-inventory-widget-filter-banner-icon {
  font-size: 0.88rem;
  color: #f4a23a;
  flex-shrink: 0;
}

.home-inventory-widget-filter-banner-text {
  flex: 1 1 auto;
  min-width: 0;
}

.home-inventory-widget-filter-banner-text strong {
  color: #ffe8c2;
}

.home-inventory-widget-filter-banner-clear {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.22rem 0.55rem;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 999px;
  color: inherit;
  font-size: 0.7rem;
  font-weight: 600;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 120ms ease, border-color 120ms ease;
}

.home-inventory-widget-filter-banner-clear:hover {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.32);
}

/* Location pill bar — multi-location vessels only. Compact so several
   pills fit per row. */
.home-inventory-widget-pill-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--surface-border, rgba(255, 255, 255, 0.06));
  flex-shrink: 0;
}

.home-inventory-widget-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.6rem;
  background: transparent;
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.18));
  border-radius: 999px;
  color: var(--color-text-secondary);
  font-size: 0.7rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.home-inventory-widget-pill i {
  font-size: 0.7rem;
}

.home-inventory-widget-pill:hover:not(.home-inventory-widget-pill-active) {
  background: var(--surface-elevated, #1f2630);
  border-color: var(--color-border-gold, #d6af5c);
  color: var(--color-text-primary);
}

/* Active pill: high-contrast warm amber to PAIR with the filter banner
   above. The two pieces together make the filtered state unmistakable. */
.home-inventory-widget-pill-active {
  background: #f4a23a;
  border-color: #f4a23a;
  color: #1a1d22;
  box-shadow: 0 0 0 2px rgba(244, 162, 58, 0.32);
}

.home-inventory-widget-pill-active:hover {
  background: #ffb45a;
  border-color: #ffb45a;
  color: #1a1d22;
}

.home-inventory-widget-pill-label {
  max-width: 8rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Sections. The low-supply section is sticky-at-top via order, while the
   all-items section gets the remaining flex space and scrolls
   internally. */
.home-inventory-widget-section {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-height: 0;
}

.home-inventory-widget-section-low-supply {
  flex: 0 0 auto;
  max-height: 40%;
  overflow-y: auto;
}

.home-inventory-widget-section-all-items {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.home-inventory-widget-section-header {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0;
  position: sticky;
  top: 0;
  background: var(--color-ocean-deep, #14181f);
  z-index: 1;
}

.home-inventory-widget-section-icon {
  font-size: 0.9rem;
  color: var(--color-text-secondary);
  flex-shrink: 0;
}

.home-inventory-widget-low-supply-icon {
  color: #f4a23a;
}

.home-inventory-widget-section-title {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
  flex: 1 1 auto;
}

.home-inventory-widget-section-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: var(--surface-elevated, #1f2630);
  color: var(--color-text-secondary);
  font-size: 0.7rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.home-inventory-widget-section-count-attention {
  background: rgba(229, 122, 31, 0.25);
  color: #ffd6a0;
}

.home-inventory-widget-section-empty {
  margin: 0;
  padding: 0.35rem 0.45rem;
  color: var(--color-text-muted);
  font-size: 0.72rem;
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.home-inventory-widget-section-empty i {
  color: #6ab86a;
}

.home-inventory-widget-row-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.home-inventory-widget-row {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.28rem 0.35rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  font-size: 0.78rem;
  line-height: 1.2;
}

.home-inventory-widget-row:last-child {
  border-bottom: none;
}

.home-inventory-widget-row-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-text-primary);
}

.home-inventory-widget-row-quantity {
  display: inline-flex;
  align-items: baseline;
  gap: 0.25rem;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.home-inventory-widget-row-quantity-value {
  color: var(--color-text-primary);
  font-weight: 700;
}

.home-inventory-widget-row-quantity-unit {
  color: var(--color-text-muted);
  font-size: 0.72rem;
}

.home-inventory-widget-row-quantity-min {
  color: var(--color-text-muted);
  font-size: 0.68rem;
}

/* Low-supply rows get a left accent both in the low-supply section AND
   when surfaced in the all-items section. */
.home-inventory-widget-row-low-supply {
  border-left: 3px solid #f4a23a;
  padding-left: calc(0.35rem - 3px + 0.35rem);
  background: rgba(229, 122, 31, 0.08);
}

.home-inventory-widget-row-low-supply .home-inventory-widget-row-quantity-value {
  color: #f4a23a;
}

.home-inventory-widget-row-low-supply-highlight {
  background: rgba(229, 122, 31, 0.06);
}

.home-inventory-widget-row-low-supply-highlight .home-inventory-widget-row-quantity-value {
  color: #f4a23a;
}

.home-inventory-widget-error {
  margin: 0;
  padding: 0.4rem 0.5rem;
  background: rgba(193, 53, 53, 0.18);
  border: 1px solid rgba(193, 53, 53, 0.55);
  border-radius: 6px;
  color: #f5b5b5;
  font-size: 0.74rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* ── Checklists widget ───────────────────────────────────────────────────
   Two stacked sections (running + recently run). The Running section is
   capped at ~50% of the widget height so the Recently-run section is
   always visible without scrolling the outer widget; both sections
   scroll internally when their lists overflow.
*/
.home-widget-body-checklist {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}

.home-checklist-widget {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  font-size: 0.78rem;
  color: var(--color-text-primary);
  gap: 0.4rem;
  overflow: hidden;
}

.home-checklist-widget-loading,
.home-checklist-widget-no-vessel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem;
  color: var(--color-text-muted);
  font-size: 0.78rem;
  text-align: center;
}

.home-checklist-widget-spinner {
  width: 0.9rem;
  height: 0.9rem;
}

.home-checklist-widget-no-vessel-icon {
  font-size: 1.1rem;
}

.home-checklist-widget-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: 0.4rem;
  overflow: hidden;
}

/* Sections. Running is capped at ~50% so the Recently-run list always
   gets some screen real estate; both sections internally scroll. */
.home-checklist-widget-section {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  min-height: 0;
}

.home-checklist-widget-section-running {
  flex: 0 1 auto;
  max-height: 55%;
  overflow-y: auto;
}

.home-checklist-widget-section-recent {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.home-checklist-widget-section-header {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0;
  position: sticky;
  top: 0;
  background: var(--color-ocean-deep);
  z-index: 1;
}

.home-checklist-widget-section-icon {
  font-size: 0.9rem;
  color: var(--color-text-secondary);
  flex-shrink: 0;
}

.home-checklist-widget-running-icon {
  /* Active runs get an "in progress" navy/blue dot. We reuse
     `--events-color-navigation` (theme-aware: pale blue on the night
     theme, deep navy on the day theme) so the badge auto-adapts. */
  color: var(--events-color-navigation);
}

.home-checklist-widget-recent-icon {
  color: var(--color-text-muted);
}

.home-checklist-widget-section-title {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
  flex: 1 1 auto;
}

.home-checklist-widget-section-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: var(--color-ocean-surface);
  color: var(--color-text-secondary);
  font-size: 0.7rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

.home-checklist-widget-section-count-attention {
  /* The widget uses the same `--events-color-navigation` accent as
     other "in progress" affordances around the app to flag a non-zero
     running count. */
  background: color-mix(in srgb, var(--events-color-navigation) 22%, transparent);
  color: var(--events-color-navigation);
}

.home-checklist-widget-section-empty {
  margin: 0;
  padding: 0.35rem 0.45rem;
  color: var(--color-text-muted);
  font-size: 0.72rem;
  display: flex;
  align-items: center;
  gap: 0.35rem;
}

.home-checklist-widget-section-empty i {
  color: var(--color-success);
}

.home-checklist-widget-row-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

/* Generic row layout — applies to both running and recently-run rows.
   Running rows wrap the row content in a button (`row-button`) so it's
   clickable; recently-run rows have no button (display-only). */
.home-checklist-widget-row {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0.32rem 0.4rem;
  border-bottom: 1px solid var(--color-border);
  font-size: 0.78rem;
  line-height: 1.25;
}

.home-checklist-widget-row:last-child {
  border-bottom: none;
}

/* Running rows expose a button for the entire row so the click target
   is the full row. The button strips its native chrome so the row still
   looks like a list item. */
.home-checklist-widget-row-button {
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  width: 100%;
  padding: 0;
  background: transparent;
  border: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.home-checklist-widget-row-running:hover {
  background: var(--color-ocean-light);
}

.home-checklist-widget-row-running-complete .home-checklist-widget-row-progress-bar-fill {
  /* When every item in a running run has been addressed, the fill turns
     green to signal "ready to sign + close". */
  background: var(--color-success);
}

.home-checklist-widget-row-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-text-primary);
  font-weight: 600;
}

.home-checklist-widget-row-meta {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
  color: var(--color-text-muted);
  font-size: 0.7rem;
}

.home-checklist-widget-row-progress {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex: 1 1 6rem;
  min-width: 4rem;
}

/* The progress bar is intentionally chunky enough to read at a glance
   even when the widget is rendered at its narrowest 2-column size. */
.home-checklist-widget-row-progress-bar {
  position: relative;
  flex: 1 1 auto;
  height: 4px;
  background: var(--color-ocean-surface);
  border-radius: 2px;
  overflow: hidden;
}

.home-checklist-widget-row-progress-bar-fill {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: var(--events-color-navigation);
  transition: width 200ms ease;
}

.home-checklist-widget-row-progress-text {
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
  color: var(--color-text-secondary);
}

.home-checklist-widget-row-timestamp {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  flex-shrink: 0;
}

.home-checklist-widget-row-timestamp i {
  font-size: 0.66rem;
}

.home-checklist-widget-row-completed-count {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  flex-shrink: 0;
}

.home-checklist-widget-row-completed-count i {
  font-size: 0.66rem;
}

.home-checklist-widget-error {
  margin: 0;
  padding: 0.4rem 0.5rem;
  background: rgba(193, 53, 53, 0.18);
  border: 1px solid rgba(193, 53, 53, 0.55);
  border-radius: 6px;
  color: #f5b5b5;
  font-size: 0.74rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* ──────────────────────────────────────────────────────────────────────────
   Home dashboard "Maintenance" widget
   ──────────────────────────────────────────────────────────────────────────
   Eight collapsible stacked sections (Late / Due / Warn / To do /
   Next 90 Days / Next 6 Months / Next Year / Others). Empty sections are
   omitted entirely by the JS so a clean maintenance state shows only the
   empty-state hint. Each section header is a collapse toggle; the whole body
   scrolls as one column. Section order / labels / icons / accents are
   data-driven from `homeMaintenanceWidget.js`, so the markup is a single
   `ng-repeat` and the accent classes below are keyed off the `accent`
   suffix each definition carries (`late` / `due` / `warn` / `todo` /
   `next-90-days` / `next-6-months` / `next-year` / `others`).
*/
.home-widget-body-maintenance {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}

.home-maintenance-widget {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  font-size: 0.78rem;
  color: var(--color-text-primary);
  gap: 0.4rem;
  overflow: hidden;
}

.home-maintenance-widget-loading,
.home-maintenance-widget-no-vessel,
.home-maintenance-widget-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem;
  color: var(--color-text-muted);
  font-size: 0.78rem;
  text-align: center;
}

.home-maintenance-widget-spinner {
  width: 0.9rem;
  height: 0.9rem;
}

.home-maintenance-widget-no-vessel-icon,
.home-maintenance-widget-empty-icon {
  font-size: 1.1rem;
}

.home-maintenance-widget-empty-icon {
  color: var(--color-success);
}

.home-maintenance-widget-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  gap: 0.7rem;
  overflow-y: auto;
}

/* Section container — every section shares this layout so visual rhythm
   stays consistent. Tone/urgency is applied via the section-icon and
   row accent rules below.

   `flex: 0 0 auto` is critical: the body is a flex column and these are its
   items. With the default `flex-shrink: 1` a short/compressed widget shrinks
   each section BELOW its content height, so the rows spill out of their box
   and render on top of the next section's header (the reported overlap that
   only appeared when the widget was small). Pinning shrink to 0 keeps every
   section at its natural height and lets the body's `overflow-y: auto`
   scroll instead. */
.home-maintenance-widget-section {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 0 0 auto;
}

/* Section headers flow with their content (NOT sticky). Earlier they were
   `position: sticky; top: 0`, but with up to eight sections every header
   pinned to the same `top: 0`, so as the body scrolled the next header
   (e.g. "Due") slid up and rendered ON TOP of the previous section's last
   row — the reported overlap. A small widget doesn't benefit from sticky
   headers anyway: the whole body scrolls as one column, so plain block flow
   never overlaps. The opaque background + bottom hairline keep each header
   reading as a distinct bar. */
.home-maintenance-widget-section-header {
  padding: 0;
  background: var(--color-ocean-deep);
  border-bottom: 1px solid var(--color-border);
}

/* The entire header is a collapse toggle so the click target is the full
   bar. Resets the native button chrome and lays the caret / icon / title /
   count out in a row; the extra bottom padding gives the label air above
   its own list. */
.home-maintenance-widget-section-toggle {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  width: 100%;
  padding: 0.25rem 0 0.3rem;
  background: transparent;
  border: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* Expand/collapse caret. Muted so it hints at interactivity without
   competing with the section's own urgency icon. Fixed width keeps the
   icon column aligned whether the caret points down (expanded) or right
   (collapsed). */
.home-maintenance-widget-section-caret {
  flex-shrink: 0;
  width: 0.8rem;
  font-size: 0.7rem;
  color: var(--color-text-muted);
}

.home-maintenance-widget-section-icon {
  font-size: 0.9rem;
  color: var(--color-text-secondary);
  flex-shrink: 0;
}

/* Late uses the danger accent (theme-aware). Due uses the warning amber
   the rest of the app already uses for the "Due" badge so the widget
   matches the table-status colours users already know. The informational
   sections (To do + the four time-boxed buckets) use muted neutrals so
   they don't compete visually with the urgent ones. */
.home-maintenance-widget-section-icon-late {
  color: var(--color-danger);
}

.home-maintenance-widget-section-icon-due {
  color: var(--color-warning);
}

/* Warn ("about to be due") uses the theme gold — clearly less alarming than
   the amber Due / red Late accents, but still a positive attention colour
   rather than the muted neutral used by the informational sections. */
.home-maintenance-widget-section-icon-warn {
  color: var(--color-gold);
}

.home-maintenance-widget-section-icon-todo,
.home-maintenance-widget-section-icon-next-90-days,
.home-maintenance-widget-section-icon-next-6-months,
.home-maintenance-widget-section-icon-next-year,
.home-maintenance-widget-section-icon-others {
  color: var(--color-text-muted);
}

.home-maintenance-widget-section-title {
  margin: 0;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-secondary);
  flex: 1 1 auto;
}

.home-maintenance-widget-section-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4rem;
  padding: 0 0.4rem;
  border-radius: 999px;
  background: var(--color-ocean-surface);
  color: var(--color-text-secondary);
  font-size: 0.7rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}

/* Late + Due counts get attention-coloured chips so the user sees at a
   glance "you have X late tasks" without having to scan section text. */
.home-maintenance-widget-section-count-late {
  background: color-mix(in srgb, var(--color-danger) 22%, transparent);
  color: var(--color-danger);
}

.home-maintenance-widget-section-count-due {
  background: color-mix(in srgb, var(--color-warning) 22%, transparent);
  color: var(--color-warning);
}

.home-maintenance-widget-section-count-warn {
  background: color-mix(in srgb, var(--color-gold) 22%, transparent);
  color: var(--color-gold-light);
}

.home-maintenance-widget-row-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

/* Generic row layout — applies to every section. The whole row is a
   button so the click target is the full row (parallels the checklist
   widget's running-row pattern). */
.home-maintenance-widget-row {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 0;
  border-bottom: 1px solid var(--color-border);
  font-size: 0.78rem;
  line-height: 1.25;
}

.home-maintenance-widget-row:last-child {
  border-bottom: none;
}

.home-maintenance-widget-row-button {
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  width: 100%;
  padding: 0.32rem 0.4rem;
  background: transparent;
  border: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.home-maintenance-widget-row-button:hover {
  background: var(--color-ocean-light);
}

/* Late rows get a left urgency stripe so a quick glance picks out the
   highest-priority section even if the user scrolls past the header. */
.home-maintenance-widget-row-late .home-maintenance-widget-row-button {
  border-left: 3px solid var(--color-danger);
}

.home-maintenance-widget-row-due .home-maintenance-widget-row-button {
  border-left: 3px solid var(--color-warning);
}

.home-maintenance-widget-row-warn .home-maintenance-widget-row-button {
  border-left: 3px solid var(--color-gold);
}

.home-maintenance-widget-row-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--color-text-primary);
  font-weight: 600;
}

.home-maintenance-widget-row-meta {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  flex-wrap: wrap;
  color: var(--color-text-muted);
  font-size: 0.7rem;
}

.home-maintenance-widget-row-due,
.home-maintenance-widget-row-due-hours,
.home-maintenance-widget-row-schedule {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}

.home-maintenance-widget-row-due i,
.home-maintenance-widget-row-due-hours i,
.home-maintenance-widget-row-schedule i {
  font-size: 0.66rem;
}

/* When a row is in the Late or Due bucket, tint its due-date pill so the
   date itself reads as urgent (not just the section header). */
.home-maintenance-widget-row-due-late {
  color: var(--color-danger);
  font-weight: 600;
}

.home-maintenance-widget-row-due-due {
  color: var(--color-warning);
  font-weight: 600;
}

.home-maintenance-widget-row-due-warn {
  color: var(--color-gold-light);
  font-weight: 600;
}

.home-maintenance-widget-row-schedule {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  max-width: 50%;
}

/* ──────────────────────────────────────────────────────────────────────────
   Home dashboard "Chat" widget
   ──────────────────────────────────────────────────────────────────────────
   Cross-channel newest-first feed. Each row is a single-line "channel pill +
   author + timestamp" header above a truncated one-line preview of the
   message body. Designed to read like a glanceable activity stream rather
   than a full chat surface — clicking a row jumps the user to the /chat
   page on the appropriate channel.
*/
.home-widget-body-chat {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}
.home-chat-widget {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  font-size: 0.78rem;
  color: var(--color-text-primary);
  overflow: hidden;
}
.home-chat-widget-loading,
.home-chat-widget-no-vessel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 1.1rem 0.85rem;
  color: var(--color-text-muted);
  font-size: 0.78rem;
}
.home-chat-widget-spinner {
  width: 0.95rem;
  height: 0.95rem;
}
.home-chat-widget-no-vessel-icon {
  font-size: 1rem;
  opacity: 0.85;
}
.home-chat-widget-body {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1 1 auto;
  overflow: hidden;
}
.home-chat-widget-section-empty {
  margin: 0;
  padding: 1.1rem 0.85rem;
  color: var(--color-text-muted);
  font-size: 0.76rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.home-chat-widget-section-empty i {
  font-size: 0.95rem;
  opacity: 0.7;
}
.home-chat-widget-row-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 0;
}
.home-chat-widget-row {
  display: block;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid transparent;
  transition: background 120ms ease, border-color 120ms ease;
}
.home-chat-widget-row:hover {
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(255, 255, 255, 0.08);
}
.home-chat-widget-row-own-message {
  background: rgba(64, 158, 255, 0.06);
}
.home-chat-widget-row-own-message:hover {
  background: rgba(64, 158, 255, 0.10);
}
.home-chat-widget-row-button {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 0.42rem 0.55rem;
  gap: 0.2rem;
  background: transparent;
  border: none;
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.home-chat-widget-row-button:focus-visible {
  outline: 2px solid var(--color-accent-primary, #409eff);
  outline-offset: -2px;
  border-radius: 6px;
}
.home-chat-widget-row-header {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  flex-wrap: nowrap;
  min-width: 0;
  font-size: 0.7rem;
}
/* Channel pill — the always-visible "indicator of which channel they came
   through" the user explicitly requested. Tinted with the accent colour so
   it reads as a tag rather than body copy and never gets lost next to the
   author name. Truncates with an ellipsis at narrow widths. */
.home-chat-widget-row-channel-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.28rem;
  padding: 0.12rem 0.42rem;
  border-radius: 999px;
  background: rgba(64, 158, 255, 0.18);
  color: var(--color-accent-primary, #409eff);
  border: 1px solid rgba(64, 158, 255, 0.32);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  flex-shrink: 1;
  min-width: 0;
  max-width: 55%;
  overflow: hidden;
  white-space: nowrap;
}
.home-chat-widget-row-channel-icon {
  font-size: 0.62rem;
  opacity: 0.85;
  flex-shrink: 0;
}
.home-chat-widget-row-channel-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.home-chat-widget-row-author {
  font-weight: 600;
  color: var(--color-text-primary);
  font-size: 0.72rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex-shrink: 1;
  min-width: 0;
}
.home-chat-widget-row-timestamp {
  margin-left: auto;
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  font-size: 0.68rem;
  flex-shrink: 0;
}
.home-chat-widget-row-preview {
  color: var(--color-text-secondary, var(--color-text-muted));
  font-size: 0.74rem;
  line-height: 1.25;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.home-chat-widget-error {
  margin: 0.6rem 0.85rem;
  padding: 0.45rem 0.6rem;
  background: rgba(232, 76, 76, 0.12);
  border: 1px solid rgba(232, 76, 76, 0.32);
  border-radius: 6px;
  color: #f5b5b5;
  font-size: 0.74rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
/* ── Calendar widget ─────────────────────────────────────────────────────
   One-month calendar (always full Sun→Sat weeks padded from the previous /
   next month so every row has 7 cells). Driven by `homeCalendarWidget.js`.
   Reuses the per-category color classes (`events-pill-<key>` and
   `events-pill-active`) defined in event.css so a category recolor only
   happens in one place.
*/
.home-widget-body-calendar {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}
.home-calendar-widget {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  font-size: 0.78rem;
  color: var(--color-text-primary);
  gap: 0.35rem;
  overflow: hidden;
}
.home-calendar-widget-loading,
.home-calendar-widget-no-vessel {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  padding: 0.6rem;
  color: var(--color-text-muted);
  font-size: 0.78rem;
}
.home-calendar-widget-spinner {
  width: 0.9rem;
  height: 0.9rem;
}
.home-calendar-widget-no-vessel-icon {
  font-size: 1.1rem;
}
.home-calendar-widget-body {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  gap: 0.35rem;
  overflow: hidden;
}
/* ── Toolbar ──────────────────────────────────────────────────────────── */
.home-calendar-widget-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--surface-border, rgba(255, 255, 255, 0.06));
  flex-shrink: 0;
}
.home-calendar-widget-toolbar-button {
  background: var(--surface-elevated-strong, rgba(255, 255, 255, 0.06));
  color: var(--color-text-primary);
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  border-radius: 4px;
  padding: 0.15rem 0.4rem;
  font-size: 0.7rem;
  cursor: pointer;
  line-height: 1.1;
}
.home-calendar-widget-toolbar-button:hover {
  background: var(--surface-elevated-stronger, rgba(255, 255, 255, 0.12));
}
.home-calendar-widget-toolbar-button-today {
  margin-left: auto;
  font-weight: 600;
}
.home-calendar-widget-toolbar-select {
  background: var(--surface-elevated-strong, rgba(255, 255, 255, 0.06));
  color: var(--color-text-primary);
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  border-radius: 4px;
  padding: 0.1rem 0.25rem;
  font-size: 0.72rem;
  font-family: inherit;
  cursor: pointer;
}
.home-calendar-widget-toolbar-select option {
  background: var(--color-ocean-mid);
  color: var(--color-text-primary);
}
.home-calendar-widget-toolbar-select-year {
  width: 4.5rem;
}
/* ── Filter pill rows ─────────────────────────────────────────────────── */
.home-calendar-widget-pill-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.2rem;
  flex-shrink: 0;
}
.home-calendar-widget-pill-row-label {
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-text-muted);
  margin-right: 0.15rem;
}
.home-calendar-widget-pill.events-pill {
  padding: 0.1rem 0.35rem;
  font-size: 0.62rem;
  font-weight: 600;
  gap: 0.18rem;
  line-height: 1.1;
}
.home-calendar-widget-pill.events-pill i {
  font-size: 0.65rem;
}
.home-calendar-widget-pill-label {
  max-width: 5rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Task pill colour overrides — drive off the task-kind enum value so a
   late / due / completed pill always reads at a glance, even in
   monochrome event-category zones. */
.home-calendar-widget-pill-task-late {
  border-color: var(--color-danger, #d9534f);
  color: var(--color-danger, #d9534f);
}
.home-calendar-widget-pill-task-late.events-pill-active {
  background: var(--color-danger, #d9534f);
  color: #fff;
}
.home-calendar-widget-pill-task-due {
  border-color: var(--color-warning, #d9a14a);
  color: var(--color-warning, #d9a14a);
}
.home-calendar-widget-pill-task-due.events-pill-active {
  background: var(--color-warning, #d9a14a);
  color: #fff;
}
.home-calendar-widget-pill-task-upcoming {
  border-color: var(--color-info, #5fa9d3);
  color: var(--color-info, #5fa9d3);
}
.home-calendar-widget-pill-task-upcoming.events-pill-active {
  background: var(--color-info, #5fa9d3);
  color: #fff;
}
.home-calendar-widget-pill-task-completed {
  border-color: var(--color-success, #5ab760);
  color: var(--color-success, #5ab760);
}
.home-calendar-widget-pill-task-completed.events-pill-active {
  background: var(--color-success, #5ab760);
  color: #fff;
}
/* ── Weekday header ─────────────────────────────────────────────────── */
.home-calendar-widget-weekday-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  flex-shrink: 0;
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-text-muted);
}
.home-calendar-widget-weekday-cell {
  padding: 0.15rem 0.2rem;
  text-align: center;
}
/* ── Week grid ──────────────────────────────────────────────────────── */
.home-calendar-widget-grid {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--surface-border-subtle, rgba(255, 255, 255, 0.05));
  border: 1px solid var(--surface-border, rgba(255, 255, 255, 0.08));
  border-radius: 4px;
  overflow: hidden;
  flex-grow: 1;
  min-height: 0;
}
.home-calendar-widget-week {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 1px;
  flex: 1 1 0;
  min-height: 0;
}
.home-calendar-widget-day {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  gap: 0.2rem;
  padding: 0.2rem 0.25rem;
  background: var(--surface-elevated, #1f2630);
  color: var(--color-text-primary);
  border: none;
  font: inherit;
  cursor: pointer;
  text-align: left;
  overflow: hidden;
  min-height: 0;
}
.home-calendar-widget-day:hover {
  background: var(--surface-elevated-stronger, rgba(255, 255, 255, 0.08));
}
.home-calendar-widget-day-other-month {
  color: var(--color-text-muted);
  opacity: 0.5;
}
.home-calendar-widget-day-today {
  outline: 1px solid var(--color-info, #5fa9d3);
  outline-offset: -1px;
}
.home-calendar-widget-day-selected {
  background: var(--color-info-soft, rgba(95, 169, 211, 0.18));
}
.home-calendar-widget-day-number {
  font-size: 0.72rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  align-self: flex-start;
}
.home-calendar-widget-day-count {
  position: absolute;
  top: 0.18rem;
  right: 0.25rem;
  font-size: 0.55rem;
  font-weight: 700;
  background: var(--surface-elevated-strong, rgba(255, 255, 255, 0.18));
  color: var(--color-text-primary);
  border-radius: 999px;
  padding: 0 0.25rem;
  min-width: 0.85rem;
  text-align: center;
  line-height: 1.2;
}
.home-calendar-widget-day-dots {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  align-items: center;
  margin-top: auto;
}
.home-calendar-widget-day-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--color-text-muted);
}
.home-calendar-widget-day-dot-event {
  background: currentColor;
}
.home-calendar-widget-day-dot-task-late      { background: var(--color-danger,  #d9534f); }
.home-calendar-widget-day-dot-task-due       { background: var(--color-warning, #d9a14a); }
.home-calendar-widget-day-dot-task-upcoming  { background: var(--color-info,    #5fa9d3); }
.home-calendar-widget-day-dot-task-completed { background: var(--color-success, #5ab760); }
/* ── Selected-date strip ─────────────────────────────────────────────── */
.home-calendar-widget-selected-strip {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex-shrink: 0;
  border-top: 1px solid var(--surface-border, rgba(255, 255, 255, 0.06));
  padding-top: 0.3rem;
  max-height: 40%;
  overflow: hidden;
}
.home-calendar-widget-selected-strip-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
}
.home-calendar-widget-selected-strip-label {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.72rem;
  font-weight: 700;
}
.home-calendar-widget-selected-strip-close {
  background: transparent;
  border: none;
  color: var(--color-text-muted);
  cursor: pointer;
  font-size: 0.8rem;
  padding: 0.1rem 0.25rem;
}
.home-calendar-widget-selected-strip-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  overflow-y: auto;
  min-height: 0;
}
.home-calendar-widget-selected-strip-empty {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--color-text-muted);
  font-size: 0.72rem;
  padding: 0.25rem;
}
.home-calendar-widget-selected-strip-row {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.2rem 0.3rem;
  border-radius: 4px;
  background: var(--surface-elevated-strong, rgba(255, 255, 255, 0.05));
  cursor: pointer;
  font-size: 0.72rem;
  min-width: 0;
}
.home-calendar-widget-selected-strip-row:hover {
  background: var(--surface-elevated-stronger, rgba(255, 255, 255, 0.1));
}
.home-calendar-widget-selected-strip-row-icon {
  flex-shrink: 0;
  width: 0.95rem;
  text-align: center;
}
.home-calendar-widget-selected-strip-row-title {
  flex-grow: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.home-calendar-widget-selected-strip-row-tag {
  flex-shrink: 0;
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.05rem 0.3rem;
  border-radius: 999px;
  background: var(--surface-elevated-stronger, rgba(255, 255, 255, 0.1));
  color: var(--color-text-muted);
}
.home-calendar-widget-selected-strip-row-tag-late      { background: var(--color-danger,  #d9534f); color: #fff; }
.home-calendar-widget-selected-strip-row-tag-due       { background: var(--color-warning, #d9a14a); color: #fff; }
.home-calendar-widget-selected-strip-row-tag-upcoming  { background: var(--color-info,    #5fa9d3); color: #fff; }
.home-calendar-widget-selected-strip-row-tag-completed { background: var(--color-success, #5ab760); color: #fff; }
