/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *













 */
/* Feature icons - both in list and as the main icon */
.feature-icon {
  font-size: 24px;
  color: #333;
}

/* Feature category icon inside the label input */
.feature-category-icon {
  position: absolute;
  right: 10px;
  top: 40%;
  transform: translateY(-50%);
  cursor: pointer;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}
/* Ensure the material icon inherits the positioning */
.feature-category-icon .material-icons {
  font-size: 24px;
  color: #333;
}

/* Category list dropdown */
.category-list {
  position: absolute;
  top: calc(100% + 5px);
  right: 0;
  background: white;
  border: 1px solid #ccc;
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
  border-radius: 8px;
  z-index: 10;
  padding: 10px;
  width: 200px;
}

/* List of category items */
.category-list ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.category-list li {
  display: flex;
  align-items: center;
  padding: 8px;
  cursor: pointer;
  border-radius: 6px;
}

.category-list li:hover {
  background-color: #f0f0f0;
}

/* Category icons in the list */
.category-list .material-icons {
  width: 24px;
  height: 24px;
  margin-right: 8px;
  display: flex;
  align-items: center;
}

/* Delete icon styling */
.delete-feature .material-icons {
  color: #dc3545;
  font-size: 20px;
}
/* Zone Memberships Container */
#zone-memberships {
    margin-top: 20px;
  }
  
  /* Base Panel Styling */
  .zone-membership-panel {
    background-color: #f9fafb;
    border-radius: 8px;
    padding: 12px;
  }
  
  /* Headers */
  .zone-membership-panel h3 {
    font-size: 14px;
    font-weight: 500;
    color: #374151;
    margin: 0;
  }
  
  .zone-membership-panel h4 {
    font-size: 12px;
    font-weight: 500;
    color: #6b7280;
    margin: 12px 0 4px 0;
  }
  
  /* Member/Zone List */
  .membership-list {
    margin-top: 8px;
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  
  /* Individual Member/Zone Item */
  .membership-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background-color: white;
    padding: 8px;
    border-radius: 4px;
    border: 1px solid #e5e7eb;
  }
  
  .membership-item span {
    font-size: 14px;
    color: #374151;
  }
  
  /* Remove Button */
  .remove-membership-button {
    background: none;
    border: none;
    padding: 4px;
    cursor: pointer;
    color: #dc2626;
  }
  
  .remove-membership-button:hover {
    color: #b91c1c;
  }
  
  .remove-membership-button svg {
    width: 16px;
    height: 16px;
  }
  
  /* Suggested Section */
  .suggested-section {
    margin-top: 12px;
  }
  
  /* Add Membership Form */
  .add-membership-form {
    display: inline-block;
  }
  
  /* Add Button */
  .add-membership-button {
    display: flex;
    align-items: center;
    gap: 4px;
    background: none;
    border: none;
    padding: 4px;
    cursor: pointer;
    color: #2563eb;
    font-size: 14px;
  }
  
  .add-membership-button:hover {
    color: #1d4ed8;
  }
  
  .add-membership-button svg {
    width: 16px;
    height: 16px;
  }
  
  /* Error Messages */
  #zone-membership-error {
    color: #dc2626;
    font-size: 14px;
    margin-bottom: 8px;
  }
  
  /* Suggestions List */
  .suggestions-list {
    margin-top: 4px;
    display: flex;
    flex-direction: column;
    gap: 4px;
  }
.google-maps-deep-link-btn {
    position: absolute;
    left: -23px;
    top: 50%;
    transform: translateY(-50%);
    background: none;
    border: none;
    cursor: pointer;
  }
  
  .google-maps-deep-link-btn:hover .tooltip {
    visibility: visible;
    opacity: 1;
  }
  
  .tooltip {
    visibility: hidden;
    opacity: 0;
    background-color: #555;
    color: #fff;
    text-align: center;
    border-radius: 5px;
    padding: 5px;
    position: absolute;
    z-index: 19;
    bottom: 150%; /* Adjust to position the tooltip above the button */
    left: 320%;
    transform: translateX(-50%);
    white-space: nowrap;
    transition: opacity 0.3s;
  }
  
#layer-switcher {
    position: absolute; /* Place it on top of the map */
    bottom: 35px; /* Positioned above the Mapbox attribution */
    left: 300px;
    background-color: rgba(255, 255, 255, 0.9); /* Slightly more transparent */
    padding: 3px;
    border-radius: 8px; /* Increased border-radius for a smoother look */
    box-shadow: 0 1px 10px rgba(0, 0, 0, 0.2); /* Softer shadow for better contrast */
    z-index: 10;
    display: flex;
    flex-direction: column;
    gap: 2px; /* Ensure a small gap between buttons */
    border: 1px solid #ddd; /* Subtle border */
  }
  
  #layer-switcher button {
    background-color: #fff;
    border: 1px solid #ccc; /* Define button border */
    padding: 5px 8px; /* Balanced padding for symmetry */
    cursor: pointer;
    text-align: center;
    width: 100%;
    font-size: 16px;
    border-radius: 4px; /* Slight rounding on buttons */
    box-shadow: none;
    transition: background-color 0.3s, border-color 0.3s;
  }
  
  #layer-switcher button:hover {
    background-color: #f0f0f0; /* Slight hover effect */
    border-color: #007bff; /* Change border on hover */
  }
  
  #layer-switcher button + button {
    margin-top: 4px; /* Space between buttons for improved symmetry */
  }
  
/* Comment input area and icons */
.comment-form {
    display: flex;
    flex-direction: column;
  }
  
  .comment-text-area {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 8px;
    outline: none;
    resize: none;
    font-size: 14px;
    background-color: #fff;
    min-height: 50px;
    margin-bottom: 10px;
  }
  
  
  .mention-suggestions {
    position: relative;
    margin-top: 5px;
  }
  
  .comment-icons {
    display: flex;
    justify-content: flex-end;
    align-items: center;
  }
  
  .upload-icon {
    cursor: pointer;
    margin-right: 10px;
  }
  
  .file-selected-name {
    font-size: 14px;
    color: #333;
    margin-right: 10px;
  }
  
  .remove-file-btn {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    font-size: 18px;
    color: red;
  }
  
  .submit-comment-btn {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0;
    width: 20px;
  }
  
  .icon {
    width: 20px;
    height: 20px;
  }
  
  .remove-icon {
    color: red;
    cursor: pointer;
  }
  
  .file-upload-input {
    display: none; /* Hidden file input */
  }
  
  .mention {
    background-color: #e0f7fa;
    color: #007c91;
    font-weight: bold;
    padding: 2px 5px;
    border-radius: 5px;
    margin-right: 5px;
  }
#feature-search-bar {
    padding: 10px;
    margin-top: 15px;
    border: 1px solid #ddd;
    border-radius: 8px;
    outline: none;
    resize: none;
    font-size: 14px;
    background-color: #fff;
    min-height: 20px;
    min-width: 240px;
    margin-bottom: 10px;
}
/* ======================================================================== */
/*  Shared location filter bar — multi-select category / status / person     */
/*  popovers. Used by location_filter_controller.js + the                    */
/*  shared/filters/_filter_popover partial. Ported from the metrics          */
/*  dashboard's .md-filter* styles so every location view reads as one       */
/*  family.                                                                  */
/* ======================================================================== */
.lf-filter { position: relative; }

.lf-btn {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 500; white-space: nowrap; cursor: pointer;
  border: 1px solid #E5E7EB; border-radius: 8px; padding: 5px 10px;
  background: #fff; color: #1E453A;
  transition: background-color 80ms ease, border-color 80ms ease;
}
.lf-btn:hover { background: #F0FFF6; border-color: rgba(70,165,106,0.4); }
.lf-btn.is-active { background: #F0FFF6; border-color: #46A56A; }

.lf-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
  font-size: 10px; font-weight: 700; line-height: 1; background: #46A56A; color: #fff;
}

.lf-pop {
  position: absolute; top: calc(100% + 4px); left: 0; z-index: 60;
  width: 250px; padding: 6px;
  background: #fff; border: 1px solid #E5E7EB; border-radius: 10px;
  box-shadow: 0 12px 28px rgba(30,69,58,0.16);
  display: flex; flex-direction: column; max-height: 360px;
}
/* Keep `.hidden` working — `display: flex` above otherwise beats Tailwind's
   `.hidden { display: none }`. */
.lf-pop.hidden { display: none; }

.lf-pop-head { display: flex; gap: 6px; padding: 2px 2px 6px; border-bottom: 1px solid #F3F4F6; }
.lf-pop-head button {
  flex: 1; font-size: 11px; font-weight: 500; color: #46A56A;
  background: #F0FFF6; border: 0; border-radius: 6px; padding: 5px; cursor: pointer;
  transition: background-color 80ms ease;
}
.lf-pop-head button:hover { background: #DCF5E6; }

.lf-opts { overflow-y: auto; max-height: 244px; padding: 4px 0; }
.lf-opt {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 6px; font-size: 12px; color: #1E453A; cursor: pointer;
}
.lf-opt:hover { background: #F7FDF8; }
.lf-opt input { accent-color: #46A56A; width: 14px; height: 14px; flex: none; }
.lf-opt-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
.lf-opt-count { flex: none; min-width: 18px; text-align: right; font-size: 10px; color: #9CA3AF; }
/* Grey-out (never hide) options that would yield zero locations given the
   other active filters — house rule, matches the sales-dashboard legend. */
.lf-opt.is-unavailable { opacity: .45; filter: grayscale(1); pointer-events: none; }

.lf-pop-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 6px 8px 2px; margin-top: 2px; border-top: 1px solid #F3F4F6;
  font-size: 11px; font-weight: 500; color: #6B7280;
}
/* "Apply" — only shown in form mode (full-page pages like Farms & Fields). */
.lf-apply {
  flex: none; font-size: 11px; font-weight: 600; color: #fff;
  background: #46A56A; border: 0; border-radius: 6px; padding: 4px 12px; cursor: pointer;
  transition: background-color 80ms ease;
}
.lf-apply:hover { background: #1E453A; }
/* ── Feature chip vocabulary (shared) ───────────────────────────────────────
   The dashboard family's chip language for a map feature — status, category,
   responsible, level, counts, last-visit — plus the editable (`.fchip`) variant
   used where those values can be reassigned inline (the maps/show quick-view
   panel today; the locations-list / metrics rows next).

   The read-only `.ll-*` chips are lifted verbatim out of the locations-list
   table's scoped <style> so the exact same pixels render everywhere. Keep this
   file the single source — do not re-declare these in a view <style> block.
   Table LAYOUT (.ll-table / .ll-row / .ll-sticky / .ll-peek / .ll-actions)
   stays with the locations table; it's context-specific, not chip vocabulary. */

/* ── Read-only display chips ─────────────────────────────────────────────── */
.ll-muted { color:#C4CBD4; font-size:13px; }

.ll-badge { flex:none; font-size:10px; font-weight:600; line-height:1; padding:3px 6px;
  border-radius:5px; background:#ECFDF3; color:#15803D; border:1px solid #D1FADF; }
.ll-badge.is-top { background:#EEF2FF; color:#4338CA; border-color:#E0E7FF; }

/* Counts and measurements (feature area, child counts) — tabular numerals so a
   column of these lines up. Declared here rather than leaning on `num-tabular`,
   which is only defined in the design_review layout and is a no-op in the app. */
.ll-count { flex:none; font-size:11px; color:#6B7280; background:#F3F4F6;
  border-radius:999px; padding:1px 8px; white-space:nowrap;
  font-variant-numeric:tabular-nums; }

.ll-pill { flex:none; font-size:10px; font-weight:500; padding:2px 6px; border-radius:5px; line-height:1.3; }
.ll-pill-warn { background:#FFFBEB; color:#B45309; border:1px solid #FDE68A; }
.ll-pill-dist { background:#EFF6FF; color:#1D4ED8; border:1px solid #DBEAFE; }

.ll-status { display:inline-flex; align-items:center; max-width:100%; font-size:11px;
  font-weight:600; padding:2px 9px; border-radius:999px; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.ll-status .ll-dot { width:6px; height:6px; border-radius:50%; margin-right:6px; flex:none; }

.ll-cat { display:inline-flex; align-items:center; gap:7px; min-width:0; max-width:100%; }
.ll-cat-ic { font-size:15px; line-height:1; flex:none; }
.ll-cat-name { font-size:13px; color:#374151; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

.ll-avatar { display:inline-flex; align-items:center; justify-content:center; width:26px;
  height:26px; border-radius:999px; background:#46A56A; color:#fff; font-size:11px; font-weight:600; flex:none; }
.ll-avatar.is-creator { background:#9CA3AF; }

.ll-visit { display:inline-flex; align-items:center; gap:7px; font-size:12px; color:#6B7280; white-space:nowrap; }
.ll-visit .ll-dot { width:7px; height:7px; border-radius:50%; background:#D1D5DB; flex:none; }
.ll-visit.is-fresh { color:#1E453A; }
.ll-visit.is-fresh .ll-dot { background:#46A56A; }

/* Kebab + menu — the standard secondary-actions affordance. */
.ll-kebab { padding:5px; border-radius:6px; color:#9CA3AF; background:none; border:0;
  cursor:pointer; display:inline-flex; transition:background-color 80ms ease, color 80ms ease; }
.ll-kebab svg { width:16px; height:16px; }
.ll-kebab:hover { color:#1E453A; background:#F0FFF6; }
.ll-menu-item { display:flex; align-items:center; gap:9px; width:100%; text-align:left;
  padding:7px 12px; font-size:13px; color:#1E453A; background:none; border:0; cursor:pointer; text-decoration:none; }
.ll-menu-item:hover { background:#F0FFF6; }
.ll-menu-item.is-danger { color:#D83A56; }
.ll-menu-item.is-danger:hover { background:#FCE4E8; }
.ll-menu-ic { width:15px; height:15px; flex:none; color:#46A56A; }
.ll-menu-item.is-danger .ll-menu-ic { color:#D83A56; }

/* ── Editable chip (`.fchip`) ────────────────────────────────────────────────
   Reads like the display chips above but is a button that opens a reassign
   dropdown. The white surface + stone border + chevron are the "you can change
   this" affordance; the inner dot / icon / avatar mirror the read-only chips so
   the row still looks native to the dashboard family. */
.fchips { display:flex; flex-wrap:wrap; align-items:center; gap:8px; }
/* Fixed height (not padding) so every chip matches regardless of whether its
   content is an emoji icon, a colour dot, an avatar, or plain text — an emoji
   category icon is intrinsically taller than a status dot, which is exactly why
   a padding-sized chip row ends up uneven. */
.fchip { display:inline-flex; align-items:center; gap:6px; max-width:100%;
  height:32px; box-sizing:border-box; padding:0 10px; font-size:12px; font-weight:600;
  line-height:1; border-radius:999px; background:#fff; border:1px solid #E5E7EB;
  color:#1E453A; cursor:pointer; overflow:hidden;
  transition:background-color 80ms ease, border-color 80ms ease; }
.fchip:hover { background:#F0FFF6; border-color:rgba(70,165,106,.45); }
.fchip:focus-visible { outline:2px solid #46A56A; outline-offset:1px; }
.fchip--muted { color:#6B7280; font-weight:500; }
.fchip-name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.fchip-chev { width:12px; height:12px; opacity:.5; flex:none; }
.fchip-ic { font-size:14px; line-height:1; flex:none; }
.fchip-dot { width:8px; height:8px; border-radius:50%; flex:none; }
.fchip-av { display:inline-flex; align-items:center; justify-content:center; width:18px; height:18px;
  border-radius:999px; background:#46A56A; color:#fff; font-size:9px; font-weight:700; flex:none; }
.fchip-av.is-creator { background:#9CA3AF; }
/* ── Turbo Frame loading feedback ────────────────────────────────────────────
   Turbo sets the `busy` attribute on a <turbo-frame> while it's fetching. We use
   it to show an immediate spinner so a click never feels dead while the server
   renders — no JS, no per-link wiring. Covers the two frames that felt slow:
   the global `modal` frame (share/delete/merge/… modals) and the maps/show
   feature-details panel (loaded via turboFrame.src on feature click). */
@keyframes tf-spin { to { transform: rotate(360deg); } }

/* Global modal frame — a dimmed backdrop + centered spinner the instant a
   modal-targeting link is clicked, before the modal HTML arrives. position:fixed
   so it shows even though the empty frame has zero size. */
turbo-frame#modal[busy]::after {
  content: ""; position: fixed; inset: 0; z-index: 60;
  background: rgba(15, 42, 36, 0.25); backdrop-filter: blur(1px);
}
turbo-frame#modal[busy]::before {
  content: ""; position: fixed; top: 50%; left: 50%; z-index: 61;
  width: 34px; height: 34px; margin: -17px 0 0 -17px; border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.5); border-top-color: #fff;
  animation: tf-spin 0.7s linear infinite;
}

/* maps/show feature-details panel — dim the panel + spinner near the top while
   the clicked feature's details load (old content stays until the swap). */
turbo-frame#feature-details-frame { display: block; position: relative; }
/* …but never out-specify Tailwind's `.hidden`. mapbox_map_controller toggles
   `hidden` on this frame to swap the panel between the feature details and the
   multi-select (bulk actions) panel — without this rule the element+id selector
   above (specificity 0,1,1) beats `.hidden` (0,1,0) and both panels render
   stacked in the same card. */
turbo-frame#feature-details-frame.hidden { display: none; }
turbo-frame#feature-details-frame[busy]::after {
  content: ""; position: absolute; inset: 0; z-index: 20;
  background: rgba(255, 255, 255, 0.6);
}
turbo-frame#feature-details-frame[busy]::before {
  content: ""; position: absolute; top: 40px; left: 50%; z-index: 21;
  width: 26px; height: 26px; margin-left: -13px; border-radius: 50%;
  border: 3px solid #E5E7EB; border-top-color: #46A56A;
  animation: tf-spin 0.7s linear infinite;
}

/* Metrics-dashboard table — EVERY interaction (sort, filter, window, roll-up,
   group-by, column toggle, load-more) re-navigates this frame, and the server
   takes ~300–900ms on a large team. Without feedback the stale table just sits
   there and the click reads as dead, so:
     ::after  — veil the stale table so it visibly recedes (z-index clears the
                sticky headers at 32 and the column ⋮ popover at 40)
     ::before — a fixed indeterminate bar pinned to the top of the VIEWPORT.
                Deliberately not centered-in-frame like the panel spinner above:
                the table is far taller than the viewport and has its own inner
                scroller, so an absolutely-positioned spinner is usually parked
                off-screen. A fixed bar is visible wherever you're scrolled. */
@keyframes tf-bar {
  0%   { transform: translateX(-100%) scaleX(0.35); }
  50%  { transform: translateX(0%)    scaleX(0.55); }
  100% { transform: translateX(100%)  scaleX(0.35); }
}
turbo-frame#metrics_table { display: block; position: relative; }
turbo-frame#metrics_table[busy]::after {
  content: ""; position: absolute; inset: 0; z-index: 50;
  background: rgba(255, 255, 255, 0.55);
}
turbo-frame#metrics_table[busy]::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0; z-index: 9999;
  height: 3px; background: #46A56A; transform-origin: 0 50%;
  animation: tf-bar 1.1s ease-in-out infinite;
}

/* ── Frames driven by a Stimulus controller assigning frame.src ─────────────
   These all had the same problem the three frames above used to have: the
   controller swaps `frame.src`, Turbo leaves the OLD content in place while it
   fetches, and the click reads as dead — long enough that people click again.
   Measured 130–180ms each on a heavy team, more on a slow connection.

   Shape is chosen by frame geometry, per the house rule:
     tall + internally scrolling → veil + FIXED top bar (a centred spinner
                                   would be parked off-screen)
     panel                       → veil + spinner near its top
     short / empty               → centred spinner (with a min-height when the
                                   frame is empty at rest and has no box) */

/* Locations list (map_features#index). Every filter, sort, view-mode and page
   click re-navigates this frame (map_features_index_controller#navigate,
   location_filter_controller), and a bulk delete now does too — the frame
   re-fetches itself so the pager, the totals and the rows flowing up from the
   next page all come from the server.

   Unlike the other frames here, this one does NOT draw its spinner in CSS.
   The list already has a first-load spinner (the "Loading locations…" card the
   page shell paints while the lazy frame fetches), and a re-fetch should look
   like a first load — so map_features/_list_loading is rendered a second time
   inside the frame as a hidden overlay, and the rule below just reveals it.
   Same markup, same svg, no second spinner to keep in sync.

   Centred overlay rather than the veil + fixed top bar used by #metrics_table
   above: that bar exists because the metrics table is far taller than the
   viewport, so an absolutely-positioned overlay's contents end up parked
   off-screen. This frame is bounded to the viewport (its container is
   h-[calc(100dvh-3.25rem)], or max-h-[74vh] when embedded) and the table
   scrolls INSIDE it, so the frame's centre is always where the user is looking.

   NOTE: deliberately does NOT set `display` — same trap as #app-peek-panel
   below. map_features/index declares this frame with
   `class="flex flex-col flex-1 min-h-0"`, and it is the middle link in the
   chain that gives the table its own scroller:
     .h-dvh.overflow-hidden container → THIS FRAME → .ll-card → .ll-scroll
   An element+id selector (1,0,1) beats Tailwind's `.flex` (0,1,0), so a
   `display: block` here severed that chain: .ll-card's `flex:1; min-height:0`
   went inert, it fell back to height:auto, .ll-scroll never got a bounded
   height to scroll inside, and the full 25-row page overflowed the
   overflow-hidden container — clipped, with no scrollbar anywhere and the
   footer and pagination unreachable. `position: relative` is all the overlay
   needs and it doesn't disturb the flex layout.
   (turbo_frame_display_guard_test enforces the no-`display` part.) */
turbo-frame#feature-list-frame { position: relative; }
/* The overlay ships with Tailwind's `hidden` on it, so it is invisible even if
   this stylesheet never loads. This selector is (1,2,1) and beats `.hidden`
   (0,1,0), so it still shows while the frame is fetching. */
turbo-frame#feature-list-frame[busy] .ll-loading-overlay {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  position: absolute; inset: 0; z-index: 50;
  background: rgba(255, 255, 255, 0.75);
}

/* App-wide peek slide-over (peek_controller). Re-opening a peek keeps the
   PREVIOUS peek's content on screen while the new one loads, which reads as
   the panel having opened on the wrong record. Veil it so the stale content
   visibly recedes.

   NOTE: deliberately does NOT set `display` or `min-height` here. peek.css has
   `.peek-panel > turbo-frame { flex: 1; min-height: 0; display: flex;
   flex-direction: column }` at specificity 0,1,1 — an id selector (1,0,1)
   would beat it and collapse the panel's flex column, which is what makes the
   sticky top bar and the scrolling body work. `position: relative` is all the
   veil needs, and it doesn't disturb the flex layout. The frame already fills
   the panel via `flex: 1`, so it always has a box to draw into. */
turbo-frame#app-peek-panel { position: relative; }
turbo-frame#app-peek-panel[busy]::after {
  content: ""; position: absolute; inset: 0; z-index: 20;
  background: rgba(255, 255, 255, 0.65);
}
turbo-frame#app-peek-panel[busy]::before {
  content: ""; position: absolute; top: 56px; left: 50%; z-index: 21;
  width: 26px; height: 26px; margin-left: -13px; border-radius: 50%;
  border: 3px solid #E5E7EB; border-top-color: #46A56A;
  animation: tf-spin 0.7s linear infinite;
}

/* Settings modal body (region_preview_controller and the settings nav). A
   panel, so veil + spinner near the top rather than a viewport-fixed bar. */
turbo-frame#settings_content { display: block; position: relative; }
turbo-frame#settings_content[busy] { min-height: 140px; }
turbo-frame#settings_content[busy]::after {
  content: ""; position: absolute; inset: 0; z-index: 20;
  background: rgba(255, 255, 255, 0.65);
}
turbo-frame#settings_content[busy]::before {
  content: ""; position: absolute; top: 48px; left: 50%; z-index: 21;
  width: 26px; height: 26px; margin-left: -13px; border-radius: 50%;
  border: 3px solid #E5E7EB; border-top-color: #46A56A;
  animation: tf-spin 0.7s linear infinite;
}

/* Saved-views dropdown (saved_views_controller). Short frame inside a small
   menu — a centred spinner is the whole feedback; no veil needed at this size.
   The frame itself stays visible; its parent `.saved-views-menu` is what
   toggles open/closed. */
turbo-frame#saved-views-list { display: block; position: relative; }
turbo-frame#saved-views-list[busy] { min-height: 56px; }
turbo-frame#saved-views-list[busy]::after {
  content: ""; position: absolute; inset: 0; z-index: 20;
  background: rgba(255, 255, 255, 0.7);
}
turbo-frame#saved-views-list[busy]::before {
  content: ""; position: absolute; top: 50%; left: 50%; z-index: 21;
  width: 20px; height: 20px; margin: -10px 0 0 -10px; border-radius: 50%;
  border: 2px solid #E5E7EB; border-top-color: #46A56A;
  animation: tf-spin 0.7s linear infinite;
}

/* Inline bulk-organise panel (bulk_organise_controller), in the maps/show
   sidebar. This one is EMPTY at rest — `turbo_frame_tag "bulk-organise-frame"`
   with no body — so there's no box to position a spinner inside until content
   arrives. Give it a height only while busy. */
turbo-frame#bulk-organise-frame[busy] {
  display: block; position: relative; min-height: 64px;
}
turbo-frame#bulk-organise-frame[busy]::before {
  content: ""; position: absolute; top: 50%; left: 50%; z-index: 21;
  width: 22px; height: 22px; margin: -11px 0 0 -11px; border-radius: 50%;
  border: 2px solid #E5E7EB; border-top-color: #46A56A;
  animation: tf-spin 0.7s linear infinite;
}

/* Link popover panel (bulk_link_controller), in the Locations-list bulk bar.
   Same shape as #bulk-organise-frame above: EMPTY at rest (the toolbar renders
   a bare frame; openLinkPop assigns src on open), so it needs a box only while
   busy. Covers both the first open and the server-side candidate-search
   refetches (?q=), which would otherwise read as dead typing. */
turbo-frame#bulk-link-frame[busy] {
  display: block; position: relative; min-height: 64px;
}
turbo-frame#bulk-link-frame[busy]::before {
  content: ""; position: absolute; top: 50%; left: 50%; z-index: 21;
  width: 22px; height: 22px; margin: -11px 0 0 -11px; border-radius: 50%;
  border: 2px solid #E5E7EB; border-top-color: #46A56A;
  animation: tf-spin 0.7s linear infinite;
}

/* Same guard as #feature-details-frame above: the element+id selectors here are
   specificity 0,1,1 and would beat Tailwind's `.hidden` (0,1,0) if anything
   ever toggles these frames that way. Nothing does today — this keeps it that
   way by construction rather than by luck. */
turbo-frame#feature-list-frame.hidden,
turbo-frame#app-peek-panel.hidden,
turbo-frame#settings_content.hidden,
turbo-frame#saved-views-list.hidden,
turbo-frame#bulk-organise-frame.hidden,
turbo-frame#bulk-link-frame.hidden { display: none; }
/* Active-visit home widget (app/views/pages/home/widgets/_active_card.html.erb).
   Each .av-card is an inline-size container, so a card lays itself out from its
   OWN width: a wide (full-width widget) card puts the "Captured so far" panel to
   the RIGHT of the details in a hero row; a narrow (half-width widget) card stacks
   the panel BELOW the details and renders the legend as a wrapping horizontal row.
   All values are --pm-* tokens (see pm_tokens.css). No raw hex, no raw px, no
   left-accent bar, no gradient. */

.av-frame { container-type: inline-size; }

/* ── Card shell ─────────────────────────────────────────────────────────── */
.av-card {
  background: var(--pm-surface);
  border: 1px solid color-mix(in srgb, var(--pm-primary) 22%, transparent);
  border-radius: var(--pm-radius-xl);
  box-shadow: var(--pm-shadow-card);
  padding: var(--pm-space-m);
  transition: box-shadow var(--pm-duration-fast) var(--pm-ease-standard);
}
.av-card:hover { box-shadow: var(--pm-shadow-m); }
/* Stale card — whole-card warm border tint (no left bar). */
.av-card.stale { border-color: color-mix(in srgb, var(--pm-warning) 32%, transparent); }

/* Compact (default): details, then panel stacked below. */
.av-body    { display: flex; flex-direction: column; gap: var(--pm-space-m); }
.av-details { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

/* ── Status row ─────────────────────────────────────────────────────────── */
.av-status-row { display: flex; align-items: center; gap: var(--pm-space-s); margin-bottom: var(--pm-space-s); }
.av-eyebrow {
  display: inline-flex; align-items: center; gap: var(--pm-space-s);
  font: var(--pm-label-s); text-transform: uppercase; letter-spacing: .06em;
  color: var(--pm-fg-2); white-space: nowrap;
}
.av-dot {
  width: var(--pm-space-s); height: var(--pm-space-s); border-radius: var(--pm-radius-pill);
  background: var(--pm-success); flex-shrink: 0;
  animation: av-pulse 1.8s ease-in-out infinite;
}
@keyframes av-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.av-pill {
  margin-left: auto; display: inline-flex; align-items: center; gap: var(--pm-space-xs);
  padding: var(--pm-space-xxs) var(--pm-space-s);
  font: var(--pm-pill); text-transform: uppercase; letter-spacing: .05em;
  background: var(--pm-surface-warning); color: var(--pm-warning-dark);
  border-radius: var(--pm-radius-pill); white-space: nowrap;
}
.av-pill .fas { font-size: 10px; }

/* ── Title ──────────────────────────────────────────────────────────────── */
.av-title {
  font: var(--pm-headline-s); font-size: 1.0625rem; /* 17px compact; 18px in hero */
  color: var(--pm-fg-1); margin: 0; min-width: 0;
  /* Clamp to 2 lines so a long feature name/purpose truncates cleanly instead of
     growing the card unbounded. */
  overflow: hidden; text-overflow: ellipsis;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}
.av-title .av-dash { color: var(--pm-fg-2); font-weight: 600; }
/* Purpose recedes so the feature name dominates the title. */
.av-title .av-purpose { font-weight: 600; color: var(--pm-fg-2); }

/* ── Meta line ──────────────────────────────────────────────────────────── */
.av-meta {
  font: var(--pm-body-s); color: var(--pm-fg-2);
  margin: var(--pm-space-xs) 0 0;
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--pm-space-xxs) var(--pm-space-s);
}
.av-meta .av-pin { color: var(--pm-accent-critical); font-size: 12px; flex-shrink: 0; }
.av-meta .av-sep { color: var(--pm-fg-3); }
.av-meta .av-place { overflow: hidden; text-overflow: ellipsis; max-width: 12rem; white-space: nowrap; }
.av-meta .av-time { color: var(--pm-fg-1); font-weight: 600; } /* the one anchor */

/* ── Stale nudge — inline warm text, no colored surface ─────────────────── */
.av-nudge {
  display: flex; align-items: flex-start; gap: var(--pm-space-xs);
  margin-top: var(--pm-space-ms);
  font: var(--pm-body-s); line-height: 1.4; color: var(--pm-warning-dark);
}
.av-nudge .av-nudge-icon { font-size: 12px; line-height: 1.4; flex-shrink: 0; }

/* ── Actions — CTAs anchored to the bottom of the details column ─────────── */
.av-actions {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--pm-space-s);
  margin-top: auto; padding-top: var(--pm-space-m);
}
.av-btn {
  min-height: 3rem; display: inline-flex; align-items: center; justify-content: center;
  gap: var(--pm-space-s); font-size: 14px; font-weight: 600;
  border-radius: var(--pm-radius-pill); border: 1px solid transparent; cursor: pointer;
  transition: box-shadow var(--pm-duration-fast) var(--pm-ease-standard),
              background var(--pm-duration-fast) var(--pm-ease-standard),
              transform var(--pm-duration-fast) var(--pm-ease-standard);
}
.av-btn:focus-visible { outline: none; box-shadow: var(--pm-focus-ring); }
.av-btn .fas, .av-btn .far { font-size: 12px; }

/* Compact (default): the two primary pills share the row and fill the column
   side-by-side instead of stacking left-aligned. Reset to natural width in hero. */
.av-continue    { flex: 1 1 0; }
.av-finish-form { flex: 1 1 0; }
.av-finish      { width: 100%; }

/* Continue — primary GO, the only fill weight. */
.av-continue {
  padding: 0 var(--pm-space-l);
  background: var(--pm-primary); color: var(--pm-on-inverse); box-shadow: var(--pm-shadow-s);
}
.av-continue:hover { box-shadow: var(--pm-shadow-m); }
.av-continue:focus-visible { box-shadow: var(--pm-shadow-s), var(--pm-focus-ring); }
.av-arrow { transition: transform var(--pm-duration-fast) var(--pm-ease-standard); }
.av-continue:hover .av-arrow { transform: translateX(2px); }

/* Finish — END, outlined coral (lighter than Continue). */
.av-finish {
  padding: 0 var(--pm-space-l);
  background: transparent; color: var(--pm-accent-critical);
  border-color: var(--pm-accent-critical);
}
.av-finish:hover { background: color-mix(in srgb, var(--pm-accent-critical) 8%, transparent); }
/* Compact (default): flex sizes the two primary pills, so trim their inner
   padding (overrides the space-l shorthand above) to keep labels on one line.
   Hero restores the roomy padding. */
.av-continue, .av-finish { padding-left: var(--pm-space-s); padding-right: var(--pm-space-s); }

/* button_to wraps each action in a <form>; the FORM is the flex item, so the
   auto-margin that shoves Discard to the far edge must live on the form. */
.av-finish-form { margin: 0; }
.av-discard-form { margin: 0 0 0 auto; }

/* Discard — destructive, tertiary/quiet, pushed to the far edge. */
.av-discard {
  min-height: auto; padding: 0 var(--pm-space-xs);
  background: transparent; color: var(--pm-fg-3); font-weight: 500;
  box-shadow: none;
}
.av-discard:hover { color: var(--pm-accent-critical); }

/* ── "Captured so far" panel ────────────────────────────────────────────── */
.av-panel {
  background: var(--pm-surface-variant); border-radius: var(--pm-radius-l);
  padding: var(--pm-space-m); display: flex; flex-direction: column;
}
.av-panel-h {
  font: var(--pm-eyebrow); text-transform: uppercase; letter-spacing: .06em;
  color: var(--pm-fg-3); margin: 0 0 var(--pm-space-s);
}
.av-panel-empty { font: var(--pm-body-s); color: var(--pm-fg-3); margin: 0; }
/* Zero-observation stand-in — short muted inline line, NO grey sub-surface/rail.
   Sits at the top beside the details in hero (align-self), below in compact. */
.av-empty-note {
  margin: 0; font: var(--pm-body-s); color: var(--pm-fg-3);
  align-self: flex-start; flex: 0 0 auto;
}

/* Legend — compact default: wrapping horizontal row of "● Label N" units. */
.av-legend {
  display: flex; flex-direction: row; flex-wrap: wrap;
  gap: var(--pm-space-s) var(--pm-space-m);
}
.av-leg { display: flex; align-items: center; gap: var(--pm-space-xs); font: var(--pm-body-s); color: var(--pm-fg-2); }
.av-leg-dot { width: 7px; height: 7px; border-radius: var(--pm-radius-pill); flex-shrink: 0; }
.av-leg-label { white-space: nowrap; }
.av-leg-count { margin-left: var(--pm-space-xxs); font-weight: 700; color: var(--pm-fg-1); }

/* Total — sum of buckets, honest. */
.av-total {
  display: flex; align-items: center;
  margin-top: var(--pm-space-s); padding-top: var(--pm-space-s);
  border-top: 1px solid var(--pm-border);
  font: var(--pm-eyebrow);
}
.av-total-label { text-transform: uppercase; letter-spacing: .05em; color: var(--pm-fg-3); }
.av-total-count { margin-left: auto; font-size: 12px; color: var(--pm-fg-1); }

@media (prefers-reduced-motion: reduce) {
  .av-dot { animation: none; opacity: 1; }
  .av-arrow { transition: none; }
  .av-continue:hover .av-arrow { transform: none; }
}

/* ── Wide (hero) — panel BESIDE the details, roomier padding + lift ──────── */
@container (min-width: 34rem) {
  .av-card       { padding: var(--pm-space-l); box-shadow: var(--pm-shadow-m); }
  .av-card:hover { box-shadow: var(--pm-shadow-l); }

  .av-body    { flex-direction: row; align-items: flex-start; gap: var(--pm-space-l); }
  /* Panel is only as tall as its content — card height is driven by the details
     column, so a stale/low-observation card shows no dead grey rail below the
     legend. Pinned to the top beside the details. */
  .av-panel   { flex: 0 0 13.5rem; align-self: flex-start; }
  .av-title   { font-size: 1.125rem; }

  /* Hero has room — primary pills return to natural width + roomy padding. */
  .av-continue    { flex: 0 0 auto; }
  .av-finish-form { flex: 0 0 auto; }
  .av-finish      { width: auto; }
  .av-continue, .av-finish { padding-left: var(--pm-space-l); padding-right: var(--pm-space-l); }

  /* Legend returns to a vertical "summary table" with right-aligned counts. */
  .av-legend      { flex-direction: column; gap: var(--pm-space-ms); }
  .av-leg         { gap: var(--pm-space-s); }
  .av-leg-count   { margin-left: auto; }
}
/* Audio Briefings home widget (app/views/pages/home/widgets/_briefings.html.erb).
   Forward-looking: a player hero that plays the soonest upcoming visit's briefing,
   then one row per upcoming visit. The .bw-frame is an inline-size container, so
   the widget lays itself out from its OWN width — a wide (full-width) widget shows
   the "Next up" kicker, the row meta line, and the full transcript label; a narrow
   (half-width) widget drops those for a denser single-line read.

   All values are --pm-* tokens (see pm_tokens.css) except small icon/element
   sizing in px, matching home_active_widget.css. No raw hex, no left-accent bar,
   no gradient. */

.bw-frame { container-type: inline-size; }

/* ── Player hero ─────────────────────────────────────────────────────────── */
.bw-player { display: flex; align-items: center; gap: var(--pm-space-ms); }

.bw-play {
  flex-shrink: 0; width: 44px; height: 44px; border: none; cursor: pointer;
  border-radius: var(--pm-radius-pill);
  background: var(--pm-primary); color: var(--pm-fg-on-primary);
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: var(--pm-shadow-m);
  transition: transform var(--pm-duration-fast) var(--pm-ease-standard);
}
.bw-play:hover { transform: scale(1.04); }
.bw-play:focus-visible { outline: none; box-shadow: var(--pm-focus-ring), var(--pm-shadow-m); }
.bw-play .fas { font-size: 16px; }

.bw-play-meta { min-width: 0; flex: 1; }
.bw-kicker {
  display: none; /* full only */
  font: var(--pm-label-s); font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--pm-primary-light);
  margin: 0 0 var(--pm-space-xxs);
}
.bw-headline {
  font: var(--pm-title-m); color: var(--pm-fg-1); margin: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bw-subline {
  font: var(--pm-body-s); color: var(--pm-fg-2); margin: 2px 0 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Quiet hero — upcoming visits exist but none have audio yet. */
.bw-hero-quiet {
  display: flex; align-items: center; gap: var(--pm-space-s);
  font: var(--pm-body-m); color: var(--pm-fg-3);
}
.bw-hero-quiet .fas { color: var(--pm-primary-light); font-size: 14px; }

/* ── Scrubber ────────────────────────────────────────────────────────────── */
.bw-scrub {
  display: flex; align-items: center; gap: var(--pm-space-s);
  margin-top: var(--pm-space-ms);
}
.bw-t {
  font-family: var(--pm-font-mono); font-size: 10px; line-height: 1;
  color: var(--pm-fg-3); width: 30px; flex-shrink: 0;
}
.bw-t--end { text-align: right; }
.bw-track {
  position: relative; flex: 1; height: 5px; cursor: pointer;
  border-radius: var(--pm-radius-pill); background: var(--pm-surface-variant);
}
.bw-track:focus-visible { outline: none; box-shadow: var(--pm-focus-ring); }
.bw-fill {
  position: absolute; inset: 0 auto 0 0; width: 0%;
  border-radius: var(--pm-radius-pill); background: var(--pm-primary-light);
}
.bw-thumb {
  position: absolute; top: 50%; left: 0%; width: 12px; height: 12px;
  transform: translate(-50%, -50%); border-radius: var(--pm-radius-pill);
  background: var(--pm-surface); border: 2px solid var(--pm-primary-light);
  box-shadow: var(--pm-shadow-xs);
}

/* ── Transport ───────────────────────────────────────────────────────────── */
.bw-transport {
  display: flex; align-items: center; gap: var(--pm-space-s);
  margin-top: var(--pm-space-s);
}
.bw-tbtn {
  display: inline-flex; align-items: center; gap: var(--pm-space-xs);
  cursor: pointer; height: 30px; padding: 0 var(--pm-space-ms);
  border: 1px solid var(--pm-border); background: var(--pm-surface);
  color: var(--pm-fg-2); border-radius: var(--pm-radius-pill);
  font: var(--pm-title-s); font-size: 11px;
  transition: background var(--pm-duration-fast) var(--pm-ease-standard),
              color var(--pm-duration-fast) var(--pm-ease-standard);
}
.bw-tbtn:hover { background: var(--pm-surface-secondary); color: var(--pm-fg-1); }
.bw-tbtn:focus-visible { outline: none; box-shadow: var(--pm-focus-ring); }
.bw-tbtn .fas { font-size: 12px; }
.bw-sec {
  font-family: var(--pm-font-mono); font-size: 9px; color: var(--pm-fg-3);
  font-variant-numeric: tabular-nums;
}
.bw-speed {
  min-width: 46px; justify-content: center;
  font-variant-numeric: tabular-nums;
}
.bw-spacer { flex: 1; }
.bw-transcript {
  display: inline-flex; align-items: center; gap: var(--pm-space-xs);
  cursor: pointer; border: none; background: transparent;
  color: var(--pm-primary-light); font: var(--pm-title-s); font-size: 11px;
  padding: var(--pm-space-xs);
}
.bw-transcript:hover { text-decoration: underline; }
.bw-transcript:focus-visible { outline: none; box-shadow: var(--pm-focus-ring); border-radius: var(--pm-radius-s); }
.bw-transcript .fas { font-size: 13px; }
.bw-transcript-label { display: inline; } /* icon-only in compact */

.bw-audio { margin-top: var(--pm-space-s); }
.bw-audio audio { width: 100%; }

/* Transcript drawer — plain surface, no left bar. */
.bw-transcript-panel {
  margin-top: var(--pm-space-s); padding: var(--pm-space-ms);
  background: var(--pm-surface-secondary); border: 1px solid var(--pm-border-card);
  border-radius: var(--pm-radius-m);
  font: var(--pm-body-s); color: var(--pm-fg-2);
  max-height: 11rem; overflow-y: auto; white-space: pre-line;
}

/* ── Divider ─────────────────────────────────────────────────────────────── */
.bw-hr { height: 1px; border: 0; background: var(--pm-border-card); margin: var(--pm-space-ms) 0; }

/* ── List ────────────────────────────────────────────────────────────────── */
.bw-list-label {
  font: var(--pm-eyebrow); letter-spacing: .08em; text-transform: uppercase;
  color: var(--pm-fg-3); margin: 0 0 var(--pm-space-s);
}
.bw-rows { display: flex; flex-direction: column; gap: var(--pm-space-s); }

.bw-row {
  display: flex; align-items: center; gap: var(--pm-space-ms);
  padding: var(--pm-space-s) var(--pm-space-ms);
  border-radius: var(--pm-radius-m);
  border: 1px solid var(--pm-border-card); background: var(--pm-surface);
  text-align: left; width: 100%; cursor: pointer;
  transition: background var(--pm-duration-fast) var(--pm-ease-standard),
              border-color var(--pm-duration-fast) var(--pm-ease-standard);
}
.bw-row:hover { background: var(--pm-surface-secondary); }
.bw-row:focus-visible { outline: none; box-shadow: var(--pm-focus-ring); }

/* Current / loaded-in-player — 6% fill + 35% border + lift. No left bar. */
.bw-row.bw-current {
  background: color-mix(in srgb, var(--pm-primary) 6%, transparent);
  border-color: color-mix(in srgb, var(--pm-primary) 35%, transparent);
  box-shadow: var(--pm-shadow-card);
}

/* Preparing — recede, don't cage. */
.bw-row.bw-preparing { cursor: default; opacity: .85; }
.bw-row.bw-preparing:hover { background: var(--pm-surface); }

.bw-glyph {
  flex-shrink: 0; width: 30px; height: 30px; border-radius: var(--pm-radius-m);
  display: inline-flex; align-items: center; justify-content: center;
}
.bw-glyph .fas { font-size: 14px; }

.bw-body { min-width: 0; flex: 1; }
.bw-name {
  display: block;
  font: var(--pm-body-m); font-weight: 600; color: var(--pm-fg-1);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bw-meta {
  display: block;
  font: var(--pm-body-s); color: var(--pm-fg-2); margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bw-sep { color: var(--pm-fg-3); margin: 0 var(--pm-space-xs); }
.bw-prepared { color: var(--pm-primary-light); font-weight: 600; font-variant-numeric: tabular-nums; }

.bw-right {
  flex-shrink: 0; display: flex; flex-direction: column;
  align-items: flex-end; gap: var(--pm-space-xxs);
}
.bw-day {
  display: block; /* shown on non-current rows in both full and compact */
  font-family: var(--pm-font-mono); font-size: 11px; line-height: 1;
  color: var(--pm-fg-2); font-variant-numeric: tabular-nums;
}
.bw-row.bw-current .bw-day { display: none; } /* equalizer takes its place */
.bw-status {
  font: var(--pm-label-s); font-weight: 700; font-size: 8px; letter-spacing: .06em;
  text-transform: uppercase; padding: var(--pm-space-xxs) var(--pm-space-xs);
  border-radius: var(--pm-radius-pill);
  background: var(--pm-surface-warning); color: var(--pm-warning-dark);
}
.bw-status-full { display: inline; }
.bw-status-compact { display: none; }

/* Equalizer — current-row cue. */
.bw-eq { display: none; align-items: flex-end; gap: 2px; height: 12px; }
.bw-row.bw-current .bw-eq { display: inline-flex; }
.bw-eq i {
  width: 2px; background: var(--pm-primary-light); border-radius: 1px;
  transform-origin: bottom; /* static bars at rest; animated only while playing */
}
.bw-eq i:nth-child(1) { height: 5px; animation-delay: 0ms; }
.bw-eq i:nth-child(2) { height: 11px; animation-delay: 150ms; }
.bw-eq i:nth-child(3) { height: 7px; animation-delay: 300ms; }
.bw-row.bw-current.is-playing .bw-eq i { animation: bw-eq 900ms ease-in-out infinite; }
@keyframes bw-eq { 0%, 100% { transform: scaleY(.5); } 50% { transform: scaleY(1); } }

@media (prefers-reduced-motion: reduce) {
  .bw-play { transition: none; }
  .bw-play:hover { transform: none; }
  .bw-row.bw-current.is-playing .bw-eq i { animation: none; }
  .bw-eq i { transform: scaleY(1); }
}

/* ── Wide (full-width widget) — kicker, row meta line, transcript label ────── */
@container (min-width: 26rem) {
  .bw-play { width: 52px; height: 52px; }
  .bw-play .fas { font-size: 20px; }
  .bw-kicker { display: block; }
  .bw-headline { font: var(--pm-title-l); }
  .bw-scrub { margin-top: var(--pm-space-m); }
  .bw-transport { margin-top: var(--pm-space-ms); }
  .bw-hr { margin: var(--pm-space-m) 0; }
}

/* ── Narrow (half-width widget) — denser rows, day rail, icon-only transcript ─ */
@container (max-width: 25.999rem) {
  .bw-row { padding: var(--pm-space-s); }
  .bw-glyph { width: 26px; height: 26px; }
  .bw-glyph .fas { font-size: 13px; }
  .bw-name { font: var(--pm-title-s); }
  .bw-meta-full { display: none; }
  .bw-transcript-label { display: none; }
  .bw-status-full { display: none; }
  .bw-status-compact { display: inline; }
}
