/*
 * Divers Hub design tokens and small shared components.
 *
 * Loaded after material-dashboard.css by the page template. Chunk 1 of the
 * redesign only ADDS this file and uses the .chip classes on the sites pages.
 * The variables are the palette and scale the new shell (chunk 2) will use,
 * published early so the direction can be reviewed before it lands
 * everywhere. Nothing in here restyles existing Material Dashboard markup.
 *
 * Naming: --dh-* so nothing collides with Bootstrap or Material variables.
 */

:root {
  /* Water palette: deep to shallow. */
  --dh-ink:        #0b2a3a;   /* text, primary buttons */
  --dh-deep:       #0e4d68;   /* headers, active states */
  --dh-sea:        #0e7c9e;   /* links, accents */
  --dh-shallow:    #5fb4cf;   /* highlights */
  --dh-foam:       #e3f1f6;   /* soft fills, selected chip background */
  --dh-sand:       #fbfbf9;   /* page background */
  --dh-paper:      #ffffff;   /* cards */
  --dh-line:       #d8dee3;   /* borders */
  --dh-muted:      #5a6b78;   /* secondary text */

  /* Conditions: good / average / poor. Used by sea state pills later. */
  --dh-good:       #2e7d4f;
  --dh-good-bg:    #eaf5ee;
  --dh-avg:        #9c7c15;
  --dh-avg-bg:     #fbf6e4;
  --dh-poor:       #b0532a;
  --dh-poor-bg:    #f8e9e2;

  /* Safety thresholds (gas planning, 2026-09-15): a genuine orange/red
     ladder, distinct from the good/avg/poor condition triad above - this
     is "danger of oxygen toxicity", not "how's the surf". */
  --dh-warn:       #c2660f;
  --dh-danger:     #b0322b;

  /* Type and spacing scale. */
  --dh-font:       "Roboto", -apple-system, "Segoe UI", Arial, sans-serif;
  --dh-radius:     10px;
  --dh-radius-pill: 999px;
  --dh-space-1:    4px;
  --dh-space-2:    8px;
  --dh-space-3:    12px;
  --dh-space-4:    16px;
  --dh-space-6:    24px;

  /* Left/right inset every page's content actually lands at: just
     .container-fluid's own padding (10px phones via the phones-only
     override below, 24px from md up) - the gap Sites already used,
     since it has no .row wrapping its cards to add anything on top.
     Dashboard's rows had their own .row.mx-1 adding extra padding on
     top of this; removed there so its cards land here too. Anything
     outside the container (the page title, the Me-tab rows) uses this
     variable instead of guessing its own number. */
  --dh-content-x: 10px;
}
@media (min-width: 768px) { :root { --dh-content-x: 24px; } }

/* Kills the elastic rubber-band bounce at the top/bottom (and any stray
   sideways bounce) of the whole page - installed as an app, that bounce
   reads as "this is a website", not a native screen (Pablo, 2026-09-18:
   "avoid the elastic bounce EVERYWHERE in the app, it makes it look more
   native"). Doesn't touch scrolling itself, only what happens at its
   edges, so every page keeps scrolling normally. */
html, body { overscroll-behavior: none; }

/* ------------------------------------------------------------------ */
/* Filter chips. Plain anchors so they work without JavaScript.        */
/* ------------------------------------------------------------------ */
.chip {
  display: inline-block;
  padding: 4px 12px;
  border: 1px solid var(--dh-line);
  border-radius: var(--dh-radius-pill);
  background: var(--dh-paper);
  color: var(--dh-muted);
  font-size: 0.8rem;
  font-weight: 600;
  line-height: 1.4;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .12s ease, border-color .12s ease, color .12s ease;
}
.chip:hover,
.chip:focus-visible {
  border-color: var(--dh-sea);
  color: var(--dh-deep);
  background: var(--dh-foam);
  outline: none;
}
/* Icon + label chips (nav bar customization picker, Pablo, 2026-09-24). */
.chip .material-icons-round { font-size: 14px; vertical-align: -2px; margin-right: 2px; }
.dh-nav-chip-icon-svg { display: inline-flex; width: 14px; height: 14px; vertical-align: -2px; margin-right: 2px; }
.dh-nav-chip-icon-svg svg { width: 100%; height: 100%; }
.chip.is-taken { opacity: .35; pointer-events: none; }

.chip.chip-on,
.chip[aria-current="true"] {
  background: var(--dh-ink);
  border-color: var(--dh-ink);
  color: #fff;
}

/* Legend row under the sites tables. */
.dive-level-legend img { vertical-align: middle; }

/* Version stamp in footers. Quiet by design (finding F-05). */
.divehub-version {
  font-size: 0.75rem;
  color: var(--dh-muted);
  opacity: .8;
}

/* ------------------------------------------------------------------ */
/* Shell: top bar, bottom tab bar, "Me" drawer, page heading.          */
/* Pages opt in with body.dh-shell (set by the page template call).    */
/* ------------------------------------------------------------------ */
:root {
  --dh-topbar-h: 56px;
  --dh-tabbar-h: 60px;
}

/* Material Dashboard reserved space for the sidenav. The shell has none. */
body.dh-shell { background: var(--dh-sand); font-family: var(--dh-font); }
body.dh-shell .main-content { margin-left: 0 !important; max-height: none !important; }
/* The one universal content cap: every page's outer container stops
   growing at 1100px, same box model (border-box, same padding) as
   .dh-me-rows below it - so the "cards" and the "buttons at the bottom"
   always cap out at exactly the same width, on every page, not just the
   pages that happened to add their own .dh-board/.dh-wx/.dh-home class
   (2026-09-11: this used to be per-page opt-in, which is why SiteDetails
   and the Weather cards drifted out of step with .dh-me-rows). */
body.dh-shell .main-content > .container-fluid {
  max-width: 1100px; margin-left: auto; margin-right: auto; box-sizing: border-box;
  padding-top: var(--dh-space-2); padding-left: var(--dh-content-x); padding-right: var(--dh-content-x);
}
/* That padding-top is every page's whole top gap under the sticky header.
   Several first-on-the-page components (.dh-wx-verdict, .dh-explorer-head,
   .dh-site-facts, .dh-card, .dh-dash-collapse, .dh-wizard...) also carry
   their own margin-top, meant to space repeated instances of themselves
   away from whatever card came before - correct everywhere except when
   one of them happens to BE the first thing on the page, where it just
   doubled the gap (2026-09-13: this, not the container padding itself,
   is why some pages read as having more top padding than others). Zero
   the redundant one out, one level of .row > column deep too since Beach
   Diving's verdict cards live inside a column, not directly in the
   container - EVERY column of that first row, not just the first one
   (:first-child on the column was dropped 2026-09-17: with it, only
   Fort Lauderdale's card - the first column - got its margin-top zeroed,
   so it rendered 12px higher than West Palm Beach's identical card right
   next to it, both being "first on the page" the same way side by side;
   Pablo: "fort lauderdale card is slightly above compared to west palm
   beach"). */
body.dh-shell .main-content > .container-fluid > *:first-child,
body.dh-shell .main-content > .container-fluid > .row:first-child > [class*="col"] > *:first-child {
  margin-top: 0 !important;
}
body.dh-shell .sidenav, body.dh-shell #sidenav-main { display: none !important; }

.dh-topbar {
  position: sticky; top: 0; z-index: 1030;
  height: var(--dh-topbar-h);
  background: var(--dh-ink); color: #fff;
  box-shadow: 0 1px 0 rgba(255,255,255,.06), 0 2px 10px rgba(0,0,0,.15);
}
.dh-topbar-inner {
  /* Full width, no max-width/centering: the brand and the search/avatar
     actions must stay pinned to the true left/right edges of the window at
     every size, not just within a centered content column (2026-09-11). */
  height: 100%;
  display: flex; align-items: center; gap: var(--dh-space-4); flex-wrap: nowrap;
  padding: 0 var(--dh-space-4);
}
/* Brand pinned left, actions pinned right, topnav takes the middle and
   scrolls itself if it ever runs out of room - so neither end can get
   squeezed off its edge at any width. */
.dh-brand { display: inline-flex; align-items: center; gap: 10px; color: #fff; font-weight: 700; font-size: 1.05rem; text-decoration: none; white-space: nowrap; flex: 0 0 auto; }
.dh-brand img { border-radius: 50%; background: #fff; }
.dh-brand:hover { color: #fff; }

.dh-topnav { display: none; gap: var(--dh-space-1); margin-left: var(--dh-space-4); flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.dh-topnav::-webkit-scrollbar { display: none; }
.dh-topnav-link {
  color: rgba(255,255,255,.82); text-decoration: none; font-weight: 600; font-size: .95rem;
  padding: 8px 14px; border-radius: var(--dh-radius-pill); flex: 0 0 auto; white-space: nowrap;
}
.dh-topnav-link:hover { color: #fff; background: rgba(255,255,255,.08); }
.dh-topnav-link.is-active { color: var(--dh-ink); background: #fff; }
button.dh-topnav-link { background: none; border: 0; cursor: pointer; font: inherit; }
button.dh-topnav-link:hover { background: rgba(255,255,255,.08); }

.dh-topbar-actions { margin-left: auto; display: flex; align-items: center; gap: var(--dh-space-2); flex: 0 0 auto; }
.dh-search { display: flex; align-items: center; gap: 6px; background: rgba(255,255,255,.12); border-radius: var(--dh-radius-pill); padding: 4px 12px; }
.dh-search input { background: transparent; border: 0; color: #fff; width: 160px; font-size: .9rem; outline: none; }
.dh-search input::placeholder { color: rgba(255,255,255,.6); }
.dh-search .material-icons-round { font-size: 20px; color: rgba(255,255,255,.7); }
.dh-btn-ghost { color: #fff; border: 1px solid rgba(255,255,255,.5); border-radius: var(--dh-radius-pill); padding: 6px 14px; font-weight: 600; font-size: .9rem; text-decoration: none; }
.dh-btn-ghost:hover { color: var(--dh-ink); background: #fff; }
.dh-avatar-btn {
  width: 38px; height: 38px; border-radius: 50%; border: 0; padding: 0;
  background: rgba(255,255,255,.12); color: #fff; display: inline-flex; align-items: center; justify-content: center; overflow: hidden;
}
.dh-avatar-btn img { width: 100%; height: 100%; object-fit: cover; }
.dh-avatar-btn.is-active, .dh-avatar-btn:hover { background: #fff; color: var(--dh-ink); }

/* Messages bell, just left of the avatar - where people expect a notification centre. */
.dh-bell-btn {
  position: relative; width: 38px; height: 38px; border-radius: 50%; border: 0; padding: 0;
  background: rgba(255,255,255,.12); color: #fff; display: inline-flex; align-items: center; justify-content: center; text-decoration: none;
}
.dh-bell-btn:hover { background: #fff; color: var(--dh-ink); }
.dh-bell-badge {
  position: absolute; top: -2px; right: -2px; min-width: 16px; height: 16px; padding: 0 3px;
  border-radius: 999px; background: var(--dh-poor, #c0392b); color: #fff; font-size: .62rem; font-weight: 800;
  display: flex; align-items: center; justify-content: center; line-height: 1; border: 2px solid var(--dh-ink);
}

/* Mobile search: a plain icon that opens the same search form in a modal,
   since .dh-search itself only appears from md up (see .dh-search rule). */
.dh-search-btn {
  width: 38px; height: 38px; border-radius: 50%; border: 0; padding: 0;
  background: rgba(255,255,255,.12); color: #fff; display: inline-flex; align-items: center; justify-content: center;
}
.dh-search-btn:hover { background: #fff; color: var(--dh-ink); }
.dh-search-modal .modal-content { border-radius: 16px; }
.dh-search-modal .dh-search { background: var(--dh-foam); }
.dh-search-modal .dh-search input { color: var(--dh-ink); width: 100%; }
.dh-search-modal .dh-search input::placeholder { color: var(--dh-muted); }
.dh-search-modal .dh-search .material-icons-round { color: var(--dh-muted); }

/* Bottom tabs: phones and small tablets. */
.dh-tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1030;
  height: calc(var(--dh-tabbar-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  display: grid; grid-template-columns: repeat(5, 1fr); /* Dives, Sites, Operators, Groups, Me */
  background: var(--dh-paper); border-top: 1px solid var(--dh-line);
}
.dh-tab {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  color: var(--dh-muted); text-decoration: none; font-size: .66rem; font-weight: 600; min-width: 0;
  border: 0; background: transparent; padding: 0;
}
.dh-tab .material-icons-round { font-size: 24px; }
.dh-tab.is-active { color: var(--dh-sea); }
body.dh-shell .main-content { padding-bottom: calc(var(--dh-tabbar-h) + env(safe-area-inset-bottom) + 12px); }
/* .dh-me-rows (page-template.blade.php, every signed-in non-guest page) now
   reserves this same tab-bar clearance itself, right before the tab bar -
   so main-content's own copy is just dead space in the middle of the page
   wherever both exist. Guests have no me-rows, so they still need this. */
body.dh-shell:has(.dh-me-rows) .main-content { padding-bottom: 0; }

@media (min-width: 992px) {
  .dh-topnav { display: flex; }
  .dh-tabbar { display: none; }
  body.dh-shell .main-content { padding-bottom: 0; }
}

/* Drawer. */
.dh-drawer { width: min(360px, 92vw); }
.dh-drawer .offcanvas-title { font-weight: 700; }
.dh-menu-cta { background: var(--dh-foam); border-radius: var(--dh-radius); padding: var(--dh-space-4); margin-bottom: var(--dh-space-4); font-size: .9rem; color: var(--dh-deep); }
.dh-menu-group { margin-bottom: var(--dh-space-4); }
.dh-menu-group h6 { font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; color: var(--dh-muted); margin: 0 0 4px 12px; }
.dh-menu-link {
  display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--dh-radius);
  color: var(--dh-ink); text-decoration: none; font-weight: 500; font-size: .95rem;
}
.dh-menu-link:hover { background: var(--dh-foam); color: var(--dh-deep); }
.dh-menu-link .material-icons-round { font-size: 22px; color: var(--dh-sea); }
.dh-menu-icon-svg { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; color: var(--dh-sea); flex: 0 0 auto; }
.dh-menu-icon-svg svg { width: 22px; height: 22px; }
.dh-menu-link.is-locked { color: var(--dh-muted); }
.dh-menu-link.is-locked .material-icons-round { color: var(--dh-muted); }
.dh-menu-link.is-locked .dh-menu-icon-svg { color: var(--dh-muted); }
.dh-menu-lock { margin-left: auto; font-size: 18px !important; }
.dh-menu-version { text-align: center; margin-top: var(--dh-space-4); }

/* Page heading row. Sticky just under the top bar (its own height, so it
   docks flush against it) with a translucent, blurred background - the
   title stays put while the page scrolls under it, same idea as the top
   bar itself. Falls back to a solid background on browsers with no
   backdrop-filter support, so it's never see-through text over text. */
.dh-pagehead {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--dh-space-3);
  padding: var(--dh-space-3) var(--dh-content-x);
  position: sticky; top: var(--dh-topbar-h); z-index: 1020;
  background: var(--dh-sand);
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .dh-pagehead { background: rgba(251, 251, 249, .82); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }
}
/* Same look and size on every page now (the style Dive Sites already had,
   dh-explorer-title, since folded into this one to drop the duplicate
   h1 that page and Operators both rendered separately). Was a small grey
   uppercase label anchored to its own fixed padding rather than the
   cards' left edge; now uses --dh-content-x like the cards and the
   Me-tab rows below them. */
.dh-pagehead-title { margin: 0; font-size: 1.5rem; font-weight: 800; color: var(--dh-ink); display: flex; align-items: center; gap: 10px; }
.dh-pagehead-icon { display: inline-flex; width: 26px; height: 26px; color: var(--dh-sea); flex: 0 0 auto; }
.dh-pagehead-icon svg { width: 100%; height: 100%; }
.dh-pagehead-icon.is-font { width: auto; height: auto; font-size: 24px; }
.dh-pagehead-guest { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: .8rem; color: var(--dh-sea); text-decoration: none; }
.dh-pagehead-guest .material-icons-round { font-size: 18px; }
/* Pins to the row's right edge whether or not the guest prompt above is
   also present - if it is, that already claimed the free space, so this
   just sits directly after it with the row's normal gap. */
.dh-pagehead .dh-pwa-back { margin-left: auto; }
.dh-pagehead-guest:hover { text-decoration: underline; color: var(--dh-deep); }

/* Horizontal chip rows on phones: swipe instead of wrap. */
/* !important beats Bootstrap's .flex-wrap utility on the same element. min-width: 0
   lets the row shrink below its content width inside .dh-filters (a column flex
   box), which is what makes overflow-x actually scroll instead of pushing the
   page wider. */
@media (max-width: 767.98px) {
  .dive-filter-chips { flex-wrap: nowrap !important; min-width: 0; max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding-bottom: 2px; }
  .dive-filter-chips > .chip { flex: 0 0 auto; }
  .dive-filter-chips > span { flex: 0 0 auto; }
  /* "More" arrow added by divershub.js when a row overflows. The wrapper is
     position: relative so the arrow sits on the row's right edge. */
  .dh-chip-scroll { position: relative; min-width: 0; }
  .dh-chip-scroll .dive-filter-chips { padding-right: 48px; }
  .dh-chip-more { position: absolute; top: 0; bottom: 2px; width: 48px; border: 0; padding: 0; display: flex; align-items: center; color: var(--dh-deep); cursor: pointer; }
  .dh-chip-more-right { right: 0; justify-content: flex-end; background: linear-gradient(to right, rgba(243,244,246,0), var(--dh-sand) 22%); }
  .dh-chip-more-left { left: 0; justify-content: flex-start; background: linear-gradient(to left, rgba(243,244,246,0), var(--dh-sand) 22%); }
  .dh-chip-more .material-icons-round { font-size: 22px; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 50%; box-shadow: 0 1px 3px rgba(11,42,58,.15); }
  .dh-chip-more[hidden] { display: none; }
  .dive-filter-chips::-webkit-scrollbar { display: none; }
}

/* ------------------------------------------------------------------ */
/* Trip board (W2) and trip cards.                                     */
/* ------------------------------------------------------------------ */
.dh-board { max-width: 1100px; margin: 0 auto; padding-left: var(--dh-space-3); padding-right: var(--dh-space-3); }

.dh-datebar { display: flex; align-items: center; justify-content: space-between; gap: var(--dh-space-3); margin: var(--dh-space-3) 0 var(--dh-space-2); }
.dh-datebar-center { display: flex; align-items: center; gap: var(--dh-space-2); min-width: 0; }
.dh-date-title { font-size: 1.35rem; font-weight: 800; margin: 0; color: var(--dh-ink); white-space: nowrap; }
.dh-datebtn { width: 40px; height: 40px; padding: 0; justify-content: center; }
.dh-datebtn[aria-disabled="true"] { opacity: .35; pointer-events: none; }
.dh-datepick { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%; color: var(--dh-sea); cursor: pointer; }
.dh-datepick:hover { background: var(--dh-foam); }
.dh-datepick input { position: absolute; inset: 0; opacity: 0; width: 100%; height: 100%; cursor: pointer; }

.dh-filters { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--dh-space-2); }
.dh-board-count { font-size: .8rem; color: var(--dh-muted); margin: 0 0 var(--dh-space-3); }
.dh-board-count a { color: var(--dh-sea); margin-left: 6px; }

/* Buttons used by the board and cards. */
.dh-btn { display: inline-flex; align-items: center; gap: 4px; padding: 7px 14px; border-radius: var(--dh-radius-pill); font-weight: 700; font-size: .85rem; text-decoration: none; border: 1.5px solid transparent; line-height: 1.2; white-space: nowrap; }
.dh-btn-primary { background: var(--dh-ink); color: #fff; border-color: var(--dh-ink); }
.dh-btn-primary:hover { background: var(--dh-deep); border-color: var(--dh-deep); color: #fff; }
.dh-btn-ghost-dark { background: #fff; color: var(--dh-ink); border-color: var(--dh-line); }
.dh-btn-ghost-dark:hover { border-color: var(--dh-ink); color: var(--dh-ink); }
.dh-btn-danger { background: var(--dh-poor); color: #fff; border-color: var(--dh-poor); }

/* Small round "?" next to "Overlay your actual dive log" (Pablo,
   2026-09-22), opens uddfHelpModal explaining where to get a UDDF export. */
.dh-uddf-help-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin-left: 6px; padding: 0;
  border-radius: 50%; border: 1.5px solid var(--dh-line);
  background: #fff; color: var(--dh-ink); cursor: pointer;
}
.dh-uddf-help-btn .material-icons-round { font-size: 16px; }
.dh-uddf-help-btn:hover { border-color: var(--dh-ink); }
.dh-btn-danger:hover { background: var(--dh-poor); border-color: var(--dh-poor); filter: brightness(.92); color: #fff; }
.dh-btn[disabled] { opacity: .5; pointer-events: none; cursor: default; }
.dh-link-danger { border: 0; background: none; padding: 0; color: var(--dh-poor); font-weight: 600; font-size: .85rem; text-decoration: underline; cursor: pointer; }
.dh-icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border: 0; background: none; padding: 0; color: var(--dh-muted); cursor: pointer; vertical-align: middle; }
.dh-icon-btn:hover { color: var(--dh-ink); }
.dh-icon-btn .material-icons-round { font-size: 18px; }

/* Notifications inbox (2026-09-13: Gmail-style list + reading pane,
   replacing the plain list + modal). .dh-msg-shell is a two-column grid on
   desktop (list | reading pane); on phones only one column shows at a time,
   toggled by .is-reading on the shell rather than by removing either pane
   from the DOM, so the reading pane's content only has to be filled in once
   per open, not rebuilt per breakpoint. */
.dh-msg-shell { display: grid; grid-template-columns: minmax(260px, 380px) 1fr; gap: var(--dh-space-4); align-items: start; }
.dh-msg-toolbar { display: flex; align-items: center; gap: 10px; padding: 10px 4px; border-bottom: 1px solid var(--dh-line); margin-bottom: 4px; flex-wrap: wrap; }
.dh-msg-tabs { display: flex; gap: 4px; }
.dh-msg-tab { border: 0; background: none; padding: 7px 14px; border-radius: var(--dh-radius-pill); font-weight: 700; font-size: .85rem; color: var(--dh-muted); cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.dh-msg-tab:hover { background: var(--dh-foam); color: var(--dh-ink); }
.dh-msg-tab.is-active { background: var(--dh-ink); color: #fff; }
.dh-msg-tab-count { font-size: .72rem; opacity: .8; }
.dh-msg-toolbar-actions { display: flex; align-items: center; gap: 8px; margin-left: auto; }
.dh-msg-select-all { width: 17px; height: 17px; accent-color: var(--dh-sea); cursor: pointer; }
.dh-msg-bulk-count { font-size: .8rem; color: var(--dh-muted); }

.dh-msg-search { display: flex; align-items: center; gap: 8px; background: var(--dh-foam); border-radius: var(--dh-radius-pill); padding: 8px 14px; margin-bottom: 8px; }
.dh-msg-search .material-icons-round { font-size: 19px; color: var(--dh-muted); }
.dh-msg-search input { flex: 1 1 auto; border: 0; background: transparent; outline: none; font-size: .85rem; color: var(--dh-ink); }
.dh-msg-search input::placeholder { color: var(--dh-muted); }

.dh-msg-list { display: flex; flex-direction: column; max-height: 70vh; overflow-y: auto; }
.dh-msg-row { display: flex; align-items: flex-start; gap: 10px; padding: 12px 8px; border-bottom: 1px solid var(--dh-line); cursor: pointer; border-radius: 10px; }
.dh-msg-row:last-child { border-bottom: 0; }
.dh-msg-row:hover { background: var(--dh-foam); }
.dh-msg-row.is-open { background: var(--dh-foam); }
.dh-msg-check { width: 16px; height: 16px; margin-top: 4px; accent-color: var(--dh-sea); cursor: pointer; flex: 0 0 auto; }
.dh-msg-avatar { width: 34px; height: 34px; border-radius: 50%; flex: 0 0 auto; object-fit: cover; background: var(--dh-foam); color: var(--dh-sea); display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: .8rem; }
.dh-msg-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }
.dh-msg-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; color: inherit; text-decoration: none; }
.dh-msg-row-top { display: flex; align-items: baseline; gap: 8px; }
.dh-msg-sender { font-size: .82rem; color: var(--dh-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-msg-row.is-unread .dh-msg-sender { color: var(--dh-ink); font-weight: 700; }
.dh-msg-date { margin-left: auto; font-size: .72rem; color: var(--dh-muted); flex: 0 0 auto; }
.dh-msg-subject { font-size: .87rem; color: var(--dh-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-msg-row.is-unread .dh-msg-subject { font-weight: 700; }
.dh-msg-snippet { font-size: .78rem; color: var(--dh-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-msg-unread-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dh-sea); flex: 0 0 auto; margin-top: 6px; }

/* Reading pane. */
.dh-msg-reading { background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; padding: var(--dh-space-4); min-height: 320px; }
.dh-msg-reading-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; height: 100%; min-height: 300px; color: var(--dh-muted); text-align: center; }
.dh-msg-reading-empty .material-icons-round { font-size: 40px; opacity: .5; }
.dh-msg-reading-back { display: none; border: 0; background: none; color: var(--dh-sea); font-weight: 700; padding: 0 0 12px; align-items: center; gap: 4px; cursor: pointer; }
.dh-msg-reading-head { display: flex; align-items: flex-start; gap: 12px; padding-bottom: 14px; margin-bottom: 14px; border-bottom: 1px solid var(--dh-line); }
.dh-msg-reading-head .dh-msg-avatar { width: 42px; height: 42px; font-size: .9rem; }
.dh-msg-reading-title { font-size: 1.05rem; font-weight: 800; color: var(--dh-ink); margin: 0 0 2px; }
.dh-msg-reading-from { font-size: .82rem; color: var(--dh-muted); }
.dh-msg-reading-actions { margin-left: auto; display: flex; gap: 6px; flex: 0 0 auto; }
.dh-msg-reading-body { font-size: .92rem; line-height: 1.6; color: var(--dh-ink); white-space: pre-wrap; }

@media (max-width: 899.98px) {
  .dh-msg-shell { display: block; }
  .dh-msg-reading { display: none; margin-top: var(--dh-space-3); }
  .dh-msg-shell.is-reading .dh-msg-list-pane { display: none; }
  .dh-msg-shell.is-reading .dh-msg-reading { display: block; }
  .dh-msg-reading-back { display: inline-flex; }
}

/* Region group. */
.dh-region { margin-bottom: var(--dh-space-6); }
.dh-region-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--dh-space-2) var(--dh-space-4); padding: 10px 14px; background: var(--dh-foam); border: 1px solid var(--dh-line); border-radius: var(--dh-radius); margin-bottom: var(--dh-space-2); }
.dh-region-title { font-size: 1.05rem; font-weight: 800; margin: 0; color: var(--dh-deep); }
.dh-region-count { font-size: .8rem; font-weight: 600; color: var(--dh-muted); margin-left: 6px; }
.dh-region-conditions { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; margin-left: auto; }
.dh-region-loc { display: inline-flex; align-items: center; gap: 4px; }
.dh-region-locname { font-size: .75rem; font-weight: 600; color: var(--dh-muted); margin-right: 2px; }
.dh-why { font-size: .75rem; color: var(--dh-sea); }
.dh-period { font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; color: var(--dh-muted); font-weight: 700; margin: var(--dh-space-2) 4px 4px; }
.dh-region-trips.is-collapsed > .dh-trip:nth-of-type(n+7) { display: none; }
.dh-showmore { display: block; width: 100%; margin-top: 6px; padding: 10px; background: #fff; border: 1px dashed var(--dh-line); border-radius: var(--dh-radius); color: var(--dh-sea); font-weight: 600; font-size: .85rem; }
.dh-showmore:hover { border-color: var(--dh-sea); background: var(--dh-foam); }

/* Sea state pill. */
.dh-pill { display: inline-flex; align-items: center; gap: 4px; font-size: .7rem; font-weight: 700; letter-spacing: .02em; padding: 2px 8px; border-radius: 4px; border: 1px solid var(--dh-line); background: #fff; color: var(--dh-muted); white-space: nowrap; }
.dh-pill-label { opacity: .7; font-weight: 600; }
.dh-pill-good { color: var(--dh-good); border-color: var(--dh-good); background: var(--dh-good-bg); }
.dh-pill-avg  { color: var(--dh-avg);  border-color: var(--dh-avg);  background: var(--dh-avg-bg); }
.dh-pill-poor { color: var(--dh-poor); border-color: var(--dh-poor); background: var(--dh-poor-bg); }

/* Saved-dive shape pills in the Deco Planner's "Open a dive" list (Pablo,
   2026-09-25: "OC: theme dark blue - CC: light dark blue - Single Level:
   theme dark blue - Multi Level: theme light blue"). */
.dh-pill-oc, .dh-pill-single { color: #fff; border-color: var(--dh-deep); background: var(--dh-deep); }
.dh-pill-cc                  { color: #fff; border-color: var(--dh-sea);  background: var(--dh-sea); }
.dh-pill-multi                { color: #fff; border-color: var(--dh-shallow); background: var(--dh-shallow); }

/* Group public/private visibility badge - dark blue for Public, light blue
   for Private (Pablo, 2026-09-23), reusing the same solid-fill pill look
   as the auto-add rule's AND/OR pills for a consistent "status badge" feel. */
.dh-pill-visibility { display: inline-flex; align-items: center; gap: 4px; padding: 3px 10px; border-radius: var(--dh-radius-pill); font-size: .7rem; font-weight: 700; letter-spacing: .02em; color: #fff; white-space: nowrap; }
.dh-pill-visibility .material-icons-round { font-size: .95rem; }
.dh-pill-public { background: var(--dh-deep); }
.dh-pill-private { background: var(--dh-shallow); }
/* Smaller here only - the calling card's avatar is a fixed 64px, so the
   pill under it reads better a size down (Pablo, 2026-09-23: "a little
   bit smaller"). My Groups keeps the default .dh-pill-visibility size. */
.dh-group-facts-pill .dh-pill-visibility { font-size: .6rem; padding: 2px 7px; gap: 3px; }
.dh-group-facts-pill .dh-pill-visibility .material-icons-round { font-size: .8rem; }

/* Card. */
.dh-trip { display: grid; grid-template-columns: 62px minmax(0, 1fr) auto; gap: var(--dh-space-3); align-items: center; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: 10px 12px; margin-bottom: 6px; }
.dh-trip.is-fav { border-left: 3px solid var(--dh-sea); }
.dh-trip.is-departed { opacity: .55; }
.dh-trip.is-cancelled { opacity: .7; }
.dh-trip.is-cancelled .dh-trip-title span { text-decoration: line-through; color: var(--dh-muted); }
.dh-trip-time { text-align: center; border-right: 1px solid var(--dh-line); padding-right: 10px; line-height: 1.1; }
.dh-trip-hour { display: block; font-size: 1.15rem; font-weight: 800; color: var(--dh-ink); }
.dh-trip-ampm, .dh-trip-date { display: block; font-size: .65rem; font-weight: 700; letter-spacing: .06em; color: var(--dh-muted); }
.dh-trip-date { margin-bottom: 2px; }
.dh-trip-body { min-width: 0; }
.dh-trip-title { font-size: .98rem; font-weight: 700; margin: 0 0 2px; line-height: 1.25; }
.dh-trip-title a { color: var(--dh-ink); text-decoration: none; }
.dh-trip-title a:hover { color: var(--dh-sea); }
.dh-trip-favicon { font-size: 16px; color: var(--dh-sea); vertical-align: -3px; margin-left: 4px; }
.dh-trip-meta { font-size: .8rem; color: var(--dh-muted); margin: 0 0 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-trip-meta a { color: var(--dh-muted); text-decoration: none; }
.dh-trip-meta a:hover { color: var(--dh-sea); text-decoration: underline; }
.dh-dot { margin: 0 4px; }
.dh-visited { color: var(--dh-good); font-weight: 600; }
.dh-trip-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.chip.chip-static { padding: 2px 8px; font-size: .7rem; cursor: default; }
.dh-trip-action { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.dh-avail { font-size: .75rem; font-weight: 700; white-space: nowrap; }
.dh-avail-open { color: var(--dh-good); }
.dh-avail-few { color: var(--dh-avg); }
.dh-avail-full { color: var(--dh-poor); }
.dh-avail-call { color: var(--dh-muted); }
.dh-avail-departed { color: var(--dh-muted); }
.dh-avail-cancelled { color: var(--dh-poor); }

.chip-cancelled { background: var(--dh-poor); border-color: var(--dh-poor); color: #fff; }

.dh-empty { text-align: center; padding: var(--dh-space-6); color: var(--dh-muted); }
.dh-empty .material-icons-round { font-size: 40px; color: var(--dh-shallow); }

/* Installed-PWA-only back control (components/shell/pwa-back.blade.php) -
   starts [hidden], material-dashboard.css's [hidden]{display:none!important}
   keeps it that way in an ordinary browser tab until its own script confirms
   standalone display-mode and reveals it. Lives in the page's own <x-shell.
   header> row (Pablo, 2026-09-18: "in the blog where it says 'blog'...
   Dive Sites, Dive Operators, Dive Trip Details and Blog") - see the
   .dh-pagehead .dh-pwa-back rule above for how it pins to that row's right
   edge; this one is just its own look. */
.dh-pwa-back { display: inline-flex; align-items: center; gap: 4px; font-size: .85rem; font-weight: 700; color: var(--dh-ink); text-decoration: none; flex-shrink: 0; }
.dh-pwa-back:hover { color: var(--dh-sea); }
.dh-pwa-back .material-icons-round { font-size: 18px; }

/* Groups (MyGroups, retheme 2026-09-11). */
.dh-groups-toolbar { display: flex; justify-content: flex-end; margin: var(--dh-space-3) 0; }
.dh-invite-list { list-style: none; margin: 0; padding: 0; }
.dh-invite-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--dh-line); flex-wrap: wrap; }
.dh-invite-row:last-child { border-bottom: 0; }
.dh-invite-actions { display: flex; gap: 8px; }
.dh-group-list { list-style: none; margin: 0; padding: 0; }
.dh-group-row { display: flex; align-items: center; gap: 12px; padding: 12px 4px; border-bottom: 1px solid #eef1f3; text-decoration: none; color: var(--dh-ink); }
.dh-group-list li:last-child .dh-group-row { border-bottom: 0; }
.dh-group-row:hover { background: var(--dh-foam); color: var(--dh-ink); }
.dh-group-avatar { width: 44px; height: 44px; border-radius: 50%; overflow: hidden; flex: 0 0 auto; background: var(--dh-sea); color: #fff; display: flex; align-items: center; justify-content: center; }
.dh-group-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Admin badge over the calling card's bottom-right corner (Pablo,
   2026-09-24) - a wrapper because .dh-group-avatar itself clips
   (overflow: hidden), which would cut the badge off at the edge. */
.dh-group-avatar-wrap { position: relative; flex: 0 0 auto; display: inline-flex; }
.dh-group-admin-badge { position: absolute; bottom: -2px; right: -2px; width: 18px; height: 18px; border-radius: 50%; background: var(--dh-deep); color: #fff; display: flex; align-items: center; justify-content: center; border: 2px solid var(--dh-paper); }
.dh-group-admin-badge .material-icons-round { font-size: 11px; }
.dh-group-info { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.dh-group-name { font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-group-meta { font-size: .8rem; color: var(--dh-muted); }
.dh-group-avatars { flex: 0 0 auto; }
.dh-group-arrow { color: var(--dh-muted); flex: 0 0 auto; }
@media (max-width: 480px) { .dh-group-avatars { display: none; } }
.dh-group-hero { position: relative; height: 180px; border-radius: var(--dh-radius); background-size: cover; background-position: center; background-color: var(--dh-foam); margin-top: var(--dh-space-3); }
.dh-group-hero-btn { position: absolute; top: 12px; right: 12px; }
.dh-group-facts { display: flex; flex-wrap: wrap; gap: var(--dh-space-4); justify-content: space-between; align-items: center; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; padding: var(--dh-space-4) var(--dh-space-6); margin: var(--dh-space-3) 0; }
.dh-group-facts-main { display: flex; align-items: center; gap: var(--dh-space-3); flex: 1 1 320px; min-width: 0; }
.dh-group-facts-avatar { flex: 0 0 auto; width: 64px; height: 64px; border-radius: 50%; overflow: hidden; display: block; border: 3px solid var(--dh-sea); }
.dh-group-facts-avatar img { width: 100%; height: 100%; object-fit: cover; }
.dh-group-facts-title { font-size: 1.3rem; font-weight: 800; color: var(--dh-ink); margin: 0; }
.dh-group-facts-meta { color: var(--dh-muted); margin: 2px 0 0; font-size: .88rem; }
.dh-group-facts-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: stretch; }
.dh-group-facts-actions .dh-btn { box-sizing: border-box; }

/* Group chat, WhatsApp style (2026-09-11): own messages right-aligned in the
   theme's sea blue, everyone else's left-aligned in a neutral bubble. */
.dh-chat-row { display: flex; align-items: flex-end; gap: 8px; margin-bottom: 12px; }
.dh-chat-row.is-mine { flex-direction: row-reverse; }
.dh-chat-avatar { flex: 0 0 auto; }
.dh-chat-bubble-wrap { display: flex; flex-direction: column; max-width: 75%; min-width: 0; }
.dh-chat-row.is-mine .dh-chat-bubble-wrap { align-items: flex-end; }
.dh-chat-meta { font-size: .7rem; color: var(--dh-muted); }
.dh-chat-bubble { background: var(--dh-foam); border-radius: 14px 14px 14px 4px; padding: 8px 12px; margin-top: 2px; }
.dh-chat-row.is-mine .dh-chat-bubble { background: var(--dh-sea); color: #fff; border-radius: 14px 14px 4px 14px; }
.dh-chat-text { font-size: .88rem; overflow-wrap: break-word; }
.dh-chat-time { margin-top: 2px; }
.dh-form-error { background: var(--dh-poor-bg); color: var(--dh-poor); border-radius: var(--dh-radius); padding: 12px 16px; margin-bottom: var(--dh-space-3); font-size: .88rem; }
.dh-form-error ul { padding-left: 18px; }
.dh-fb-page-list { display: flex; flex-direction: column; gap: 8px; }
.dh-fb-page-option { display: flex; align-items: center; gap: 10px; border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: 10px 14px; cursor: pointer; transition: background-color .15s ease, color .15s ease, border-color .15s ease; }
.dh-fb-page-option:hover { border-color: var(--dh-sea); }
.dh-fb-page-option.is-selected { background: var(--dh-sea); color: #fff; border-color: var(--dh-sea); }
.dh-fb-page-radio { accent-color: var(--dh-sea); width: 18px; height: 18px; flex: 0 0 auto; }
.dh-panel-divider { border: 0; border-top: 1px solid var(--dh-line); margin: var(--dh-space-3) 0; }
.dh-fb-post { display: flex; gap: 10px; padding-bottom: var(--dh-space-3); margin-bottom: var(--dh-space-3); border-bottom: 1px solid var(--dh-line); }
.dh-fb-post:last-child { border-bottom: 0; margin-bottom: 0; padding-bottom: 0; }
.dh-fb-post-img { width: 70px; height: 70px; object-fit: cover; border-radius: var(--dh-radius); flex: 0 0 auto; }
.dh-fb-post-body { min-width: 0; }
.dh-fb-post-text { font-size: .88rem; margin: 0 0 4px; overflow-wrap: break-word; }
.dh-fb-post-time { font-size: .76rem; color: var(--dh-muted); margin: 0 0 4px; }
.dh-fb-post-link { font-size: .76rem; color: var(--dh-sea); font-weight: 700; text-decoration: none; }

@media (max-width: 575.98px) {
  .dh-trip { grid-template-columns: 52px minmax(0, 1fr); }
  .dh-trip-action { grid-column: 1 / -1; flex-direction: row; justify-content: space-between; align-items: center; border-top: 1px dashed var(--dh-line); padding-top: 8px; }
  .dh-region-conditions { margin-left: 0; width: 100%; }
  .dh-date-title { font-size: 1.15rem; }
}

/* ------------------------------------------------------------------ */
/* Home (W1).                                                          */
/* ------------------------------------------------------------------ */
.dh-home { max-width: 1100px; margin: 0 auto; padding-left: var(--dh-space-3); padding-right: var(--dh-space-3); }
.dh-hero { position: relative; min-height: 300px; border-radius: 16px; background-size: cover; background-position: center; display: flex; align-items: flex-end; padding: var(--dh-space-4); margin-top: var(--dh-space-3); overflow: hidden; }
.dh-hero::before { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(11,42,58,.75), rgba(11,42,58,.05) 60%); }
.dh-hero-card { position: relative; z-index: 1; background: rgba(255,255,255,.94); border-radius: var(--dh-radius); padding: var(--dh-space-4) var(--dh-space-6); max-width: 560px; }
.dh-hero-card h1 { font-size: clamp(1.4rem, 3vw, 2rem); font-weight: 800; color: var(--dh-ink); margin: 0 0 6px; letter-spacing: -.01em; }
.dh-hero-card p { color: var(--dh-muted); margin: 0 0 var(--dh-space-3); font-size: .95rem; }
.dh-hero-actions { display: flex; flex-wrap: wrap; gap: var(--dh-space-2); }

.dh-section-head { display: flex; align-items: baseline; justify-content: space-between; margin: var(--dh-space-6) 0 var(--dh-space-3); }
.dh-section-head h2 { font-size: 1.1rem; font-weight: 800; color: var(--dh-ink); margin: 0; }

.dh-strip-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: var(--dh-space-2); }
.dh-coast { display: flex; flex-direction: column; gap: 6px; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: 12px 14px; text-decoration: none; color: var(--dh-ink); }
.dh-coast:hover { border-color: var(--dh-sea); box-shadow: 0 4px 14px rgba(14,124,158,.12); color: var(--dh-ink); }
.dh-coast-name { font-weight: 800; }
.dh-coast-pills { display: flex; gap: 4px; flex-wrap: wrap; }
.dh-coast-boats { font-size: .85rem; color: var(--dh-deep); }

.dh-site-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--dh-space-3); }
.dh-site-card { position: relative; display: flex; flex-direction: column; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: var(--dh-radius); overflow: hidden; text-decoration: none; color: var(--dh-ink); }
.dh-site-link { display: flex; flex-direction: column; flex: 1 1 auto; color: inherit; text-decoration: none; }
.dh-site-link:hover { color: inherit; }
.dh-site-card:hover { border-color: var(--dh-sea); color: var(--dh-ink); box-shadow: 0 4px 14px rgba(14,124,158,.12); }
.dh-site-img { position: relative; display: block; aspect-ratio: 16 / 9; background-size: cover; background-position: center; background-color: var(--dh-foam); overflow: hidden; }
.dh-site-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.dh-site-type { position: absolute; top: 8px; left: 8px; background: rgba(255,255,255,.92); }
.dh-site-body { padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 6px; }
.dh-site-name { font-weight: 700; line-height: 1.25; }
.dh-site-card-facts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 2px; }
.dh-site-level { display: inline-flex; align-items: center; gap: 6px; font-size: .85rem; font-weight: 700; color: var(--dh-deep); background: var(--dh-foam); border-radius: var(--dh-radius-pill); padding: 2px 10px 2px 4px; }
.dh-site-level img { width: 22px; height: 22px; display: block; }
.dh-site-fact { font-size: .85rem; font-weight: 600; color: var(--dh-muted); }
.dh-site-fact + .dh-site-fact::before, .dh-site-level + .dh-site-fact::before { content: "·"; margin-right: 8px; color: var(--dh-line); }
.dh-site-rate { color: var(--dh-ink); }

.dh-cta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--dh-space-4); margin: var(--dh-space-6) 0; padding: var(--dh-space-4) var(--dh-space-6); background: var(--dh-foam); border: 1px solid var(--dh-line); border-radius: 16px; }
.dh-cta h2 { font-size: 1.1rem; font-weight: 800; margin: 0 0 4px; color: var(--dh-deep); }
.dh-cta p { margin: 0; color: var(--dh-muted); font-size: .9rem; max-width: 60ch; }

@media (max-width: 575.98px) {
  .dh-hero { min-height: 240px; padding: var(--dh-space-2); }
  .dh-hero-card { padding: var(--dh-space-3) var(--dh-space-4); }
  .dh-strip-row { grid-template-columns: 1fr 1fr; }
  .dh-site-grid { grid-template-columns: 1fr 1fr; }
}

/* Drawer extras: unread badge, translator block. */
.dh-menu-badge { margin-left: auto; background: var(--dh-poor); color: #fff; font-size: .7rem; font-weight: 700; border-radius: var(--dh-radius-pill); padding: 2px 8px; }
.dh-menu-translate { padding: 0 12px; }
.dh-trip-hour-tbd { font-size: .9rem; color: var(--dh-muted); }

/* ------------------------------------------------------------------ */
/* Sites explorer (W4) and site detail (W3).                           */
/* ------------------------------------------------------------------ */
.dh-explorer-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--dh-space-3); margin: var(--dh-space-3) 0 var(--dh-space-3); }
.dh-explorer-intro { color: var(--dh-muted); margin: 4px 0 0; font-size: .9rem; max-width: 60ch; }
.dh-omnibox { position: relative; display: flex; align-items: center; gap: 8px; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill); padding: 8px 14px; min-width: min(360px, 100%); flex: 1 1 320px; max-width: 480px; }
.dh-omnibox:focus-within { border-color: var(--dh-sea); box-shadow: 0 0 0 3px var(--dh-foam); }
.dh-omnibox input { border: 0; outline: none; background: transparent; flex: 1; font-size: .95rem; color: var(--dh-ink); }
.dh-omnibox .material-icons-round { color: var(--dh-muted); }
.dh-omnibox-clear { color: var(--dh-muted); text-decoration: none; font-size: 1.2rem; line-height: 1; }
.dh-site-grid-wide { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.dh-site-loc { font-size: .8rem; color: var(--dh-muted); }
.dh-site-shore { position: absolute; bottom: 8px; left: 8px; background: rgba(255,255,255,.92); }
.dh-map { width: 100%; height: 70vh; min-height: 420px; border-radius: var(--dh-radius); border: 1px solid var(--dh-line); background: var(--dh-foam); }
.dh-map-small { height: 280px; min-height: 0; }

/* Weather "All locations": Pablo's original Florida1.png with hand-placed
   pins (2026-09-11), restored in place of the Mapbox pin map. Pins are
   positioned in JS-free inline styles (top/left in px) matching the
   original coordinates 1:1, offset down 24px so the ones placed above the
   image's own top edge (Stuart, Port St Lucie) aren't clipped. */
.dh-wx-florida {
  position: relative; width: fit-content; max-width: 100%; margin: 0 auto;
  padding: 24px 16px 10px; border-radius: var(--dh-radius);
  background: var(--dh-deep);
}
.dh-wx-florida-img { display: block; height: 200px; width: auto; max-width: 100%; }
.dh-wx-florida-pin {
  position: absolute; width: 14px; height: 14px; margin: -7px 0 0 -7px;
  border-radius: 50%; background: #fff; border: 2px solid var(--dh-sea);
  box-shadow: 0 1px 3px rgba(0,0,0,.45); transition: transform .15s ease, border-color .15s ease;
}
.dh-wx-florida-pin:hover { border-color: var(--dh-sand); transform: scale(1.2); }
.dh-wx-florida-pin.is-here { border-color: var(--dh-ink); border-width: 3px; width: 18px; height: 18px; margin: -9px 0 0 -9px; }

/* Site detail. */
.dh-site-hero { display: grid; grid-template-columns: 2fr 1fr; gap: var(--dh-space-2); margin-top: var(--dh-space-3); height: 340px; }
.dh-site-hero-main, .dh-site-hero-side a { display: block; border-radius: 14px; background-size: cover; background-position: center; background-color: var(--dh-foam); }
.dh-site-hero-side { display: grid; grid-template-rows: 1fr 1fr; gap: var(--dh-space-2); position: relative; }
.dh-site-hero-more { position: absolute; right: 10px; bottom: 10px; background: rgba(11,42,58,.85); color: #fff; font-size: .75rem; font-weight: 700; padding: 4px 10px; border-radius: var(--dh-radius-pill); }
.dh-site-facts { display: flex; flex-wrap: wrap; gap: var(--dh-space-4); justify-content: space-between; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; padding: var(--dh-space-4) var(--dh-space-6); margin: var(--dh-space-3) 0; }
.dh-site-facts-main { flex: 1 1 360px; min-width: 0; }
.dh-site-title { font-size: clamp(1.4rem, 3vw, 2rem); font-weight: 800; color: var(--dh-ink); margin: 0 0 4px; letter-spacing: -.01em; }
.dh-site-sub { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; color: var(--dh-deep); font-weight: 600; margin: 0 0 10px; }
.dh-site-type-icon { display: inline-flex; width: 26px; height: 26px; color: var(--dh-sea); flex: 0 0 auto; }
.dh-site-type-icon svg { width: 100%; height: 100%; }
.dh-site-gps { font-size: .76rem; font-weight: 600; color: var(--dh-muted); margin: -6px 0 10px; }
.dh-site-gps-map { margin: 8px 0 0; }
.dh-aka-toggle { border: 0; background: none; padding: 0; color: var(--dh-sea); font-weight: 700; font-size: .85rem; text-decoration: underline; cursor: pointer; }

/* Wreck Details card. */
.dh-wreck-sunk { font-size: .78rem; font-weight: 600; color: var(--dh-muted); white-space: nowrap; }
.dh-wreck-type { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 8px; font-size: 1rem; color: var(--dh-ink); padding-bottom: 14px; margin-bottom: 14px; border-bottom: 1px solid var(--dh-line); }
.dh-wreck-type-icon { display: inline-flex; width: 120px; height: 120px; color: var(--dh-sea); flex: 0 0 auto; }
.dh-wreck-type-icon svg { width: 100%; height: 100%; }
.dh-wreck-dims { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; text-align: center; }
.dh-wreck-dims div { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.dh-wreck-dims b { font-size: 1rem; color: var(--dh-ink); }
.dh-wreck-dims span { font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; color: var(--dh-muted); font-weight: 700; }
.dh-wreck-dim-icon { display: inline-flex; width: 34px; height: 34px; color: var(--dh-sea); }
.dh-wreck-dim-icon svg { width: 100%; height: 100%; }

/* Full-size photo modal, replacing the old open-in-a-new-tab gallery links. */
.dh-photo-modal .modal-content { background: transparent; border: 0; box-shadow: none; }
.dh-photo-modal img { width: 100%; height: auto; max-height: 85vh; object-fit: contain; border-radius: var(--dh-radius); }
/* A real Material icon, not Bootstrap's .btn-close (Pablo, 2026-09-24,
   round two: still "just a white circle" after fixing the background
   shorthand that was erasing it - turned out Bootstrap's close SVG is a
   hardcoded WHITE X, invisible against this white circle regardless of
   the shorthand bug. Explicit dark icon sidesteps that entirely. */
.dh-photo-modal-close { position: absolute; top: -12px; right: -12px; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; background-color: #fff; border: 0; border-radius: 50%; padding: 0; z-index: 1; box-shadow: 0 2px 8px rgba(0,0,0,.3); cursor: pointer; }
.dh-photo-modal-close .material-icons-round { font-size: 20px; color: var(--dh-ink); }

/* Diver-uploaded site pictures (Pablo, 2026-09-23) - a 2x2 mosaic, paged
   4-at-a-time via horizontal scroll-snap when there are more than 4
   ("a carrousel of 4 pictures swiping right"). */
.dh-diver-carousel { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; gap: var(--dh-space-3); -webkit-overflow-scrolling: touch; }
.dh-diver-carousel::-webkit-scrollbar { display: none; }
.dh-diver-page { flex: 0 0 100%; scroll-snap-align: start; display: grid; grid-template-columns: 1fr 1fr; gap: var(--dh-space-2); }
.dh-diver-tile-figure { margin: 0; }
.dh-diver-tile { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: pointer; }
.dh-diver-tile img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--dh-radius); display: block; }
.dh-diver-tile-caption { display: flex; justify-content: space-between; gap: 6px; font-size: .72rem; color: var(--dh-muted); margin-top: 4px; }
.dh-diver-tile-name { font-weight: 700; color: var(--dh-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-diver-carousel-hint { display: flex; align-items: center; gap: 4px; justify-content: center; font-size: .72rem; color: var(--dh-muted); margin: 8px 0 0; }
.dh-diver-carousel-hint .material-icons-round { font-size: 16px; }

/* Full-size diver photo modal - overlay credit bar over the picture
   (Pablo, 2026-09-23: "Overlay name, avatar and date over the picture"). */
.dh-diver-modal-frame { position: relative; }
.dh-diver-modal-overlay { position: absolute; left: 0; right: 0; bottom: 0; display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-radius: 0 0 var(--dh-radius) var(--dh-radius); background: linear-gradient(0deg, rgba(0,0,0,.75), rgba(0,0,0,0)); }
.dh-diver-modal-text { display: flex; flex-direction: column; min-width: 0; }
.dh-diver-modal-name { color: #fff; font-weight: 700; font-size: .9rem; }
.dh-diver-modal-date { color: rgba(255,255,255,.85); font-size: .72rem; }

/* Contribute-a-picture nudge, a slim in-flow bar at the top of the site
   page (Pablo, 2026-09-24: moved off a fixed bottom popup that "covered
   the navigation bar" - "without taking too much space"). */
.dh-photo-cta-bar { display: flex; align-items: center; gap: 8px; background: var(--dh-foam); border: 1px solid var(--dh-sea); border-radius: var(--dh-radius); padding: 8px 12px; margin-bottom: var(--dh-space-3); color: var(--dh-deep); }
.dh-photo-cta-bar > .material-icons-round { font-size: 18px; flex: 0 0 auto; }
.dh-photo-cta-text { flex: 1 1 auto; font-size: .82rem; font-weight: 600; }
.dh-photo-cta-btn { flex: 0 0 auto; background: var(--dh-deep); color: #fff; border: 0; border-radius: var(--dh-radius-pill); padding: 4px 14px; font-size: .78rem; font-weight: 700; cursor: pointer; }
.dh-photo-cta-dismiss { background: none; border: 0; color: var(--dh-muted); padding: 2px; cursor: pointer; flex: 0 0 auto; display: flex; }
.dh-photo-cta-dismiss:hover { color: var(--dh-ink); }
@media (max-width: 576px) { .dh-photo-cta-text { display: none; } }

/* Site-wide "turn on notifications" nag (Pablo, 2026-09-24) - a bottom
   popup on purpose ("as requested"), but resting just above the mobile
   tab bar rather than over it like the diver-photo one used to. */
.dh-bottom-popup { position: fixed; left: 12px; right: 12px; bottom: 12px; z-index: 1040; display: flex; align-items: center; gap: 10px; background: var(--dh-deep); color: #fff; border-radius: var(--dh-radius); padding: 12px 14px; box-shadow: 0 8px 24px rgba(0,0,0,.25); }
.dh-bottom-popup > .material-icons-round { flex: 0 0 auto; }
.dh-bottom-popup-text { flex: 1 1 auto; font-size: .85rem; font-weight: 600; }
.dh-bottom-popup-btn { flex: 0 0 auto; background: #fff; color: var(--dh-deep); border: 0; border-radius: var(--dh-radius-pill); padding: 6px 14px; font-size: .82rem; font-weight: 700; cursor: pointer; }
.dh-bottom-popup-dismiss { background: none; border: 0; color: rgba(255,255,255,.8); padding: 4px; cursor: pointer; flex: 0 0 auto; display: flex; }
.dh-bottom-popup-dismiss:hover { color: #fff; }
@media (max-width: 991.98px) { .dh-bottom-popup { bottom: calc(var(--dh-tabbar-h) + env(safe-area-inset-bottom) + 12px); } }
@media (max-width: 576px) { .dh-bottom-popup-text { display: none; } }

/* "My uploaded pictures" on the profile overview page. */
.dh-my-photos-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--dh-space-3); }
.dh-my-photo { margin: 0; position: relative; }
.dh-my-photo img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--dh-radius); display: block; }
.dh-my-photo figcaption { display: flex; flex-direction: column; font-size: .72rem; color: var(--dh-muted); margin-top: 4px; }
.dh-my-photo figcaption a { color: var(--dh-ink); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-my-photo-date { color: var(--dh-muted); }
.dh-my-photo-status { position: absolute; top: 6px; left: 6px; }
.dh-my-photo-remove { position: absolute; top: 6px; right: 6px; margin: 0; }
.dh-my-photo-remove button { background: rgba(0,0,0,.55); border: 0; color: #fff; width: 26px; height: 26px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; }
.dh-my-photo-remove button:hover { background: var(--dh-poor); }
.dh-my-photo-remove .material-icons-round { font-size: 16px; }

/* Platform Health (admin). */
.dh-health-table-wrap { overflow-x: auto; padding: 0; }
.dh-health-table { width: 100%; border-collapse: collapse; font-size: .85rem; white-space: nowrap; }
.dh-health-table th { text-align: left; padding: 10px 15px; font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--dh-muted); border-bottom: 1px solid var(--dh-line); }
.dh-health-table td { padding: 8px 15px; border-bottom: 1px solid #eef1f3; color: var(--dh-ink); vertical-align: middle; }
.dh-health-table tbody tr:last-child td { border-bottom: 0; }
.dh-health-table tbody tr:hover { background: var(--dh-foam); }
.dh-health-name { font-weight: 700; white-space: normal; }
.dh-health-logo { width: 34px; height: 34px; object-fit: contain; border-radius: 8px; background: #fff; border: 1px solid var(--dh-line); }
.dh-health-pill { display: inline-flex; align-items: center; gap: 5px; font-weight: 700; font-size: .78rem; padding: 4px 10px; border-radius: var(--dh-radius-pill); white-space: nowrap; }
.dh-health-pill .material-icons-round { font-size: 16px; }
.dh-health-pill.is-good { background: var(--dh-good-bg); color: var(--dh-good); }
.dh-health-pill.is-wait { background: var(--dh-avg-bg); color: var(--dh-avg); }
.dh-health-pill.is-run  { background: var(--dh-foam); color: var(--dh-sea); }
.dh-health-pill.is-poor { background: var(--dh-poor-bg); color: var(--dh-poor); }
.dh-health-pill.is-none { background: var(--dh-line); color: var(--dh-muted); }

/* Operators scraping / not scraping / Weather API are <details> now, collapsed by
   default under the summary dashboard above them. */
details.dh-card > summary.dh-card-head { cursor: pointer; list-style: none; justify-content: flex-start; }
details.dh-card > summary.dh-card-head::-webkit-details-marker { display: none; }
details.dh-card > summary.dh-card-head::after { content: 'expand_more'; font-family: 'Material Icons Round'; font-size: 20px; color: var(--dh-muted); margin-left: auto; }
details.dh-card[open] > summary.dh-card-head::after { content: 'expand_less'; }

/* Platform Health "at a glance" summary. */
.dh-health-stats { display: flex; flex-wrap: wrap; gap: 10px; }
.dh-health-stat { flex: 1 1 120px; display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 14px 10px; border-radius: var(--dh-radius); background: var(--dh-sand); }
.dh-health-stat .material-icons-round { font-size: 22px; }
/* Google/Divers Hub logos on the User Management mini dashboard (Pablo,
   2026-09-24), same size as the icon-font stat tiles next to them. */
.dh-health-stat-icon { width: 22px; height: 22px; object-fit: contain; }
.dh-health-stat-n { font-size: 1.5rem; font-weight: 800; line-height: 1; }
.dh-health-stat-label { font-size: .75rem; color: var(--dh-muted); text-align: center; }
.dh-health-stat.is-run { color: var(--dh-sea); }
.dh-health-stat.is-good { color: var(--dh-good); }
.dh-health-stat.is-wait { color: var(--dh-avg); }
.dh-health-stat.is-poor { color: var(--dh-poor); }
.dh-health-stat.is-none { color: var(--dh-muted); }
.dh-health-stat .dh-health-stat-n { color: var(--dh-ink); }
.dh-health-errored { display: flex; align-items: flex-start; gap: 6px; margin: 14px 0 0; padding: 10px 12px; background: var(--dh-poor-bg); color: var(--dh-poor); border-radius: var(--dh-radius); font-size: .85rem; }
.dh-health-errored .material-icons-round { font-size: 18px; flex: 0 0 auto; margin-top: 1px; }
.dh-health-wx-summary { display: flex; align-items: flex-start; gap: 6px; margin: 10px 0 0; font-size: .85rem; color: var(--dh-muted); }
.dh-health-wx-summary .material-icons-round { font-size: 18px; flex: 0 0 auto; margin-top: 1px; color: var(--dh-sea); }
.dh-site-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.dh-site-chips .chip img { vertical-align: -3px; margin-right: 2px; }
.dh-site-facts-side { display: flex; flex-direction: column; align-items: flex-end; gap: var(--dh-space-3); }
.dh-site-rating { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.dh-page-actions { display: flex; gap: var(--dh-space-2); flex-wrap: wrap; }
.dh-page-actions .material-icons-round { font-size: 18px; }
.dh-dived-toggle input[type="checkbox"] { position: absolute; opacity: 0; pointer-events: none; }
.dh-dived-toggle label { cursor: pointer; }
.dh-dived-toggle .is-on { background: var(--dh-good-bg); border-color: var(--dh-good); color: var(--dh-good); }
.dh-site-columns { margin-bottom: var(--dh-space-3); }
.dh-panel { background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; padding: var(--dh-space-4); margin-bottom: var(--dh-space-3); }
.dh-panel-title { font-size: 1rem; font-weight: 800; color: var(--dh-ink); margin: 0 0 var(--dh-space-3); }
/* A panel whose title shares its row with a control (e.g. Best Gas's "show
   details" switch), and a two-up layout for panels merging two subsections
   (e.g. Route + Typical conditions) that stacks on phones. */
.dh-panel-head-row { display: flex; align-items: center; justify-content: space-between; gap: var(--dh-space-3); flex-wrap: wrap; margin-bottom: var(--dh-space-3); }
.dh-panel-head-row .dh-panel-title { margin-bottom: 0; }
.dh-panel-toggle { display: flex; align-items: center; gap: 6px; }
.dh-panel-toggle .form-check-label { color: var(--dh-muted); font-size: .85rem; font-weight: 600; }
.dh-panel-cols { display: grid; grid-template-columns: 1fr 1fr; gap: var(--dh-space-4); }

/* Members/Upcoming-dives/Facebook-feed/Chat (Groups page): all four share
   the same 350px scroll cap (each card's own inline max-height/
   overflow-y), AND the column/panel/scroll-area all stretch to fill
   whatever height Bootstrap's row already equalizes the pair to
   (Pablo, 2026-09-23, after the two prior attempts: unifying the caps
   alone left a gap under a short card's content whenever its row
   sibling's OWN total height - e.g. Chat's compose box below its
   message list - made the row taller than that card's own content;
   "Make the Upcoming dives card longer...make sure the content takes
   all the height of the card"). Since every card's cap already agrees
   at 350px, letting the scroll area flex-grow can never ask for more
   than that cap allows either way, so this doesn't reintroduce the
   unbounded-growth risk the first flex attempt had no cap against. */
.dh-equal-card-col { display: flex; }
.dh-equal-card-col > .dh-panel { flex: 1 1 auto; display: flex; flex-direction: column; }
.dh-equal-card-col .dh-equal-card-scroll { flex: 1 1 auto; min-height: 0; }
/* Wider content column for a form whose main field is a long body of text (the newsletter composer) - still collapses to one column below, same as the plain .dh-panel-cols. */
.dh-panel-cols-wide { grid-template-columns: 2.4fr 1fr; }
.dh-panel-subtitle { font-size: .78rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--dh-muted); margin: 0 0 8px; }
@media (max-width: 767.98px) { .dh-panel-cols { grid-template-columns: 1fr; } }
.dh-site-details { display: grid; grid-template-columns: 200px 1fr; gap: var(--dh-space-4); align-items: center; }
.dh-facts-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: var(--dh-space-3); margin: 0; }
.dh-facts-list dt { font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: var(--dh-muted); font-weight: 700; }
.dh-facts-list dd { margin: 0; font-weight: 700; color: var(--dh-ink); }
.dh-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: var(--dh-space-2); }
.dh-gallery-item { margin: 0; }
.dh-gallery-item img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--dh-radius); display: block; }
.dh-gallery-item figcaption { font-size: .75rem; color: var(--dh-muted); margin-top: 4px; }
.dh-operator-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 6px; }
.dh-operator-list a { display: flex; align-items: center; gap: 10px; color: var(--dh-ink); text-decoration: none; font-weight: 600; font-size: .9rem; padding: 6px 8px; border-radius: var(--dh-radius); }
.dh-operator-list a:hover { background: var(--dh-foam); color: var(--dh-deep); }
.dh-operator-list img { width: 36px; height: 36px; object-fit: contain; border-radius: 8px; background: #fff; border: 1px solid var(--dh-line); }

/* Search results (restored 2026-09-11): plain link rows per category, plus
   a snippet variant for description/history matches. */
.dh-search-list { list-style: none; padding: 0; margin: 0; }
.dh-search-list li { border-bottom: 1px solid #eef1f3; }
.dh-search-list li:last-child { border-bottom: 0; }
.dh-search-list a { display: flex; align-items: center; gap: 10px; padding: 10px 4px; color: var(--dh-ink); text-decoration: none; }
.dh-search-list a:hover { background: var(--dh-foam); color: var(--dh-deep); }
.dh-search-type { flex: 0 0 auto; font-size: .7rem; font-weight: 800; text-transform: uppercase; letter-spacing: .03em; color: var(--dh-sea); background: var(--dh-foam); border-radius: var(--dh-radius-pill); padding: 3px 9px; }
.dh-search-name { font-weight: 700; }
.dh-search-loc { margin-left: auto; font-size: .8rem; color: var(--dh-muted); }
.dh-search-list-snippet a { flex-direction: column; align-items: flex-start; gap: 3px; }
.dh-search-snippet { font-size: .85rem; color: var(--dh-muted); line-height: 1.4; }
.dh-search-snippet mark { background: var(--dh-avg-bg); color: var(--dh-ink); font-weight: 700; padding: 0 2px; border-radius: 3px; }

@media (max-width: 767.98px) {
  .dh-site-hero { grid-template-columns: 1fr; height: auto; }
  .dh-site-hero-main { height: 220px; }
  .dh-site-hero-side { grid-template-rows: none; grid-template-columns: 1fr 1fr; height: 90px; }
  .dh-site-facts { padding: var(--dh-space-3) var(--dh-space-4); }
  .dh-site-facts-side { align-items: flex-start; width: 100%; }
  .dh-site-rating { align-items: flex-start; }
  .dh-site-details { grid-template-columns: 1fr; }
}

/* Trip details. */
.dh-trip-kicker { font-size: .8rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--dh-sea); margin: 0 0 2px; }
.dh-trip-head .dh-site-sub a { color: var(--dh-deep); }
.dh-trip-head .dh-avail { font-size: .85rem; }
.dh-note { font-size: .85rem; color: var(--dh-avg); background: var(--dh-avg-bg); border-radius: var(--dh-radius); padding: 8px 12px; margin: 0 0 var(--dh-space-3); }
.dh-boat-list { display: flex; flex-direction: column; gap: var(--dh-space-3); }
.dh-boat { display: grid; grid-template-columns: 180px 1fr; gap: var(--dh-space-3); align-items: start; }
.dh-boat-img { display: block; aspect-ratio: 4 / 3; border-radius: var(--dh-radius); background-size: cover; background-position: center; background-color: var(--dh-foam); }
.dh-boat-name { font-size: 1rem; font-weight: 800; margin: 0 0 6px; color: var(--dh-ink); }
.dh-facts-list-tight { gap: var(--dh-space-2); grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }
.dh-facts-list-stack { grid-template-columns: 1fr; }
.dh-facts-list dd a { color: var(--dh-sea); text-decoration: none; }
.dh-operator-card { display: flex; align-items: center; gap: var(--dh-space-3); margin-bottom: var(--dh-space-3); }
.dh-operator-logo { width: 56px; height: 56px; object-fit: contain; border-radius: 10px; border: 1px solid var(--dh-line); background: #fff; }
.dh-operator-name { font-weight: 800; color: var(--dh-ink); text-decoration: none; font-size: 1.05rem; }
.dh-operator-name:hover { color: var(--dh-sea); }

/* Online waivers grid. */
.dh-waiver-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--dh-space-3); }
.dh-waiver-card { display: flex; flex-direction: column; align-items: center; gap: 8px; padding: var(--dh-space-3); border: 1px solid var(--dh-line); border-radius: var(--dh-radius); text-decoration: none; text-align: center; }
.dh-waiver-card:hover { border-color: var(--dh-sea); background: var(--dh-foam); }
.dh-waiver-logo { width: 64px; height: 64px; object-fit: contain; border-radius: 10px; background: #fff; }
.dh-waiver-name { font-size: .85rem; font-weight: 700; color: var(--dh-ink); }

/* Legal pages: Terms of Use, Privacy Policy, Data Deletion. */
.dh-legal h1 { font-size: 1.4rem; font-weight: 800; color: var(--dh-ink); margin: 0 0 var(--dh-space-2); }
.dh-legal h2 { font-size: 1.05rem; font-weight: 700; color: var(--dh-ink); margin: var(--dh-space-4) 0 var(--dh-space-2); }
.dh-legal p, .dh-legal ul { font-size: .9rem; color: var(--dh-ink); line-height: 1.6; margin: 0 0 var(--dh-space-2); }
.dh-legal a { color: var(--dh-sea); }

/* "Me" drawer header: avatar next to the diver's name, when they have one. */
.dh-drawer-user { display: flex; align-items: center; gap: 10px; min-width: 0; }
.dh-drawer-avatar { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; border: 2px solid var(--dh-sea); flex: 0 0 auto; }
.dh-drawer-avatar-initials { display: inline-flex; align-items: center; justify-content: center; background: var(--dh-sea); color: #fff; font-weight: 700; font-size: .8rem; }
.dh-panel-subtitle { font-size: .7rem; letter-spacing: .06em; text-transform: uppercase; color: var(--dh-muted); font-weight: 700; margin: var(--dh-space-3) 0 6px; }
.dh-fills { display: flex; flex-wrap: wrap; gap: 6px; }
.dh-fills .chip { display: inline-flex; align-items: center; gap: 2px; }
.dh-fills .material-icons-round { font-size: 14px; }
.chip-yes { color: var(--dh-good); border-color: var(--dh-good); background: var(--dh-good-bg); }
.chip-no { color: var(--dh-muted); opacity: .7; }
.chip-poor { color: var(--dh-poor); border-color: var(--dh-poor); background: var(--dh-poor-bg); }
@media (max-width: 575.98px) { .dh-boat { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------------ */
/* Template palette remap.                                             */
/* Material Dashboard paints card headers, switches and buttons with   */
/* its own "info" blue (#1A73E8) on about forty pages we did not       */
/* redesign. Instead of editing each page, the shell repaints those    */
/* classes with the Divers Hub palette so old and new sections match.  */
/* Scoped to body.dh-shell so the admin and template demo pages are    */
/* untouched. Remove a rule here if a page needs the stock colour.      */
/* ------------------------------------------------------------------ */
.dh-shell .bg-gradient-info,
.dh-shell .bg-gradient-primary { background-image: linear-gradient(195deg, var(--dh-deep) 0%, var(--dh-ink) 100%) !important; }
.dh-shell .shadow-info,
.dh-shell .shadow-primary { box-shadow: 0 4px 16px 0 rgba(11, 42, 58, 0.22) !important; }
.dh-shell .bg-info,
.dh-shell .bg-primary,
.dh-shell .btn-info,
.dh-shell .btn-primary { background-color: var(--dh-deep) !important; border-color: var(--dh-deep) !important; }
.dh-shell .text-info,
.dh-shell .text-primary { color: var(--dh-sea) !important; }
.dh-shell .form-check-input:checked,
.dh-shell .form-switch .form-check-input:checked { border-color: var(--dh-sea) !important; background-color: var(--dh-sea) !important; }
.dh-shell .form-switch .form-check-input:checked:after { border-color: var(--dh-sea) !important; }
.dh-shell .btn.bg-gradient-info,
.dh-shell .btn.bg-gradient-primary,
.dh-shell .btn.bg-gradient-info:hover,
.dh-shell .btn.bg-gradient-primary:hover { box-shadow: 0 3px 8px 0 rgba(11, 42, 58, 0.25) !important; }

/* ------------------------------------------------------------------ */
/* Operators explorer and operator detail.                             */
/* ------------------------------------------------------------------ */
.dh-op-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: var(--dh-space-3); }
.dh-op-card { display: grid; grid-template-columns: 112px 1fr; grid-template-rows: auto auto; gap: var(--dh-space-2) var(--dh-space-3); background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; padding: var(--dh-space-3); }
.dh-op-card-private { border-style: dashed; }
/* Fixed 2:1 white box so logos of every shape line up. */
.dh-op-logo { grid-row: 1 / span 2; display: flex; align-items: center; justify-content: center; width: 112px; height: 56px; padding: 4px; background: #fff; border: 1px solid var(--dh-line); border-radius: 10px; color: var(--dh-muted); }
/* Definite box so the image has a size before it loads (lazy loading needs one). */
.dh-op-logo img { width: 100%; height: 100%; object-fit: contain; }
.dh-op-body { min-width: 0; }
.dh-op-name { display: block; font-weight: 800; color: var(--dh-ink); text-decoration: none; font-size: 1rem; line-height: 1.2; }
.dh-op-name:hover { color: var(--dh-sea); }
.dh-op-loc { font-size: .8rem; color: var(--dh-muted); margin: 2px 0 6px; }
.dh-op-facts { display: flex; flex-wrap: wrap; gap: 4px; }
.chip-tec { color: var(--dh-deep); border-color: var(--dh-deep); background: var(--dh-foam); }
.dh-op-actions { grid-column: 2; display: flex; gap: var(--dh-space-2); }
.dh-op-actions .dh-btn { padding: 6px 10px; font-size: .8rem; }
.dh-op-actions .material-icons-round { font-size: 16px; }
@media (max-width: 575.98px) {
  .dh-op-grid { grid-template-columns: 1fr; }
  .dh-op-card { grid-template-columns: 88px 1fr; }
  .dh-op-logo { width: 88px; height: 44px; }
  .dh-op-action-text { display: none; }
}

/* Operator detail. */
.dh-op-head { display: flex; gap: var(--dh-space-4); align-items: center; }
.dh-op-head .dh-op-logo { grid-row: auto; width: 160px; height: 80px; flex: 0 0 auto; }
.dh-hours { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; text-align: center; }
.dh-hours div { background: var(--dh-foam); border-radius: 8px; padding: 6px 2px; }
.dh-hours dt { font-size: .65rem; letter-spacing: .05em; text-transform: uppercase; color: var(--dh-muted); font-weight: 700; }
.dh-hours dd { margin: 0; font-size: .8rem; font-weight: 700; color: var(--dh-ink); }
.dh-price-list { margin: 0; }
.dh-price-list div { display: flex; justify-content: space-between; gap: var(--dh-space-3); padding: 8px 0; border-bottom: 1px solid var(--dh-line); }
.dh-price-list div:last-child { border-bottom: 0; }
.dh-price-list dt { font-weight: 600; color: var(--dh-ink); }
.dh-price-list dd { margin: 0; font-weight: 800; color: var(--dh-deep); white-space: nowrap; }
.dh-op-desc { white-space: pre-line; color: var(--dh-ink); margin: 0; line-height: 1.55; }
@media (max-width: 575.98px) {
  .dh-op-head { flex-direction: column; align-items: flex-start; }
  .dh-hours { grid-template-columns: repeat(4, 1fr); }
}
.dh-btn.is-on { background: var(--dh-good-bg); border-color: var(--dh-good); color: var(--dh-good); }

/* Guest empty state on personal pages (show, then gate). */
.dh-guest-note { display: flex; gap: var(--dh-space-4); align-items: flex-start; }
.dh-guest-note > .material-icons-round { font-size: 40px; color: var(--dh-sea); }
.dh-guest-note .dh-btn { margin-right: 6px; }

/* Dashboard: favorite operator picker. The select shrinks to the card, the logo never overflows. */
.dh-fav-operator { max-width: 100%; }
.dh-fav-operator #filterOperators { max-width: 100%; white-space: normal; text-overflow: ellipsis; overflow: hidden; }
.dh-fav-operator #operatorLogo { max-width: 120px; height: 45px; object-fit: contain; }
.dh-shell .card-body table { max-width: 100%; }

/* Drawer links that use one of the original white line icons instead of a Material glyph. */
.dh-menu-icon-img { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; border-radius: 50%; background: var(--dh-deep); flex: 0 0 auto; }
.dh-menu-icon-img img { width: 17px; height: 17px; object-fit: contain; }

/* ------------------------------------------------------------------ */
/* Add to home screen bar. Sits above the bottom tab bar on phones.     */
/* ------------------------------------------------------------------ */
.dh-install { position: fixed; left: 8px; right: 8px; bottom: calc(64px + env(safe-area-inset-bottom, 0px)); z-index: 1040; display: flex; align-items: center; gap: 10px; padding: 10px 12px; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; box-shadow: 0 6px 24px rgba(11,42,58,.22); animation: dhInstallSlideUp .35s ease-out; }
.dh-install[hidden] { display: none; }
/* Removing the [hidden] attribute is what makes this element start
   rendering at all, so the animation above replays from the start every
   time JS shows it - not just the first time on a page. */
@keyframes dhInstallSlideUp { from { transform: translateY(120%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .dh-install { animation: none; } }
.dh-install img { width: 40px; height: 40px; border-radius: 9px; flex: 0 0 auto; }
.dh-install-text { flex: 1 1 auto; min-width: 0; font-size: .82rem; line-height: 1.3; color: var(--dh-muted); }
.dh-install-text strong { display: block; color: var(--dh-ink); font-size: .9rem; }
.dh-install-text .material-icons-round { font-size: 16px; vertical-align: -3px; color: var(--dh-sea); }
.dh-install .dh-btn { padding: 8px 14px; flex: 0 0 auto; }
.dh-install-close { border: 0; background: transparent; color: var(--dh-muted); padding: 4px; margin: -4px -4px -4px 0; flex: 0 0 auto; }
.dh-install-close .material-icons-round { font-size: 20px; }
/* The automatic popup is phone/tablet only by design; a manual "Install as
   App" tap from the drawer (any device) still needs to fall back to this
   bar on desktop when the browser hasn't handed us a deferred prompt to
   call directly yet - see the "manual" flag in divershub.js's show(). */
@media (min-width: 768px) { .dh-install:not(.is-manual) { display: none !important; } }
@media (min-width: 768px) { .dh-install.is-manual { left: auto; width: min(380px, calc(100vw - 32px)); bottom: 24px; right: 24px; } }

/* ------------------------------------------------------------------ */
/* Home: coast tiles centred, so an odd count does not leave an orphan */
/* hanging on the left.                                               */
/* ------------------------------------------------------------------ */
.dh-strip-row { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--dh-space-3); }
.dh-strip-row .dh-coast { flex: 1 1 200px; max-width: 260px; }
/* Phones: two per row, and an odd last tile stays half width and centred rather than stretching. */
@media (max-width: 575.98px) { .dh-strip-row .dh-coast { flex: 0 1 calc(50% - var(--dh-space-3) / 2); max-width: none; } }

/* ------------------------------------------------------------------ */
/* Trip finder: date presets, custom range, day strip, day sections.   */
/* ------------------------------------------------------------------ */
.dh-range-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 var(--dh-space-2); }
.dh-range-custom { display: inline-block; }
.dh-range-custom summary { list-style: none; cursor: pointer; }
.dh-range-custom summary::-webkit-details-marker { display: none; }
.dh-range-form { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 8px; }
.dh-range-form input[type="date"] { border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: 6px 8px; font: inherit; color: var(--dh-ink); background: var(--dh-paper); }
.dh-range-title { font-size: 1.35rem; font-weight: 800; color: var(--dh-ink); margin: var(--dh-space-3) 0 4px; }
.dh-daystrip { display: flex; gap: 6px; overflow-x: auto; padding: 4px 0 8px; scrollbar-width: none; }
.dh-daystrip::-webkit-scrollbar { display: none; }
.dh-daystrip a { flex: 0 0 auto; width: 52px; text-align: center; text-decoration: none; color: var(--dh-ink); border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: 6px 2px; background: var(--dh-paper); }
.dh-daystrip a .dh-ds-dow { display: block; font-size: .65rem; letter-spacing: .05em; text-transform: uppercase; color: var(--dh-muted); }
.dh-daystrip a .dh-ds-day { display: block; font-weight: 800; font-size: 1rem; line-height: 1.2; }
.dh-daystrip a .dh-ds-n { display: block; font-size: .7rem; color: var(--dh-sea); font-weight: 700; }
.dh-daystrip a.is-empty { opacity: .45; }
.dh-daystrip a.is-empty .dh-ds-n { color: var(--dh-muted); font-weight: 400; }
.dh-daystrip a.is-weekend { background: var(--dh-foam); }
.dh-day { margin-top: var(--dh-space-4); }
.dh-day-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; font-size: 1.1rem; font-weight: 800; color: var(--dh-ink); margin: 0 0 var(--dh-space-2); }
.dh-day-title .dh-region-count { font-weight: 600; color: var(--dh-muted); font-size: .85rem; }
.dh-day-title .dh-why { margin-left: auto; }
.dh-more-link { display: inline-block; margin: 4px 0 0; font-size: .85rem; font-weight: 700; color: var(--dh-sea); text-decoration: none; }

/* Themed calendars (Recreational/Technical/Wreck/Shark/Lobster): a real month grid above the day-by-day trip list. */
.dh-calendar-panel { padding: var(--dh-space-3); }
.dh-calendar-panel .fc { font-family: var(--dh-font); }
.dh-calendar-panel .fc-daygrid-day-number, .dh-calendar-panel .fc-col-header-cell-cushion { color: var(--dh-ink); }
.dh-calendar-panel .fc-day-today { background: var(--dh-foam) !important; }
.dh-calendar-panel .fc-event { border: 0; font-size: .72rem; padding: 1px 4px; cursor: pointer; }
/* Pills are colored per operator (inline, set in the events array); departed trips just dim, availability stays a trip-card detail below. */
.fc .dh-tripfc-departed { opacity: .45; }
.dh-calendar-panel .fc-daygrid-more-link { color: var(--dh-sea); font-weight: 700; }
.dh-calendar-panel .fc-popover { border-radius: var(--dh-radius); border-color: var(--dh-line); overflow: hidden; }
.dh-calendar-panel .fc-popover-header { background: var(--dh-sand); }

/* FullCalendar's own toolbar buttons (Today / < / >) default to a plain
   navy (#2C3E50) that has nothing to do with the theme - can't restyle them
   into pills, they're fixed markup from fullcalendar.js, but FullCalendar
   itself exposes these exact custom properties for theming its buttons, so
   setting them once on :root covers every calendar sitewide (My Calendar,
   group calendars, the hydrotherapy calendar, operator schedules) with no
   per-page CSS needed (Pablo, 2026-09-17: "in all the calendars...make
   those buttons using theme colors"). Same navy/blue pair as .dh-btn-primary
   uses everywhere else (dh-ink normal, dh-deep hover/active). */
:root {
  --fc-button-bg-color: var(--dh-ink);
  --fc-button-border-color: var(--dh-ink);
  --fc-button-text-color: #fff;
  --fc-button-hover-bg-color: var(--dh-deep);
  --fc-button-hover-border-color: var(--dh-deep);
  --fc-button-active-bg-color: var(--dh-deep);
  --fc-button-active-border-color: var(--dh-deep);
}

.dh-cal-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; padding: 12px 4px 2px; border-top: 1px solid var(--dh-line); margin-top: 12px; }
.dh-cal-legend-label { font-size: .8rem; font-weight: 700; color: var(--dh-muted); }
.dh-cal-legend-item { display: inline-flex; align-items: center; gap: 6px; font-size: .8rem; color: var(--dh-ink); }
.dh-cal-legend-swatch { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; }

/* Shark/Lobster "About" card: a collapsible intro carried over from the old
   front end. .dh-dash-collapse's own 8px left/right margin stacked on top
   of .dh-board's padding, making this card the only thing on the page
   narrower than the date bar/grid/trip list below it (Pablo, 2026-09-18:
   "they are not respecting the paddings to the right and left"). */
.dh-about-card { margin-bottom: var(--dh-space-3); margin-left: 0; margin-right: 0; }
.dh-about-body { display: flex; flex-wrap: wrap; gap: var(--dh-space-3); padding: var(--dh-space-3) 4px 4px; }
.dh-about-img { width: 220px; max-width: 100%; height: auto; border-radius: var(--dh-radius); object-fit: cover; flex: 0 0 auto; }
.dh-about-text { flex: 1 1 260px; min-width: 0; font-size: .88rem; color: var(--dh-ink); line-height: 1.5; }
.dh-about-text p { margin: 0 0 10px; }
.dh-about-text p:last-child { margin-bottom: 0; }

/* Trip finder: operator picker (a details element, works without JavaScript). */
.dh-ops { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.dh-ops summary { list-style: none; cursor: pointer; }
.dh-ops summary::-webkit-details-marker { display: none; }
.dh-ops-panel { margin-top: 8px; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; padding: 12px; max-width: 720px; }
.dh-ops-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 4px 12px; max-height: 260px; overflow-y: auto; margin: 8px 0; }
.dh-ops-list label { display: flex; align-items: center; gap: 8px; font-size: .9rem; color: var(--dh-ink); padding: 4px 2px; cursor: pointer; }
.dh-ops-list label span.n { color: var(--dh-muted); font-size: .8rem; margin-left: auto; }
.dh-ops-list input { width: 18px; height: 18px; accent-color: var(--dh-deep); flex: 0 0 auto; }
.dh-ops-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.dh-ops-selected { display: inline-flex; flex-wrap: wrap; gap: 4px; }

/* ------------------------------------------------------------------ */
/* Welcome wizard.                                                     */
/* ------------------------------------------------------------------ */
.dh-wizard { max-width: 720px; margin: var(--dh-space-4) auto; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 16px; padding: var(--dh-space-6); }
.dh-wizard-dots { list-style: none; display: flex; gap: 8px; padding: 0; margin: 0 0 var(--dh-space-4); }
.dh-wizard-dots li { width: 28px; height: 6px; border-radius: 3px; background: var(--dh-line); }
.dh-wizard-dots li.is-done { background: var(--dh-sea); }
.dh-wizard-dots li.is-current { background: var(--dh-ink); }
.dh-wizard-title { font-size: clamp(1.4rem, 3vw, 1.9rem); font-weight: 800; color: var(--dh-ink); margin: 0 0 6px; letter-spacing: -.01em; }
.dh-wizard-lead { color: var(--dh-muted); margin: 0 0 var(--dh-space-4); max-width: 56ch; }
.dh-wizard-form { display: flex; flex-direction: column; gap: var(--dh-space-4); }
.dh-wizard-field { display: flex; flex-direction: column; gap: 6px; border: 0; padding: 0; margin: 0; }
.dh-wizard-field > span, .dh-wizard-field legend { font-weight: 700; color: var(--dh-ink); font-size: .95rem; }
.dh-wizard-field small { color: var(--dh-muted); font-weight: 400; }
/* type=tel was already used (the old comms step's phone field) but never
   actually had a rule here - picked up now that the new phone-verification
   step (Pablo, 2026-09-16) also uses it, alongside type=text for the
   6-digit code field. */
.dh-wizard-field input[type="text"], .dh-wizard-field input[type="tel"] { border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: 10px 12px; font: inherit; font-size: 1rem; }
.dh-phone-us { display: flex; align-items: stretch; border: 1px solid var(--dh-line); border-radius: var(--dh-radius); overflow: hidden; }
.dh-phone-us-prefix { display: flex; align-items: center; padding: 10px 10px 10px 12px; background: var(--dh-foam); color: var(--dh-deep); font-weight: 700; border-right: 1px solid var(--dh-line); }
.dh-phone-us input[type="tel"] { border: 0 !important; border-radius: 0 !important; flex: 1; min-width: 0; }
.dh-wizard-photo-row { display: flex; align-items: center; gap: 12px; }
.dh-wizard-photo-row img { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; }
.dh-wizard-photo-row .material-icons-round { font-size: 56px; color: var(--dh-line); }
.dh-wizard-group { font-size: .75rem; letter-spacing: .06em; text-transform: uppercase; color: var(--dh-muted); font-weight: 700; margin: var(--dh-space-2) 0 0; }
.dh-wizard-choices { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; }
/* The "Follow Divers Hub" step is the one place these choice cards sit
   outside the form (Pablo, 2026-09-23) - everywhere else they're a form
   child and already get spacing from .dh-wizard-form's flex gap. */
.dh-wizard-choices + .dh-wizard-form { margin-top: var(--dh-space-4); }
.dh-wizard-choices-compact { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 8px; }
.dh-choice { position: relative; display: block; cursor: pointer; }
.dh-choice input { position: absolute; opacity: 0; pointer-events: none; }
.dh-choice-body { display: flex; flex-direction: column; gap: 2px; border: 2px solid var(--dh-line); border-radius: 12px; padding: 12px; min-height: 100%; background: var(--dh-paper); transition: border-color .12s, background-color .12s; }
.dh-choice-body img { width: 40px; height: 40px; object-fit: contain; border-radius: 8px; background: #fff; }
.dh-choice-title { font-weight: 700; color: var(--dh-ink); }
.dh-choice-sub { font-size: .78rem; color: var(--dh-muted); }
.dh-choice input:checked + .dh-choice-body { border-color: var(--dh-deep); background: var(--dh-foam); }
.dh-choice input:focus-visible + .dh-choice-body { outline: 3px solid var(--dh-shallow); outline-offset: 2px; }
.dh-wizard-choices-compact .dh-choice-body { padding: 10px 12px; }
/* Photo-source choice on the welcome step's Google-avatar offer - a
   thumbnail/icon beside the label instead of stacked (Pablo, 2026-09-16). */
.dh-choice-body-row { flex-direction: row; align-items: center; gap: 10px; }
/* Follow-us wizard step: .dh-choice has no :hover of its own (only the
   radio/checkbox :checked state does), so a plain link needs one added -
   same border-color cue the checked state uses elsewhere. */
.dh-wizard-social-link:hover .dh-choice-body, .dh-wizard-social-link:focus-visible .dh-choice-body { border-color: var(--dh-sea); }
.dh-social-icon { width: 40px; height: 40px; border-radius: 50%; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; color: #fff; font-size: 1.15rem; }
.dh-social-icon-ig { background: radial-gradient(circle at 30% 110%, #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285AEB 90%); }
.dh-social-icon-fb { background: #1877f2; }
.dh-radio { display: flex; align-items: center; gap: 8px; font-size: .95rem; color: var(--dh-ink); }
.dh-radio input { width: 18px; height: 18px; accent-color: var(--dh-deep); }
.dh-wizard-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.dh-wizard-actions-stack .dh-btn { display: inline-flex; align-items: center; gap: 6px; }
.dh-wizard-skip { margin-top: var(--dh-space-4); text-align: center; }
.dh-link-btn { border: 0; background: transparent; color: var(--dh-muted); text-decoration: underline; font-size: .85rem; cursor: pointer; }
@media (max-width: 575.98px) { .dh-wizard { padding: var(--dh-space-4); margin: var(--dh-space-3) 0; } }

/* Post-wizard "quick tour" - a self-contained slide carousel offered from
   the wizard's done step (Pablo, 2026-09-16: "we can offer a brief tour
   showing the app"). Reuses .dh-wizard-dots/.dh-wizard-title/.dh-wizard-lead
   for visual consistency with the wizard itself. */
.dh-tour-backdrop {
  position: fixed; inset: 0; z-index: 10060; background: rgba(11, 42, 58, .55);
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.dh-tour {
  position: relative; width: 100%; max-width: 440px; max-height: 85vh; overflow-y: auto;
  background: var(--dh-paper); border-radius: 16px; padding: var(--dh-space-6);
  box-shadow: 0 20px 60px rgba(0, 0, 0, .3); text-align: center;
}
.dh-tour-close {
  position: absolute; top: 12px; right: 12px; border: 0; background: transparent;
  color: var(--dh-muted); cursor: pointer; display: flex; padding: 4px;
}
.dh-tour-close:hover { color: var(--dh-ink); }
.dh-tour-dots { justify-content: center; margin: 0 0 var(--dh-space-4); }
.dh-tour-icon { font-size: 56px; color: var(--dh-sea); margin-bottom: 8px; }
.dh-tour .dh-wizard-title, .dh-tour .dh-wizard-lead { text-align: center; max-width: none; }
.dh-tour .dh-wizard-actions { justify-content: center; margin-top: var(--dh-space-4); }

/* ------------------------------------------------------------------ */
/* Communication preferences (the consent screen). Shared by the        */
/* profile page and the welcome wizard.                                */
/* ------------------------------------------------------------------ */
.dh-comms { display: flex; flex-direction: column; gap: var(--dh-space-3); }
.dh-comms-row { border: 1px solid var(--dh-line); border-radius: 12px; padding: 12px 14px; background: var(--dh-paper); }
.dh-comms-label { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; margin: 0; }
.dh-comms-label input { width: 20px; height: 20px; margin: 1px 0 0; accent-color: var(--dh-deep); flex: 0 0 auto; }
.dh-comms-label span { font-size: .92rem; color: var(--dh-ink); line-height: 1.4; }
.dh-comms-label strong { display: block; font-weight: 800; }
.dh-comms-note { font-size: .78rem; color: var(--dh-muted); margin: 6px 0 0 30px; line-height: 1.45; }
.dh-comms-warn { display: flex; align-items: flex-start; gap: 6px; margin-left: 0; color: var(--dh-avg); background: var(--dh-avg-bg); border-radius: var(--dh-radius); padding: 8px 10px; }
.dh-comms-warn .material-icons-round { font-size: 16px; }
.dh-comms-legal { font-size: .78rem; color: var(--dh-muted); margin: 0; }

/* Themed file picker (Pablo, 2026-09-24: "the choose file button needs to
   be themed to the site") - a styled label over a hidden native input. */
.dh-file-picker { display: flex; align-items: center; gap: 8px; border: 1.5px dashed var(--dh-line); border-radius: var(--dh-radius); padding: 12px 14px; cursor: pointer; color: var(--dh-deep); font-weight: 600; font-size: .9rem; background: var(--dh-foam); transition: border-color .12s ease, background-color .12s ease; }
.dh-file-picker:hover { border-color: var(--dh-sea); background: #fff; }
.dh-file-picker .material-icons-round { color: var(--dh-sea); }

/* Upload spinner - feedback while a form POST is in flight, not a real
   byte-progress bar (Pablo, 2026-09-24: "a spinner or progress bar while
   the picture is uploading"). */
.dh-upload-progress { display: flex; align-items: center; gap: 8px; font-size: .85rem; color: var(--dh-muted); margin: 10px 0 0; }
.dh-spinner { width: 16px; height: 16px; border: 2px solid var(--dh-line); border-top-color: var(--dh-sea); border-radius: 50%; animation: dh-spin .7s linear infinite; flex: 0 0 auto; }
@keyframes dh-spin { to { transform: rotate(360deg); } }
.dh-comms-since { color: var(--dh-good); font-weight: 700; margin-top: 2px; }
/* Material Dashboard's base checkbox styling (`.form-check-input { appearance:
   none }`) draws its own checked state with a hardcoded pink/magenta
   gradient (#e91e63/#EC407A) instead of a native control, which is why
   setting accent-color on it does nothing - appearance:none opts a checkbox
   out of native rendering entirely, and accent-color only ever affects that
   native rendering. !important is used deliberately here since Material
   Dashboard's own checked-state rule is itself high-specificity and loaded
   first (Pablo, 2026-09-16: "the color of the picker in the notifications is
   a pink that has nothing to do with the theme...use the blue"). */
.dh-comms .form-check-input:checked {
  background-color: var(--dh-deep) !important;
  background-image: none !important;
  border-color: var(--dh-deep) !important;
}
/* Round 1 of this only set border-color, which did nothing: Material
   Dashboard's real base rule is `.form-check-input { border: none }` (a
   single class, the actual baseline here) - the OTHER rule that looks like
   it draws a visible #d1d7e1 border, `.form-check:not(.form-switch)
   .form-check-input[type=checkbox]`, never applies to this component at
   all, since its markup doesn't wrap the input in a .form-check div the
   way Bootstrap expects. So there was never a border to recolor - width
   and style both computed to 0/none regardless of what color was set,
   confirmed via the live site's own computed styles (border-width: 0px,
   border-style: none) after the color-only fix visibly did nothing
   (Pablo, 2026-09-17: "shows exactly the same as before"). Setting the
   full shorthand here actually draws one. */
.dh-comms .form-check-input {
  border: 1px solid var(--dh-muted) !important;
}
.dh-comms .form-check-input:disabled {
  border-color: var(--dh-line) !important;
  opacity: .6;
}

/* Same themed checkbox as .dh-comms above (dark checked state instead of
   Material Dashboard's default pink, visible border), reusable anywhere
   a plain on/off checkbox is wanted instead of the pill-shaped
   .form-switch toggle (Pablo, 2026-09-22, group settings modal: "Use the
   same checkbox you used in the image attached and eliminate the
   toggles"). Add .dh-check to the input and drop .form-switch from its
   wrapping .form-check div. */
.dh-check.form-check-input {
  border: 1px solid var(--dh-muted) !important;
}
.dh-check.form-check-input:checked {
  background-color: var(--dh-deep) !important;
  background-image: none !important;
  border-color: var(--dh-deep) !important;
}
.dh-check.form-check-input:disabled {
  border-color: var(--dh-line) !important;
  opacity: .6;
}

/* Guest prompt: create an account or sign in, side by side and stacking on phones. */
.dh-guest-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: var(--dh-space-3); }

/* ------------------------------------------------------------------ */
/* Generic card: same flat paper/border/heading Weather already uses     */
/* (.dh-wx-card/.dh-wx-ch), named without the "wx" so any page's cards   */
/* can share it instead of each page inventing its own header style.    */
/* ------------------------------------------------------------------ */
.dh-card { background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 16px; margin-top: 12px; }
.dh-card-head { font-size: .95rem; font-weight: 800; padding: 13px 15px; margin: 0; border-bottom: 1px solid var(--dh-line); display: flex; align-items: center; justify-content: space-between; gap: 8px; color: var(--dh-ink); }
.dh-card-body { padding: 15px; }

/* ------------------------------------------------------------------ */
/* Dashboard: the collapsed month calendar at the foot of the page.     */
/* ------------------------------------------------------------------ */
.dh-dash-cards { margin-top: 2rem; }
.dh-dash-collapse { margin: var(--dh-space-3) 8px var(--dh-space-6); }
.dh-dash-collapse > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 10px; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; padding: 14px 16px; font-weight: 700; color: var(--dh-ink); }
.dh-dash-collapse > summary::-webkit-details-marker { display: none; }
.dh-dash-collapse > summary:hover { border-color: var(--dh-sea); color: var(--dh-deep); }
.dh-dash-collapse > summary .material-icons-round { color: var(--dh-sea); }
.dh-dash-collapse-hint { margin-left: auto; font-weight: 400; font-size: .8rem; color: var(--dh-muted); }
.dh-dash-headlink { font-size: .78rem; font-weight: 700; color: var(--dh-sea); text-decoration: none; }
.dh-dash-headlink:hover { text-decoration: underline; }

/* ------------------------------------------------------------------ */
/* Tab bar: unread badge on Groups.                                     */
/* ------------------------------------------------------------------ */
.dh-tab-icon { position: relative; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 24px; }
.dh-tab-badge { position: absolute; top: -6px; right: -8px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--dh-radius-pill); background: var(--dh-poor); color: #fff; font-size: .65rem; font-weight: 700; line-height: 18px; text-align: center; }
.dh-topnav-link .dh-tab-badge { position: static; display: inline-block; margin-left: 6px; vertical-align: 2px; }
/* Inlined calendar SVGs (shell/menu.blade.php's "svg:<file>" convention),
   sized to match the 24px Material icons next to them. */
.dh-tab-icon-svg { display: inline-flex; width: 24px; height: 24px; }
.dh-tab-icon-svg svg { width: 100%; height: 100%; }

/* Dashboard: fixed, center tab (Pablo, 2026-09-24: "make the dashboard
   icon larger and maybe over a circle shape matching the same color of
   the bar" - filled with the bar's own active-state accent, --dh-sea, so
   it reads as "the same color already used in this bar", raised slightly
   like a standard mobile center action button. */
.dh-tab-dashboard { margin-top: -14px; }
.dh-tab-icon-big { width: 48px; height: 48px; border-radius: 50%; background: var(--dh-sea); color: #fff; box-shadow: 0 3px 10px rgba(0,0,0,.25); }
.dh-tab-icon-big .material-icons-round { font-size: 26px; }
.dh-tab-dashboard.is-active .dh-tab-icon-big { background: var(--dh-deep); }
.dh-tab-dashboard span:last-child { margin-top: 3px; }

/* ------------------------------------------------------------------ */
/* Me rows: on every page now (page-template.blade.php), not just the   */
/* dashboard, so they sit after </main> rather than inside the          */
/* .main-content that already clears the fixed tab bar - they need      */
/* their own clearance or the fixed bar covers the last row.            */
/* ------------------------------------------------------------------ */
.dh-me-rows {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px;
  /* Same 1100px cap as .dh-board/.dh-home (the card grids above this on most
     pages) - without it these buttons keep stretching past where the cards
     stop, since there's nothing else here to grow into extra columns. */
  max-width: 1100px; margin: var(--dh-space-2) auto var(--dh-space-6); box-sizing: border-box;
  padding: 0 var(--dh-content-x) calc(var(--dh-tabbar-h) + env(safe-area-inset-bottom) + 12px);
}
.dh-me-row { display: flex; align-items: center; gap: 10px; padding: 12px 14px; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 14px; color: var(--dh-ink); font-weight: 600; font-size: .9rem; text-decoration: none; }
.dh-me-row:hover { border-color: var(--dh-sea); color: var(--dh-deep); }
.dh-me-row .material-icons-round { font-size: 22px; color: var(--dh-sea); }
@media (min-width: 768px) { .dh-me-rows { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 992px) { .dh-me-rows { padding-bottom: 0; } }

/* ------------------------------------------------------------------ */
/* Dashboard: upcoming dives list, groups card, my calendar card.       */
/* ------------------------------------------------------------------ */
.dh-dive-list, .dh-group-list { list-style: none; margin: 0; padding: 0; }
.dh-dive-row { display: flex; flex-direction: column; gap: 8px; padding: 12px 0; border-bottom: 1px solid var(--dh-line); }
.dh-dive-row:last-child { border-bottom: 0; }
.dh-dive-main, .dh-group-row { display: flex; align-items: center; gap: 12px; color: var(--dh-ink); text-decoration: none; border-radius: 12px; }
.dh-dive-main:hover .dh-dive-title, .dh-group-row:hover .dh-group-name { color: var(--dh-sea); text-decoration: underline; }
.dh-dive-type { flex: 0 0 36px; width: 36px; height: 36px; border-radius: 50%; background: var(--dh-deep); display: inline-flex; align-items: center; justify-content: center; }
.dh-dive-type img { height: 20px; }
.dh-dive-text, .dh-group-text { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.dh-dive-title, .dh-group-name { font-weight: 700; font-size: .95rem; line-height: 1.25; }
.dh-dive-when, .dh-group-meta { font-size: .8rem; color: var(--dh-muted); margin-top: 2px; }
.dh-dive-when b { color: var(--dh-ink); }
.dh-dive-op { font-size: .8rem; color: var(--dh-muted); }
.dh-dive-chevron { color: var(--dh-muted); flex: 0 0 auto; }
.dh-dive-status { align-self: flex-start; margin-left: 48px; display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: var(--dh-radius-pill); border: 1px solid; background: #fff; font-size: .8rem; font-weight: 700; cursor: pointer; line-height: 1; }
.dh-dive-status .material-icons-round { font-size: 18px; }
.dh-dive-status.is-booked { color: #0f7b3f; border-color: #a9dcbb; background: #eaf7ee; }
.dh-dive-status.is-open { color: #b0322b; border-color: #f2b9b4; background: #fdf0ee; }
.dh-dive-status.is-cancelled { color: #5a5a5a; border-color: #cfcfcf; background: #eee; }
.dh-dive-row.is-cancelled .dh-dive-title { text-decoration: line-through; color: var(--dh-muted); }
.dh-dive-status-more { font-weight: 600; opacity: .75; }
.dh-dive-status-more::before { content: "\00b7"; margin-right: 6px; }
.dh-dive-status:hover { filter: brightness(.97); }

.dh-group-invite { display: flex; align-items: center; gap: 10px; padding: 10px 14px; margin-bottom: 12px; border-radius: 12px; background: var(--dh-foam); color: var(--dh-deep); font-weight: 700; font-size: .9rem; text-decoration: none; }
.dh-group-invite .material-icons-round:last-child { margin-left: auto; }
.dh-group-list li { padding: 10px 0; border-bottom: 1px solid var(--dh-line); }
.dh-group-list li:last-child { border-bottom: 0; }
.dh-group-avatar { flex: 0 0 40px; width: 40px; height: 40px; border-radius: 50%; overflow: hidden; background: var(--dh-foam); color: var(--dh-sea); display: inline-flex; align-items: center; justify-content: center; }
.dh-group-avatar img { width: 100%; height: 100%; object-fit: cover; }

.dh-seg { display: inline-flex; padding: 3px; border-radius: var(--dh-radius-pill); background: var(--dh-foam); margin-bottom: 12px; }
.dh-seg-btn { border: 0; background: transparent; padding: 7px 14px; border-radius: var(--dh-radius-pill); font-weight: 700; font-size: .85rem; color: var(--dh-deep); cursor: pointer; }
.dh-seg-btn.is-active { background: #fff; color: var(--dh-sea); box-shadow: 0 1px 3px rgba(0,0,0,.12); }
.dh-cal-key { display: inline-block; width: 10px; height: 10px; border-radius: 3px; vertical-align: middle; margin-right: 4px; }
.dh-cal-key.is-booked { background: #0f7b3f; }
.dh-cal-key.is-open { background: #c0392b; }
.dh-subscribe { margin-top: 16px; padding: 14px; border-radius: 14px; background: var(--dh-foam); }
.dh-subscribe-text { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; font-size: .85rem; color: var(--dh-deep); }
.dh-subscribe-text strong { display: inline-flex; align-items: center; gap: 6px; font-size: .95rem; }
.dh-subscribe-text .material-icons-round { font-size: 20px; color: var(--dh-sea); }
.dh-subscribe-row { display: flex; gap: 8px; flex-wrap: wrap; }
.dh-subscribe-row input { flex: 1 1 220px; min-width: 0; font-size: .8rem; }
.dh-subscribe-row .dh-btn { white-space: nowrap; }
.dh-fav-cal { padding-top: 4px; }

/* ------------------------------------------------------------------ */
/* Options sheet for one saved dive (dashboard).                        */
/* ------------------------------------------------------------------ */
.dh-sheet { border-radius: 18px; padding: 14px 16px 10px; }
.dh-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.dh-sheet-head .dh-dive-status { margin: 0; cursor: default; }
.dh-sheet-title { font-size: .9rem; font-weight: 600; color: var(--dh-ink); line-height: 1.4; margin: 0 0 10px; }
.dh-sheet-actions { display: flex; flex-direction: column; }
.dh-sheet-action { display: flex; align-items: center; gap: 12px; padding: 11px 6px; border-top: 1px solid var(--dh-line); color: var(--dh-ink); text-decoration: none; }
.dh-sheet-action:hover { background: var(--dh-foam); border-radius: 10px; }
.dh-sheet-action .material-icons-round { color: var(--dh-sea); font-size: 22px; flex: 0 0 auto; }
.dh-sheet-action span:last-child { display: flex; flex-direction: column; }
.dh-sheet-action strong { font-size: .92rem; }
.dh-sheet-action small { font-size: .75rem; color: var(--dh-muted); }
.dh-sheet-action.is-danger, .dh-sheet-action.is-danger .material-icons-round { color: #b0322b; }

/* ------------------------------------------------------------------ */
/* Site cards: save and dived buttons over the photo, boats soon chip.  */
/* ------------------------------------------------------------------ */
.dh-site-actions { position: absolute; top: 8px; right: 8px; display: flex; gap: 6px; z-index: 2; }
.dh-site-act { width: 34px; height: 34px; border-radius: 50%; border: 0; background: rgba(255,255,255,.94); color: var(--dh-deep); display: inline-flex; align-items: center; justify-content: center; cursor: pointer; box-shadow: 0 1px 4px rgba(0,0,0,.18); padding: 0; }
.dh-site-act .material-icons-round { font-size: 20px; }
.dh-site-act:hover { background: #fff; color: var(--dh-sea); }
.dh-site-act.is-on[data-act="wish"] { color: #d6336c; }
.dh-site-act.is-on[data-act="dived"] { color: #0f7b3f; }
.dh-site-act[disabled] { opacity: .7; }
.dh-site-soon { position: absolute; bottom: 8px; right: 8px; display: inline-flex; align-items: center; gap: 4px; background: var(--dh-deep); color: #fff; }
.dh-site-soon .material-icons-round { font-size: 14px; }
.dh-inline-icon { font-size: 16px; vertical-align: -3px; color: var(--dh-sea); }

/* ------------------------------------------------------------------ */
/* Dashboard: recommended and wishlist as rows, not wide tables.        */
/* ------------------------------------------------------------------ */
.dh-trip-list { list-style: none; margin: 0; padding: 0; }
.dh-trip-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--dh-line); }
.dh-trip-row:last-child { border-bottom: 0; }
.dh-trip-date { flex: 0 0 52px; text-align: center; background: var(--dh-foam); border-radius: 12px; padding: 6px 0; line-height: 1.1; }
.dh-trip-date b { display: block; font-size: 1.05rem; color: var(--dh-deep); }
.dh-trip-date span { display: block; font-size: .7rem; text-transform: uppercase; color: var(--dh-muted); letter-spacing: .04em; }
.dh-trip-main { flex: 1 1 auto; min-width: 0; color: var(--dh-ink); text-decoration: none; display: flex; flex-direction: column; }
.dh-trip-main:hover .dh-trip-title { color: var(--dh-sea); text-decoration: underline; }
.dh-trip-title { font-weight: 700; font-size: .92rem; line-height: 1.25; }
.dh-trip-meta { font-size: .78rem; color: var(--dh-muted); margin-top: 2px; }
.dh-trip-meta b { color: var(--dh-ink); }
.dh-trip-facts { display: flex; gap: 6px; align-items: center; margin-top: 4px; font-size: .75rem; color: var(--dh-muted); }
.dh-trip-facts img { height: 18px; }
.dh-seats { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px; padding: 6px 10px; border-radius: var(--dh-radius-pill); font-size: .78rem; font-weight: 700; text-decoration: none; white-space: nowrap; }
.dh-seats.is-open { background: #eaf7ee; color: #0f7b3f; border: 1px solid #a9dcbb; }
.dh-seats.is-full { background: var(--dh-foam); color: var(--dh-muted); border: 1px solid var(--dh-line); }
.dh-seats .material-icons-round { font-size: 16px; }
.dh-wish-row { display: flex; flex-direction: column; gap: 6px; padding: 12px 0; border-bottom: 1px solid var(--dh-line); }
.dh-wish-row:last-child { border-bottom: 0; }
.dh-wish-site { display: flex; align-items: center; gap: 10px; color: var(--dh-ink); text-decoration: none; }
.dh-wish-site img { height: 28px; width: 28px; }
.dh-wish-site:hover .dh-trip-title { color: var(--dh-sea); text-decoration: underline; }
.dh-wish-next { display: flex; align-items: center; gap: 8px; margin-left: 38px; font-size: .8rem; color: var(--dh-muted); flex-wrap: wrap; }
.dh-wish-next a { color: var(--dh-sea); font-weight: 700; text-decoration: none; }
.dh-wish-next a:hover { text-decoration: underline; }
.dh-wish-next .material-icons-round { font-size: 16px; color: var(--dh-sea); }
.dh-card-foot { margin-top: 10px; text-align: right; font-size: .85rem; }
.dh-card-foot a { color: var(--dh-sea); font-weight: 700; text-decoration: none; }
.dh-linkbtn { border: 0; background: none; padding: 0; color: var(--dh-sea); font-weight: 700; font-size: .85rem; cursor: pointer; }
.dh-linkbtn:hover { text-decoration: underline; }

/* ------------------------------------------------------------------ */
/* Account pages: sign in, create account, forgot and reset password.  */
/* The last pages still on the old template (Zach, 2026-09-10).        */
/* ------------------------------------------------------------------ */
body.dh-auth-body { background: var(--dh-ink); }
.dh-auth { position: relative; min-height: 100vh; display: flex; flex-direction: column; }
.dh-auth-bg { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--dh-ink); }
/* The brand wash over the photo layers below, instead of the template's
   grey gradient - a plain ::after so it always paints on top of the
   Ken Burns slides and the caustic overlay without needing its own
   z-index (default paint order: a pseudo-element paints after its
   element's real children). */
.dh-auth-bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(11,42,58,.78) 0%, rgba(14,77,104,.82) 100%); }

/* Ken Burns crossfade (Sign-In Lab study, Pablo 2026-09-19: "implement
   your recommendation") - three photos slowly cross-fading and scaling.
   The parallax wrapper is oversized (inset:-6%) and JS-translated on
   pointermove, so nudging it never reveals an edge; kept separate from
   the slides' own scale/opacity animation so the two transforms don't
   fight on the same element. */
.dh-auth-parallax { position: absolute; inset: -6%; transition: transform .6s cubic-bezier(.18,.7,.28,1); }
.dh-auth-kb { position: absolute; inset: 0; background-size: cover; background-position: center 45%; opacity: 0; animation: dhAuthKb 21s infinite; will-change: transform, opacity; }
.dh-auth-kb:nth-child(1) { animation-delay: 0s; }
.dh-auth-kb:nth-child(2) { animation-delay: 7s; }
.dh-auth-kb:nth-child(3) { animation-delay: 14s; }
@keyframes dhAuthKb {
  0% { opacity: 0; transform: scale(1.02); }
  4% { opacity: 1; }
  33% { opacity: 1; transform: scale(1.09); }
  38% { opacity: 0; transform: scale(1.10); }
  100% { opacity: 0; }
}
/* Drifting caustic-light texture layered on top of the photos, under the
   ink wash - the shimmer real sunlight makes through moving water. */
.dh-auth-caustic { position: absolute; inset: -20%; opacity: .38; mix-blend-mode: screen; pointer-events: none;
  background:
    repeating-linear-gradient(104deg, rgba(150,230,255,0) 0 22px, rgba(150,230,255,.5) 24px, rgba(150,230,255,0) 44px),
    repeating-linear-gradient(72deg, rgba(120,220,245,0) 0 34px, rgba(120,220,245,.34) 37px, rgba(120,220,245,0) 66px);
  filter: blur(7px);
  animation: dhAuthSway 14s ease-in-out infinite alternate;
}
@keyframes dhAuthSway {
  0% { transform: translate3d(-3%,-2%,0) rotate(-1.2deg) scale(1.04); }
  100% { transform: translate3d(4%,3%,0) rotate(1.6deg) scale(1.12); }
}
@media (prefers-reduced-motion: reduce) {
  .dh-auth-kb, .dh-auth-caustic { animation: none !important; }
  .dh-auth-kb:first-child { opacity: 1; }
  .dh-auth-parallax { transition: none !important; }
}
.dh-auth-main { position: relative; z-index: 1; flex: 1 1 auto; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 24px 16px calc(40px + env(safe-area-inset-bottom)); }
.dh-auth-card { width: 100%; max-width: 420px; background: var(--dh-paper); border-radius: 18px; padding: 28px 24px 24px; box-shadow: 0 18px 50px rgba(5,25,35,.35); text-align: center; }
.dh-auth-logo { display: block; margin: 0 auto 14px; }
.dh-auth-title { font-size: 1.45rem; font-weight: 700; color: var(--dh-ink); margin: 0; line-height: 1.2; }
.dh-auth-sub { font-size: .87rem; color: var(--dh-muted); margin: 8px 0 0; line-height: 1.45; }

.dh-form { text-align: left; margin-top: 22px; }
.dh-field { margin-bottom: 14px; }
.dh-field label { display: block; font-size: .78rem; font-weight: 700; color: var(--dh-muted); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 5px; }
.dh-field input { width: 100%; padding: 12px 14px; font-size: 1rem; color: var(--dh-ink); background: #fff; border: 1px solid var(--dh-line); border-radius: 12px; }
.dh-field input:focus { outline: none; border-color: var(--dh-sea); box-shadow: 0 0 0 3px rgba(14,124,158,.15); }
.dh-field textarea { width: 100%; padding: 12px 14px; font-size: 1rem; color: var(--dh-ink); background: #fff; border: 1px solid var(--dh-line); border-radius: 12px; resize: vertical; }
.dh-field textarea:focus { outline: none; border-color: var(--dh-sea); box-shadow: 0 0 0 3px rgba(14,124,158,.15); }
.dh-editor-toolbar { display: flex; gap: 6px; margin-bottom: 8px; flex-wrap: wrap; }
.dh-editor-toolbar button {
  display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
  border: 1px solid var(--dh-line); background: #fff; border-radius: 8px; color: var(--dh-muted); cursor: pointer;
}
.dh-editor-toolbar button:hover { background: var(--dh-foam); color: var(--dh-ink); border-color: var(--dh-sea); }
.dh-editor-toolbar button .material-icons-round { font-size: 19px; }
.dh-editor-toolbar .dh-editor-sep { width: 1px; background: var(--dh-line); margin: 4px 4px; }
.dh-field-error { margin: -8px 0 12px; font-size: .8rem; color: #b0322b; }
.dh-note { padding: 10px 14px; border-radius: 12px; font-size: .85rem; margin-bottom: 14px; }
.dh-note.is-good { background: #eaf5ee; color: #2e7d4f; }
.dh-note.is-bad { background: #f8e9e2; color: #b0532a; }

.dh-btn-block { width: 100%; justify-content: center; padding: 13px 16px; font-size: .95rem; }
.dh-btn-google { background: #fff; color: var(--dh-ink); border: 1px solid var(--dh-line); gap: 10px; margin-top: 10px; }
.dh-btn-google:hover { border-color: var(--dh-sea); color: var(--dh-ink); background: var(--dh-sand); }

.dh-auth-remember { display: flex; align-items: center; gap: 8px; margin: 4px 0 18px; padding-left: 0; }
.dh-auth-remember .form-check-input { margin: 0; flex: 0 0 auto; }
.dh-auth-remember .form-check-label { font-size: .85rem; color: var(--dh-muted); margin: 0; }
.dh-auth-terms { display: flex; align-items: flex-start; gap: 8px; margin: 4px 0 18px; padding-left: 0; }
.dh-auth-terms .form-check-input { margin: 2px 0 0; flex: 0 0 auto; }
.dh-auth-terms .form-check-label { font-size: .82rem; color: var(--dh-muted); margin: 0; line-height: 1.45; }
.dh-auth-terms a { color: var(--dh-sea); font-weight: 700; }
/* The template paints a checked box magenta; these are ours, so they are ours. */
.dh-auth-terms .form-check-input:checked,
.dh-auth-remember .form-check-input:checked { background-color: var(--dh-sea) !important; border-color: var(--dh-sea) !important; }
.dh-auth-terms .form-check-input:checked:after,
.dh-auth-remember .form-check-input:checked:after { border-color: #fff !important; }

.dh-captcha-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.dh-captcha-row img { border: 1px solid var(--dh-line); border-radius: 10px; height: 46px; }
.dh-captcha-refresh { border: 1px solid var(--dh-line); background: #fff; border-radius: 10px; width: 42px; height: 42px; display: inline-flex; align-items: center; justify-content: center; cursor: pointer; color: var(--dh-sea); }
.dh-captcha-refresh:hover { border-color: var(--dh-sea); }

.dh-auth-links { margin-top: 20px; text-align: center; }
.dh-auth-links p { font-size: .85rem; color: var(--dh-muted); margin: 0 0 8px; }
.dh-auth-links a { color: var(--dh-sea); font-weight: 700; text-decoration: none; }
.dh-auth-links a:hover { text-decoration: underline; }
.dh-auth-guest { padding-top: 10px; border-top: 1px solid var(--dh-line); margin-top: 14px !important; }

.dh-auth-foot { position: relative; z-index: 1; margin: 18px 0 0; font-size: .78rem; color: rgba(255,255,255,.75); text-align: center; }
.dh-auth-foot a { color: rgba(255,255,255,.92); margin-left: 12px; text-decoration: none; }
.dh-auth-foot a:hover { text-decoration: underline; }
.dh-auth-version { display: block; margin-top: 4px; opacity: .7; }
/* The add to home screen bar sits above the tab bar everywhere else; there is
   no tab bar here, so it drops to the real bottom and the card clears it
   (Zach's screenshot: it was covering the "Sign up" link). */
body.dh-auth-body .dh-install { bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
@media (max-width: 991px) { .dh-auth-main { padding-bottom: calc(118px + env(safe-area-inset-bottom)); } }

/* ------------------------------------------------------------------ */
/* Marine forecast. Weather became a bottom tab, so the page leads with */
/* the verdict Pablo's crawler already computes instead of a photo.     */
/* ------------------------------------------------------------------ */
/* No cap of its own: it's nested inside .main-content > .container-fluid,
   which now carries the universal 1100px cap (see above) - adding another
   one here would just add a second, smaller inset on top of that. */
.dh-wx { padding: 0 4px; }
.dh-wx-verdict, .dh-wx-card { background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 16px; margin-top: 12px; }
.dh-wx-verdict { padding: 16px; }
/* Live current reading (Miami/Fort Lauderdale only, weatherlocations.buoy):
   shares a row with the "Good diving today" callout, 10/2, at every width -
   the callout's own text just wraps to more lines on narrow phones rather
   than the two stacking (2026-09-11). */
.dh-wx-callout-row.has-current { display: grid; grid-template-columns: 10fr 2fr; align-items: stretch; gap: 8px; margin-top: 14px; }
.dh-wx-callout-row.has-current .dh-wx-callout { margin-top: 0; min-width: 0; }
.dh-wx-current { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 8px 4px; border-radius: 14px; background: var(--dh-foam); text-align: center; min-width: 0; }
.dh-wx-current-label { font-size: .58rem; font-weight: 800; text-transform: uppercase; letter-spacing: .02em; color: var(--dh-muted); }
/* Modern compass (2026-09-11): plain SVG replacing Pablo's old raster
   bg/needle PNGs. Face is fixed (N marked at top); the needle rotates to
   the buoy's reported bearing, sea-blue tip / muted tail like a real dial. */
.dh-wx-compass { position: relative; width: 52px; height: 52px; max-width: 100%; aspect-ratio: 1 / 1; }
@media (max-width: 374.98px) { .dh-wx-compass { width: 40px; } .dh-wx-compass-n { font-size: 13px; } }
.dh-wx-compass-face, .dh-wx-compass-needle { position: absolute; inset: 0; width: 100%; height: 100%; }
.dh-wx-compass-face circle { fill: var(--dh-paper); stroke: var(--dh-line); stroke-width: 3; }
.dh-wx-compass-n { fill: var(--dh-muted); font-size: 15px; font-weight: 800; text-anchor: middle; font-family: var(--dh-font); }
.dh-wx-compass-needle { transition: transform .3s ease; }
.dh-wx-compass-tip { fill: var(--dh-sea); }
.dh-wx-compass-tail { fill: var(--dh-line); }
.dh-wx-compass-hub { fill: var(--dh-deep); }
.dh-wx-current-speed { font-size: .8rem; font-weight: 800; color: var(--dh-deep); }
.dh-wx-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.dh-wx-place { font-size: 1.2rem; font-weight: 700; margin: 0; color: var(--dh-ink); }
.dh-wx-date { font-size: .76rem; color: var(--dh-muted); margin: 2px 0 0; }
.dh-wx-swap { flex: 0 0 auto; border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill); padding: 6px 12px; font-size: .78rem; font-weight: 700; color: var(--dh-sea); text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
.dh-wx-swap .material-icons-round { font-size: 16px; }
.dh-wx-swap:hover { border-color: var(--dh-sea); color: var(--dh-deep); }

.dh-wx-callout { margin-top: 14px; border-radius: 14px; padding: 14px; border: 1px solid; }
.dh-wx-callout.is-good { background: var(--dh-good-bg); border-color: #a9dcbb; }
.dh-wx-callout.is-avg  { background: var(--dh-avg-bg);  border-color: #e6d79a; }
.dh-wx-callout.is-poor { background: var(--dh-poor-bg); border-color: #f2b9b4; }
.dh-wx-callout.is-none { background: var(--dh-foam); border-color: var(--dh-line); }
.dh-wx-word { font-size: 1.55rem; font-weight: 900; line-height: 1.1; margin: 0; }
.dh-wx-callout.is-good .dh-wx-word { color: var(--dh-good); }
.dh-wx-callout.is-avg  .dh-wx-word { color: var(--dh-avg); }
.dh-wx-callout.is-poor .dh-wx-word { color: var(--dh-poor); }
.dh-wx-callout.is-none .dh-wx-word { color: var(--dh-muted); }
.dh-wx-why { font-size: .85rem; margin: 6px 0 0; line-height: 1.45; opacity: .9; }

.dh-wx-halves { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px; }
.dh-wx-half { border: 1px solid var(--dh-line); border-radius: 12px; padding: 10px; display: flex; flex-direction: column; }
.dh-wx-lab { font-size: .67rem; text-transform: uppercase; letter-spacing: .05em; color: var(--dh-muted); font-weight: 700; }
.dh-wx-val { font-size: 1rem; font-weight: 800; margin-top: 2px; }
.dh-wx-half.is-good .dh-wx-val { color: var(--dh-good); }
.dh-wx-half.is-avg  .dh-wx-val { color: var(--dh-avg); }
.dh-wx-half.is-poor .dh-wx-val { color: var(--dh-poor); }
.dh-wx-half.is-none .dh-wx-val { color: var(--dh-muted); font-size: .85rem; }
.dh-wx-sub { font-size: .72rem; color: var(--dh-muted); margin-top: 3px; }

.dh-wx-facts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; margin-top: 12px; }
.dh-wx-fact { background: var(--dh-foam); border-radius: 11px; padding: 9px 4px; text-align: center; display: flex; flex-direction: column; align-items: center; }
.dh-wx-fact .material-icons-round { font-size: 15px; color: var(--dh-sea); }
.dh-wx-n { font-size: .98rem; font-weight: 800; color: var(--dh-deep); line-height: 1.15; margin-top: 2px; }
.dh-wx-n small { font-size: .62rem; font-weight: 700; margin-left: 1px; }
.dh-wx-u { font-size: .61rem; color: var(--dh-muted); text-transform: uppercase; letter-spacing: .03em; margin-top: 3px; font-weight: 700; }

.dh-wx-boats { display: flex; align-items: center; gap: 8px; margin-top: 12px; padding: 11px 13px; border-radius: 12px; background: var(--dh-ink); color: #fff; text-decoration: none; font-size: .85rem; font-weight: 700; }
.dh-wx-boats:hover { background: var(--dh-deep); color: #fff; }
.dh-wx-boats .material-icons-round { font-size: 19px; }
.dh-wx-arrow { margin-left: auto; }
.dh-wx-explain { margin: 10px 0 0; text-align: center; font-size: .76rem; }
.dh-wx-explain a { color: var(--dh-sea); font-weight: 700; text-decoration: none; }

.dh-beach-sky { display: flex; align-items: center; gap: 4px; font-size: .8rem; color: var(--dh-muted); margin: 2px 0 0; }
.dh-beach-sky img { flex: 0 0 auto; }
.dh-beach-below-top { margin-top: var(--dh-space-6); }

/* Beach Diving: tide strip (shore diving is usually best around high tide, so this is
   promoted out of the "Tides and daylight" details panel the forecast page tucks it in). */
.dh-beach-tides { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--dh-line); }
.dh-beach-next-tide { display: flex; align-items: center; gap: 8px; font-weight: 700; color: var(--dh-ink); margin: 0 0 8px; font-size: .92rem; }
.dh-beach-next-tide .material-icons-round { color: var(--dh-sea); font-size: 20px; }
.dh-beach-tide-row { display: flex; flex-wrap: wrap; gap: 8px; }
.dh-beach-tide { display: inline-flex; align-items: center; gap: 4px; padding: 5px 10px; border-radius: var(--dh-radius-pill); font-size: .8rem; background: var(--dh-foam); color: var(--dh-muted); }
.dh-beach-tide.is-high { background: var(--dh-good-bg); color: var(--dh-good); }
.dh-beach-tide.is-next { outline: 2px solid var(--dh-sea); outline-offset: 1px; font-weight: 700; }

.dh-beach-map { width: 100%; height: 420px; border-radius: var(--dh-radius); background: var(--dh-sand); overflow: hidden; }

.dh-wx-ch { font-size: .95rem; font-weight: 800; padding: 13px 15px; margin: 0; border-bottom: 1px solid var(--dh-line); display: flex; align-items: center; justify-content: space-between; }
/* Was a blanket "span" selector, which also caught the outer title span
   wrapping "Along the coast today" + its hint (needed so both sit on the
   left of the sort button) and shrank the title itself along with the
   hint. Scoped to .dh-wx-hint specifically instead (2026-09-11). */
.dh-wx-ch .dh-wx-hint { font-size: .72rem; font-weight: 400; color: var(--dh-muted); }
.dh-wx-ch-title { font-size: inherit; font-weight: inherit; color: inherit; }

.dh-wx-day { display: flex; align-items: center; gap: 9px; padding: 11px 15px; border-bottom: 1px solid #eef1f3; color: var(--dh-ink); text-decoration: none; }
.dh-wx-day:last-child { border-bottom: 0; }
.dh-wx-day:hover { background: var(--dh-sand); color: var(--dh-ink); }
.dh-wx-day.is-today { background: #f7fbfc; }
.dh-wx-dday { flex: 0 0 46px; }
.dh-wx-dday b { display: block; font-size: .85rem; font-weight: 800; }
.dh-wx-dday span { display: block; font-size: .67rem; color: var(--dh-muted); }
.dh-wx-bars { flex: 1 1 auto; display: flex; gap: 4px; min-width: 0; }
.dh-wx-bar { flex: 1; border-radius: 7px; padding: 5px 4px; text-align: center; font-size: .67rem; font-weight: 800; line-height: 1.2; }
.dh-wx-bar small { display: block; font-weight: 600; opacity: .75; font-size: .6rem; }
.dh-wx-bar.is-good { background: var(--dh-good-bg); color: var(--dh-good); }
.dh-wx-bar.is-avg  { background: var(--dh-avg-bg);  color: var(--dh-avg); }
.dh-wx-bar.is-poor { background: var(--dh-poor-bg); color: var(--dh-poor); }
.dh-wx-bar.is-none { background: var(--dh-foam); color: var(--dh-muted); }
.dh-wx-dsea { flex: 0 0 78px; text-align: right; font-size: .69rem; color: var(--dh-muted); line-height: 1.35; }
.dh-wx-dsea b { color: var(--dh-ink); font-weight: 700; }
.dh-wx-dboats { color: var(--dh-sea); font-weight: 700; }

.dh-wx-crow { display: flex; align-items: center; gap: 10px; padding: 9px 15px; border-bottom: 1px solid #eef1f3; text-decoration: none; color: var(--dh-ink); }
.dh-wx-crow:last-child { border-bottom: 0; }
.dh-wx-crow:hover { background: var(--dh-sand); color: var(--dh-ink); }
.dh-wx-crow.is-here { background: #f7fbfc; }
.dh-wx-crow.is-here .dh-wx-cname { font-weight: 800; }
.dh-wx-cname { flex: 1 1 auto; font-size: .86rem; font-weight: 600; }
.dh-wx-clabel { margin: 10px 15px 4px; font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--dh-muted); }
.dh-wx-cnum { flex: 0 0 70px; text-align: right; font-size: .7rem; color: var(--dh-muted); }
.dh-wx-cnum b { color: var(--dh-ink); }

/* South/north toggle sitting in the "Along the coast" card header. */
.dh-wx-sort {
  display: inline-flex; align-items: center; gap: 3px; margin-left: 8px; padding: 3px 9px;
  border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill); color: var(--dh-sea);
  font-size: .68rem; font-weight: 700; text-decoration: none;
}
.dh-wx-sort:hover { border-color: var(--dh-sea); color: var(--dh-deep); }
.dh-wx-sort .material-icons-round { font-size: 14px; }

.dh-wx-more { background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 16px; margin-top: 12px; }
.dh-wx-more > summary { padding: 13px 15px; font-weight: 700; font-size: .9rem; cursor: pointer; list-style: none; display: flex; align-items: center; gap: 9px; color: var(--dh-ink); }
.dh-wx-more > summary::-webkit-details-marker { display: none; }
.dh-wx-more > summary:hover { color: var(--dh-deep); }
.dh-wx-more > summary .material-icons-round { color: var(--dh-sea); font-size: 20px; }
/* Chevron in the top-right corner marking these <details> as collapsible -
   same chevron_right/expand_more pair as the Best Gas card's own Show/Hide
   details toggle (Pablo, 2026-09-24: "all the gas price frames need to
   have the arrow...to indicate they are collapsable"). Covers every
   .dh-wx-more on the site (Gas Price/Gas prices, Weather's Live Webcam,
   etc.) since they're all the same collapsible pattern. */
.dh-wx-more > summary::after { content: 'chevron_right'; font-family: 'Material Icons Round'; font-size: 20px; color: var(--dh-muted); margin-left: auto; }
.dh-wx-more[open] > summary::after { content: 'expand_more'; }
.dh-wx-hint { margin-left: auto; font-weight: 400; font-size: .72rem; color: var(--dh-muted); }
.dh-wx-more-body { padding: 0 15px 15px; }
.dh-wx-tides { list-style: none; margin: 0; padding: 0; font-size: .84rem; }
.dh-wx-tides li { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eef1f3; color: var(--dh-muted); }
.dh-wx-tides li:last-child { border-bottom: 0; }
.dh-wx-tides b { color: var(--dh-ink); }
/* The old cards inside the collapsed sections keep their own look but must not
   push the page sideways on a phone. */
.dh-wx-more-body .table-responsive { overflow-x: auto; }
.dh-wx-more-body iframe, .dh-wx-more-body img, .dh-wx-more-body canvas { max-width: 100%; }

/* Quick webcam, right under the verdict card - a single collapsed row until
   tapped, so it never competes with the diving verdict for attention. */
.dh-wx-cam-body iframe { width: 100%; height: 260px; border: 0; border-radius: 10px; display: block; }

/* Charts and the full table, restyled onto the flat .dh-card look instead of
   the old dark-gradient Material-Dashboard cards. */
.dh-wx-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin-top: 12px; }
.dh-wx-chart-card { margin-top: 0; }
.dh-wx-chart-card canvas { max-height: 160px; }
.dh-wx-update { display: flex; align-items: center; gap: 5px; margin: 10px 0 0; font-size: .74rem; color: var(--dh-muted); }
.dh-wx-update .material-icons-round { font-size: 15px; }
.dh-wx-table-card { margin-top: 12px; }
.dh-wx-table-wrap { overflow-x: auto; }
/* Real <table> (2026-09-11): a genuine AM/PM sub-header for the Marine rows
   instead of cramming both values into one cell - each day is two real
   columns, so the header can label them instead of the reader guessing. */
.dh-wx-table { width: 100%; min-width: 620px; border-collapse: collapse; font-size: .82rem; }
.dh-wx-table th, .dh-wx-table td { padding: 8px 6px; text-align: center; border-bottom: 1px solid var(--dh-line); }
.dh-wx-table thead tr:first-child th { font-size: .78rem; font-weight: 800; color: var(--dh-ink); }
.dh-wx-table .dh-wx-subhead th { font-size: .64rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--dh-muted); padding-top: 0; }
.dh-wx-table td.dh-wx-tlabel { text-align: left; font-size: .68rem; font-weight: 800; text-transform: uppercase; letter-spacing: .02em; color: var(--dh-muted); white-space: nowrap; }
.dh-wx-table tbody td { color: var(--dh-ink); }
.dh-wx-table .dh-wx-tsection-row td { background: var(--dh-foam); color: var(--dh-deep); font-weight: 800; text-transform: uppercase; font-size: .7rem; letter-spacing: .04em; border-radius: 6px; border-bottom: 0; }
.dh-wx-table tbody tr:last-child td { border-bottom: 0; }
.dh-wx-table .material-icons-round.rotate-icon { font-size: 15px; color: var(--dh-sea); vertical-align: middle; }

/* ------------------------------------------------------------------ */
/* Deco Planner / Best Gases (2026-09-13): collapsible "Inputs" card    */
/* header, and the plain-number twin for every noUiSlider (see the      */
/* mirror() enhancement in divershub.js). Everything the sliders,       */
/* charts and tables themselves already draw is untouched - this only   */
/* dresses the outer chrome and adds the numeric fallback.              */
/* ------------------------------------------------------------------ */
.dh-calc-inputs-head {
  display: flex; align-items: center; gap: 10px; cursor: pointer; user-select: none;
  padding: 16px 20px; background: var(--dh-ink); color: #fff; border-radius: 14px 14px 0 0;
}
.dh-calc-inputs-head .material-icons-round { color: #fff; opacity: .85; }
/* h3 grows to fill the row, so the hint + chevron after it stay pinned to
   the right edge whether or not the (optional, hidden-when-open) hint is
   present. */
.dh-calc-inputs-head h3 { flex: 1 1 auto; margin: 0; font-size: 1.05rem; font-weight: 800; color: #fff; }
.dh-calc-inputs-hint { font-size: .78rem; font-weight: 600; color: rgba(255,255,255,.7); }
.dh-calc-inputs-head:hover { background: var(--dh-deep); }

/* Same dark header bar as .dh-calc-inputs-head, reused for every section
   of the results card (Decompression plan, What if, Gas consumption,
   Tissue compartments) so the whole page reads as one theme instead of
   the old blue/grey Material-Dashboard gradient banners (Pablo,
   2026-09-16: "retheme...and all the titles inside that card"). Collapsible
   variant adds the pointer cursor + chevron; non-collapsible sections
   (the outer "Decompression plan" card) just drop .is-toggle.
   Named dh-deco-section-* (not dh-section-*) because that generic name is
   already a different, older component (Landing.blade.php's h2-based
   section title) - reusing it left this header inheriting that unrelated
   rule's `margin` and rendering as if it floated inside its own card
   instead of flush at the top (Pablo, 2026-09-16: "not at the top? there
   is a white card behind"). */
.dh-deco-section-head {
  display: flex; align-items: center; gap: 10px; padding: 14px 20px; margin: 0;
  background: var(--dh-ink); color: #fff; border-radius: 14px 14px 0 0;
}
.dh-deco-section-head .material-icons-round { color: #fff; opacity: .85; }
.dh-deco-section-head-icon-svg { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; color: #fff; opacity: .85; flex: 0 0 auto; }
.dh-deco-section-head-icon-svg svg { width: 24px; height: 24px; }
.dh-deco-section-head h3, .dh-deco-section-head h4 { flex: 1 1 auto; margin: 0; font-size: 1rem; font-weight: 800; color: #fff; }
/* Title + Model/GFs stacked instead of sharing the title's own line, so
   Export PDF/Save Plan on a narrow card don't get squeezed against a long
   "Model ZH-L16C-GF - GFs 40/70" string (Pablo, 2026-09-19: "show the model
   and GF below Decompression Plan text so the two...pills don't overflow"). */
.dh-deco-section-head-title-wrap { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.dh-deco-section-head-title-wrap h3 { flex: 0 0 auto; }
.dh-deco-section-head.is-toggle { cursor: pointer; user-select: none; }
.dh-deco-section-head.is-toggle:hover { background: var(--dh-deep); }
.dh-deco-section-head-chevron { transition: transform .15s; }
.dh-deco-section-head.is-collapsed .dh-deco-section-head-chevron { transform: rotate(-90deg); }
.dh-deco-section-body { border: 1px solid var(--dh-line); border-top: none; border-radius: 0 0 14px 14px; padding: 16px; background: var(--dh-paper); }

/* Per-gas SAC rate control inline in the Gas consumption table (Pablo,
   2026-09-24: "typically you consume more gas depending on the mix...put
   them inline with the gas table"; then: "user can type the numbers for
   the SACs, specially useful on mobile view where moving a slider is
   tricky"). A real editable .dh-gas-input (same pencil-icon affordance as
   every other slider-paired value on this page) plus a slider below it -
   stacked, not side-by-side, since this column shares a row with the Gas
   split pill and Volume figure and phone-width tables don't have room to
   spare. */
.dh-gasconsumption-sac { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 90px; }
.dh-gasconsumption-sac .dh-gas-input { width: 52px; height: 26px; font-size: .76rem; padding: 0 10px 0 4px; }
.dh-gasconsumption-sac .dh-gas-edit-icon { font-size: 13px; }
.dh-gasconsumption-sac-unit { font-size: .68rem; color: var(--dh-muted); font-weight: 600; }
.dh-gasconsumption-sac-slider { width: 100%; max-width: 100px; accent-color: var(--dh-sea); height: 16px; margin: 0; }

/* O2 toxicity card (Pablo, 2026-09-24) - CNS gets a gauge bar since the
   API's own field is already a 0-100(+)% of a hard limit; OTU has no such
   ceiling so it's just a pill + caption, not a bar with a fabricated
   endpoint. */
.dh-o2tox-row { display: flex; align-items: center; gap: 12px; }
.dh-o2tox-row + .dh-o2tox-row { margin-top: 14px; }
.dh-o2tox-label { flex: 0 0 40px; font-weight: 800; font-size: .8rem; color: var(--dh-ink); }
.dh-o2tox-track { flex: 1 1 auto; height: 12px; border-radius: 99px; background: var(--dh-sand); border: 1px solid var(--dh-line); overflow: hidden; }
.dh-o2tox-fill { height: 100%; border-radius: 99px; background: var(--dh-good); transition: width .3s ease; }
.dh-o2tox-fill.is-warn { background: var(--dh-warn); }
.dh-o2tox-fill.is-danger { background: var(--dh-danger); }
.dh-o2tox-value { flex: 0 0 auto; min-width: 44px; text-align: right; font-weight: 800; font-size: .85rem; color: var(--dh-ink); font-variant-numeric: tabular-nums; }
.dh-o2tox-otu-caption { font-size: .76rem; color: var(--dh-muted); }
.dh-o2tox-sub { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--dh-line); font-size: .82rem; color: var(--dh-muted); text-align: center; }
.dh-o2tox-sub .dh-gas-result-pill { margin: 0 2px; }

/* Decompression plan's summary strip - one compact line instead of a
   two-column table (Pablo, 2026-09-16: "smaller and more sleek...one
   single line"). Run/deco time are calculated results, so they get the
   same blue pill as everywhere else; model/GFs are just context, so they
   stay small, grey, plain text. */
/* Horizontal padding dropped to 0 (was 14px 16px) - the column's own
   Bootstrap gutter already lines this row up with the card's edges;
   keeping a padding here on top of that made it sit noticeably more inset
   than the Decompression Table/Chart row right below it (Pablo, 2026-09-19:
   "need to take all the card width, with the right padding like the table
   and the graph below"). Vertical padding stays so the pills don't crowd
   the header/table above and below them. */
.dh-deco-summary {
  display: flex; align-items: stretch; gap: 12px;
  padding: 14px 0;
}
/* Run time and Deco time each take half the card as one big pill - not a
   plain label next to a small result pill anymore (Pablo, 2026-09-17:
   "center in the middle of the card and make it larger...include the whole
   'Run time xm' in one pill taking half the card"). */
.dh-deco-summary-pill {
  flex: 1 1 50%; height: 52px; gap: 8px; padding: 0 16px; font-size: 1.05rem;
}
.dh-deco-summary-pill-label { font-weight: 600; opacity: .85; font-size: .8em; }

/* Model/GFs moved into the "Decompression plan" title itself, in a smaller
   un-bold light font right next to it (Pablo, 2026-09-16). */
.dh-deco-section-head-meta { font-size: .76rem; font-weight: 400; color: rgba(255,255,255,.7); flex: 0 1 auto; white-space: nowrap; }
.dh-deco-section-head-meta b { font-weight: 400; }

/* Export PDF / Save Plan - small so they don't compete with the card title
   (Pablo, 2026-09-18: "not too large"). */
.dh-deco-header-btn {
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto;
  padding: 5px 10px; border-radius: var(--dh-radius-pill); border: 1px solid rgba(255,255,255,.4);
  background: rgba(255,255,255,.1); color: #fff; font-size: .74rem; font-weight: 700; cursor: pointer;
  white-space: nowrap;
}
.dh-deco-header-btn:hover { background: rgba(255,255,255,.25); }
.dh-deco-header-btn .material-icons-round { font-size: 14px; }
.dh-deco-header-btn.is-success { background: var(--dh-good); border-color: var(--dh-good); }
.dh-deco-header-btn.is-error { background: var(--dh-danger); border-color: var(--dh-danger); }
.dh-deco-header-btn[disabled] { opacity: .7; cursor: default; }
/* Registered-account-only header action (Export PDF, Pablo, 2026-09-25) -
   still clickable (opens the guest sign-up modal), just muted like the
   disabled state above so it doesn't read as a normal, immediately-usable
   action. */
.dh-deco-header-btn.is-locked { opacity: .6; }

/* The Inputs card's grey row separators only earn their keep on a phone,
   where each slider group is its own full-width block stacked vertically -
   on tablet/desktop, the same groups sit side by side in columns, and the
   lines read as visual clutter cutting across otherwise-related content
   (Pablo, 2026-09-16: "hide...ONLY in desktop and iPad views...keep them
   for mobile ONLY"). Bootstrap's own md breakpoint (768px) is what these
   same rows already switch from stacked to columned at. */
.dh-deco-input-divider { border-bottom: 1px solid #D3D3D3; }
@media (min-width: 768px) {
  .dh-deco-input-divider { border-bottom: none; }
}

/* Multi-level dive planning (Pablo, 2026-09-25): each level needs to read
   as its own distinct "frame" even on desktop, unlike
   .dh-deco-input-divider above (a mobile-only bottom line, no border at
   all once columned). A real bordered card instead. */
.dh-level-panel { position: relative; border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: var(--dh-space-3); background: var(--dh-paper); margin-bottom: var(--dh-space-3); }
@media (min-width: 992px) { .dh-level-panel { margin-bottom: 0; } }
/* Mobile stacks these full-width (Pablo: "in Mobile they look great") -
   only tighten the horizontal gap between panels at tablet/desktop
   widths, where Bootstrap's default 1.5rem row gutter left them a bit
   too far apart (Pablo, 2026-09-25: "in desktop and iPad I want them
   slightly closer"). */
@media (min-width: 768px) { #multiLevelRow { --bs-gutter-x: 1rem; } }

/* Small red circular delete affordance, replacing the old full-width
   "Delete level"/"Delete gas" buttons to save layout space (Pablo,
   2026-09-25). Two contexts: inline in a .dh-level-panel's corner
   (absolute, top-right of the card - levels 2-4), and inline in a gas
   preset chip row right after "Save this gas to My Gases" (Pablo: "put
   them to the right of the button 'Save this gas' for each gas" - flows
   naturally as a chip-row sibling there, not absolutely positioned). */
.dh-corner-delete {
  width: 26px; height: 26px; border-radius: 50%; border: 0; flex: 0 0 auto;
  background: var(--dh-danger); color: #fff;
  display: flex; align-items: center; justify-content: center;
  padding: 0; cursor: pointer;
}
.dh-corner-delete .material-icons-round { font-size: 15px; }
.dh-level-panel .dh-corner-delete { position: absolute; top: 8px; right: 8px; z-index: 5; }

/* "What if...?" scenario toggles, restyled as pill chips instead of the
   old Bootstrap form-switch (Pablo, 2026-09-16: "make them pills, they
   look old"). The checkbox stays real and unstyled (hidden) so every
   existing filter1-7 .checked read keeps working untouched - only the
   chrome changes. Wrapping the input INSIDE the label also fixes a
   latent bug where the label's for= pointed at a nonexistent id, so
   clicking the text never actually toggled the box. */
.dh-whatif-chips { display: flex; flex-direction: column; gap: 8px; }
.dh-whatif-chip { display: inline-flex; align-items: center; cursor: pointer; user-select: none; margin: 0; }
.dh-whatif-chip input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.dh-whatif-chip-body {
  display: inline-flex; align-items: center; width: 100%; padding: 8px 14px; border-radius: var(--dh-radius-pill);
  border: 1px solid var(--dh-line); background: var(--dh-paper); color: var(--dh-muted);
  font-size: .8rem; font-weight: 600; transition: background .15s, color .15s, border-color .15s;
}
.dh-whatif-chip input:checked + .dh-whatif-chip-body { background: var(--dh-ink); border-color: var(--dh-ink); color: #fff; }
.dh-whatif-chip input:focus-visible + .dh-whatif-chip-body { box-shadow: 0 0 0 2px var(--dh-foam); }

/* Material Symbols (variable font) - a separate family from the classic
   Material Icons Round used everywhere else in this app. Google's css2
   endpoint only ships the @font-face; unlike the older icon-font endpoint
   it doesn't bundle a ready-to-use class, so this app defines one itself.
   FILL 1 matches the filled look of .material-icons-round so the two sets
   don't visually clash side by side (Pablo, 2026-09-19: "Implement picking
   the icon Question Exchange" - a Material Symbols-only icon). */
.material-symbols-rounded {
  font-family: 'Material Symbols Rounded';
  font-weight: normal; font-style: normal; font-size: 24px; line-height: 1;
  letter-spacing: normal; text-transform: none; display: inline-block; white-space: nowrap;
  word-wrap: normal; direction: ltr;
  font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}

/* Floating "What if...?" bubble + picker modal (Pablo, 2026-09-19): replaces
   the old always-visible collapsible chip panel. Scoped to the deco chart
   card via its own position:relative wrapper, not fixed to the viewport
   like .dh-chat-fab is. One plain pill - icon then label - after a fused
   circle+pill version didn't land (Pablo, 2026-09-17: "let's avoid the
   circle and do only a pill"). */
.dh-whatif-fab {
  /* top was 10px, then 40px - level with Chart.js's own "Deco profile"
     legend row at the top of the canvas, so the pill sat right on top of
     it (Pablo, 2026-09-17: "push the what if bubble down a little...
     overlapping with the chart title"). Moved again once the UDDF upload
     button (Pablo, 2026-09-22) sat above the chart and the pill was back
     to blocking the top of the profile line - vertically centered on the
     chart instead, out of the way of both (Pablo: "sit it in the middle
     to the right of the chart"). */
  position: absolute; top: 50%; right: 10px; transform: translateY(-50%); z-index: 20;
  display: flex; align-items: center; gap: 8px;
  border: 0; background: var(--dh-sea); color: #fff;
  padding: 10px 16px; border-radius: var(--dh-radius-pill);
  box-shadow: 0 6px 18px rgba(11,42,58,.28); cursor: pointer;
}
.dh-whatif-fab .material-symbols-rounded { font-size: 20px; }
.dh-whatif-fab-label { font-weight: 800; font-size: .82rem; white-space: nowrap; }
.dh-whatif-fab:hover { background: var(--dh-deep); }

.dh-whatif-modal-backdrop {
  position: fixed; inset: 0; z-index: 10060; background: rgba(11,42,58,.45);
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.dh-whatif-modal {
  width: 100%; max-width: 360px; max-height: 80vh; overflow-y: auto;
  background: var(--dh-paper); border-radius: 14px; box-shadow: 0 20px 60px rgba(0,0,0,.3);
}
.dh-whatif-modal-head {
  display: flex; align-items: center; gap: 8px; padding: 14px 16px; border-bottom: 1px solid var(--dh-line);
  position: sticky; top: 0; background: var(--dh-paper); border-radius: 14px 14px 0 0;
}
.dh-whatif-modal-head h4 { margin: 0; flex: 1 1 auto; font-size: 1rem; font-weight: 700; color: var(--dh-ink); }
.dh-whatif-modal-head .material-symbols-rounded { color: var(--dh-sea); font-size: 22px; }
.dh-whatif-modal-close {
  border: 0; background: transparent; color: var(--dh-muted); cursor: pointer; padding: 2px;
  display: flex; align-items: center; justify-content: center;
}
.dh-whatif-modal-close:hover { color: var(--dh-ink); }
.dh-whatif-modal-body { padding: 14px 16px 16px; }
.dh-whatif-modal-hint { margin: 0 0 10px; font-size: .78rem; color: var(--dh-muted); }

/* Legend pill naming the active What-if scenario - sits ABOVE the New RT/
   New Deco Time pills, full width of the card so the two read as one
   group (Pablo, 2026-09-19: "put the pill with the legend above...get
   them closer together...the pill with the specific what if case should
   take the length of the screen"). The X is the exact equivalent of
   unchecking the scenario's chip today. */
.dh-whatif-legend {
  display: flex; align-items: center; gap: 6px; width: 100%; box-sizing: border-box;
  margin-bottom: 6px; padding: 6px 14px;
  border-radius: var(--dh-radius-pill); background: var(--dh-ink); color: #fff; font-size: .78rem; font-weight: 600;
}
.dh-whatif-legend .material-symbols-rounded { font-size: 16px; opacity: .85; }
#dhWhatIfLegendText { flex: 1 1 auto; }
.dh-whatif-legend-clear { cursor: pointer; font-size: 18px; opacity: .8; display: inline-flex; }
.dh-whatif-legend-clear:hover { opacity: 1; }

/* Tucks the New RT/New Deco Time row right under its legend (instead of
   the normal 14px .dh-deco-summary padding that separates it from the
   baseline pills above), so legend + pills visually read as one group. */
.dh-whatif-summary-row { padding-top: 0; }

.dh-slider-num {
  display: block; width: 88px; margin: 8px auto 0; padding: 5px 8px; text-align: center;
  border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill);
  font-size: .85rem; font-weight: 700; color: var(--dh-ink); background: var(--dh-paper);
}
.dh-slider-num:focus { outline: none; border-color: var(--dh-sea); box-shadow: 0 0 0 2px rgba(43,140,158,.18); }
/* Number input spinner arrows read as noise next to a slider that already
   has its own drag handle - keep the field plain. */
.dh-slider-num::-webkit-outer-spin-button, .dh-slider-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.dh-slider-num[type=number] { -moz-appearance: textfield; }

/* iOS install walkthrough modal (2026-09-14). */
.dh-ios-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.dh-ios-steps li { display: flex; align-items: center; gap: 12px; font-size: .92rem; color: var(--dh-ink); }
.dh-ios-step-icon {
  flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%; background: var(--dh-foam); color: var(--dh-sea);
  display: flex; align-items: center; justify-content: center;
}
.dh-ios-step-icon .material-icons-round { font-size: 20px; }
.dh-ios-copylink { display: flex; gap: 8px; }
.dh-ios-copylink input { flex: 1 1 auto; min-width: 0; font-size: .85rem; }
.dh-ios-copylink .dh-btn { flex: 0 0 auto; white-space: nowrap; }
.dh-ios-copylink .material-icons-round { font-size: 17px; }

/* Group chat @mention picker (2026-09-14). */
.dh-mention-menu {
  position: absolute; left: 0; right: 0; bottom: 100%; margin-bottom: 4px; z-index: 20;
  background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 10px;
  box-shadow: 0 6px 20px rgba(11,42,58,.18); max-height: 220px; overflow-y: auto;
}
.dh-mention-item {
  display: block; width: 100%; text-align: left; border: 0; background: none; padding: 9px 12px;
  font-size: .88rem; font-weight: 600; color: var(--dh-ink); cursor: pointer;
}
.dh-mention-item:hover, .dh-mention-item:first-child { background: var(--dh-foam); }

/* Profile Overview rebrand (2026-09-14). Keeps the page's existing
   multistep-form edit-toggle/slider/Choices/Dropzone JS wiring untouched -
   only the surrounding chrome changes. */
.dh-profile-head { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.dh-profile-avatar { position: relative; width: 84px; height: 84px; flex: 0 0 auto; }
.dh-profile-avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; border: 3px solid var(--dh-paper); box-shadow: 0 2px 10px rgba(11,42,58,.18); display: block; }
.dh-profile-avatar-edit {
  position: absolute; right: -2px; bottom: -2px; width: 30px; height: 30px; border-radius: 50%;
  background: var(--dh-sea); color: #fff; border: 2px solid var(--dh-paper); padding: 0;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.dh-profile-avatar-edit .material-icons-round { font-size: 16px; }
.dh-profile-avatar-edit:hover { background: var(--dh-deep); }
.dh-profile-who h5 { font-weight: 800; color: var(--dh-ink); }
.dh-google-badge {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 6px;
  font-size: .72rem; font-weight: 700; color: var(--dh-muted);
  background: var(--dh-sand); border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill);
  padding: 3px 10px 3px 8px;
}
.dh-google-badge img { display: block; }

.dh-profile-card { border: 1px solid var(--dh-line); border-radius: 12px; margin-bottom: var(--dh-space-4); }
.dh-profile-card-head { padding: 14px 16px 0; }
.dh-profile-card-head .dh-panel-title { text-transform: uppercase; font-size: .72rem; letter-spacing: .04em; color: var(--dh-muted); }
.dh-profile-card-body { padding: 16px; }
/* A collapsible card's header has no body-below to supply the bottom
   space .dh-profile-card-head's own padding (14px 16px 0) assumes - left
   as-is it read "too thin" when collapsed (Pablo, 2026-09-24). Full
   padding on all sides instead. */
.dh-profile-card-head-collapsible { padding: 14px 16px; }
.dh-profile-edit-btn { display: inline-flex; color: var(--dh-sea); cursor: pointer; }
.dh-profile-edit-btn .material-icons-round { font-size: 18px; }
.dh-profile-edit-btn:hover { color: var(--dh-deep); }

/* My Profile redesign (2026-09-17): compact themed replacements for the old
   Material Dashboard noUiSlider (certLevel, show-dives-within-level) and the
   Choices.js multi-select (favorite operators/locations) - neither is used
   anywhere else on the site (Pablo: "fav operators and fav location picker
   is something we don't use anywhere else"). Selects and the .dh-choice
   tile grid (already used by the welcome wizard) replace them so this page
   only speaks the one visual language the rest of the redesign already
   uses, and level values always render as their translated name (Open
   Water, etc.) instead of a raw number. */
/* x-dh-select: a themed dropdown, not a native <select> - the popup list
   on a native select renders with the OS's own chrome and font, completely
   outside the page's CSS (Pablo, 2026-09-17: "I really hate the native
   dropdowns...I'm ok with dropdowns, but not the system natives"). This is
   a button + an absolutely positioned <ul> the page's own CSS fully
   controls, with a hidden input carrying the real value. */
.dh-select { position: relative; }
.dh-select-btn {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 12px 14px; font-size: 1rem; font-family: inherit; color: var(--dh-ink); text-align: left;
  background: #fff; border: 1px solid var(--dh-line); border-radius: 12px; cursor: pointer;
}
.dh-select-btn:focus-visible { outline: none; border-color: var(--dh-sea); box-shadow: 0 0 0 3px rgba(14,124,158,.15); }
.dh-select-btn:disabled { background-color: var(--dh-sand); color: var(--dh-muted); cursor: not-allowed; }
.dh-select-btn .material-icons-round { font-size: 20px; color: var(--dh-muted); flex: 0 0 auto; }
.dh-select-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dh-select-menu {
  position: absolute; z-index: 20; top: calc(100% + 4px); left: 0; right: 0;
  background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: 12px;
  box-shadow: 0 8px 24px rgba(11,42,58,.16); list-style: none; margin: 0; padding: 6px;
  max-height: 260px; overflow-y: auto;
}
.dh-select-menu li { padding: 9px 10px; border-radius: 8px; cursor: pointer; font-size: .92rem; color: var(--dh-ink); }
.dh-select-menu li:hover { background: var(--dh-foam); }
.dh-select-menu li.is-selected { background: var(--dh-foam); color: var(--dh-deep); font-weight: 700; }
.dh-hint { font-size: .78rem; color: var(--dh-muted); margin: 6px 0 0; line-height: 1.45; }
.dh-level-row { display: flex; align-items: center; gap: 10px; }
.dh-level-row select { flex: 1; }
.dh-range-row { display: flex; gap: 12px; }
.dh-range-row .dh-field { flex: 1; margin-bottom: 0; }
.dh-chip-row { display: flex; flex-wrap: wrap; gap: 6px; }
.dh-fav-empty { font-size: .85rem; color: var(--dh-muted); font-style: italic; margin: 0; }

.dh-tag-input-row { display: flex; gap: 8px; }
.dh-tag-input-row input { flex: 1 1 auto; }
.dh-tag-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 6px 4px 12px;
  border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill);
  background: var(--dh-paper); color: var(--dh-muted); font-size: .8rem; font-weight: 600;
}
.dh-tag-chip button {
  display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  border: 0; border-radius: 50%; background: var(--dh-line); color: var(--dh-ink); padding: 0;
  font-size: .85rem; line-height: 1; cursor: pointer;
}
.dh-tag-chip button:hover { background: var(--dh-poor); color: #fff; }

/* Themed replacement for a native <input type="file"> (Pablo, 2026-09-22:
   "retheme...the button to upload a picture") - the real input stays in
   the DOM (still what the form submits), just visually hidden; this button
   triggers it and shows the chosen filename. */
.dh-file-picker { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.dh-file-picker input[type="file"] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; }
.dh-file-picker-name { font-size: .85rem; color: var(--dh-muted); }
.dh-choice-toolbar { margin-bottom: 10px; }
.dh-choice-toolbar input {
  width: 100%; padding: 10px 12px; border: 1px solid var(--dh-line); border-radius: 10px;
  font-size: .9rem; font-family: inherit;
}
.dh-choice-toolbar input:focus { outline: none; border-color: var(--dh-sea); box-shadow: 0 0 0 3px rgba(14,124,158,.15); }
.dh-choice-scroll { max-height: 360px; overflow-y: auto; padding-right: 4px; }

/* Auto-add rule (Pablo, 2026-09-23): the three AND-ed criteria groups as
   nested framed boxes with AND/OR pills between them, so the rule's own
   boolean shape ("trip type AND (operator OR location) AND (level OR
   site)") reads visually instead of just being implied by field order. */
.dh-rule-box { border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: 14px; background: var(--dh-paper); }
.dh-rule-outer { background: var(--dh-foam); }
.dh-rule-or-row { display: flex; align-items: stretch; gap: 12px; }
.dh-rule-or-row > .dh-rule-box { flex: 1 1 0; min-width: 0; }
.dh-rule-or-pill-col { display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
/* Reverted to this size after a shorter-lived smaller version (Pablo,
   2026-09-23: "revert the ANDs and ORs pills to the previous size"). */
.dh-rule-pill { display: inline-flex; align-items: center; justify-content: center; padding: 4px 14px; border-radius: var(--dh-radius-pill); font-size: .72rem; font-weight: 800; letter-spacing: .5px; color: #fff; white-space: nowrap; }
.dh-rule-pill-and { background: var(--dh-good); }
.dh-rule-pill-or { background: var(--dh-sea); }
.dh-rule-and-row { display: flex; justify-content: center; margin: 12px 0; }
@media (max-width: 576px) {
  .dh-rule-or-row { flex-direction: column; }
  .dh-rule-or-pill-col { margin: 4px 0; }
}
.dh-collapse-chevron { transition: transform .2s ease; color: var(--dh-muted); }
/* Two shapes: the chevron nested inside a bigger clickable toggle area
   (Notification preferences), or the chevron itself as its own second
   trigger for the same collapse target, sitting at the row's far right
   (auto-add rule, so it lines up with the other section's chevron
   position - Pablo, 2026-09-23: "put the both aligned to the right in
   both collapsable sections"). */
[data-bs-toggle="collapse"].collapsed .dh-collapse-chevron,
.dh-collapse-chevron.collapsed { transform: rotate(-90deg); }

/* Collapsible section headers (Notification preferences, Auto-add rule)
   and the Facebook sub-section - smaller and bold rather than the
   default .form-label size/weight (Pablo, 2026-09-23: "make the titles
   of the section in a smaller and bold font"). */
.dh-settings-section-title { font-size: .82rem; font-weight: 800; color: var(--dh-ink); }

/* Field labels inside an auto-add rule box (Trip type, Operators,
   Locations, Levels, Sites) - smaller than the default .form-label,
   scoped to this component only (Pablo, 2026-09-23: "Reduce all the
   text labels in dive type, locations, operators, levels and site"). */
.dh-rule-field-label { display: block; font-size: .78rem; font-weight: 700; color: var(--dh-ink); margin-bottom: 4px; }
.dh-profile-savebar { position: sticky; bottom: 12px; }

/* Verify-phone modal. */
.dh-verify-code-input { text-align: center; font-size: 1.4rem; font-weight: 800; letter-spacing: .3em; }

/* Admin Message Management console (2026-09-14). */
.dh-thread-scroll { max-height: 400px; overflow-y: auto; padding: 4px; display: flex; flex-direction: column; gap: 10px; }
.dh-thread-bubble { max-width: 78%; padding: 10px 12px; border-radius: 12px; background: var(--dh-foam); }
.dh-thread-bubble.is-outbound { align-self: flex-end; color: #fff; }
.dh-thread-bubble.is-outbound .dh-thread-bubble-meta { color: rgba(255,255,255,.75); }
/* Colored by channel, not just sent/received (Pablo, 2026-09-14) - a
   light tint received, the same hue solid-filled sent, so a diver's
   WhatsApp/SMS/email thread reads apart at a glance. */
.dh-thread-bubble.is-inbound.channel-sms { background: var(--dh-foam); }
.dh-thread-bubble.is-outbound.channel-sms { background: var(--dh-sea); }
.dh-thread-bubble.is-inbound.channel-whatsapp { background: var(--dh-good-bg); }
.dh-thread-bubble.is-outbound.channel-whatsapp { background: var(--dh-good); }
.dh-thread-bubble.is-inbound.channel-email { background: var(--dh-avg-bg); }
.dh-thread-bubble.is-outbound.channel-email { background: var(--dh-avg); }
.dh-thread-bubble-meta { display: flex; align-items: center; gap: 4px; font-size: .68rem; color: var(--dh-muted); margin-bottom: 3px; }
.dh-thread-bubble-body { font-size: .88rem; white-space: pre-wrap; word-break: break-word; }
.dh-thread-reply { margin-top: 14px; border-top: 1px solid var(--dh-line); padding-top: 14px; }

/* Small channel icon - the list's avatar fallback and each bubble's meta
   line, in place of the word "SMS"/"WhatsApp"/"Email" (Pablo, 2026-09-14). */
.dh-ch-icon { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; flex: 0 0 auto; }
.dh-ch-icon svg { width: 100%; height: 100%; }
.dh-ch-icon.is-sms { color: var(--dh-sea); font-size: 15px; }
.dh-ch-icon.is-whatsapp { color: var(--dh-good); }
.dh-ch-icon.is-email { color: var(--dh-avg); font-size: 15px; }
/* Inside a filled (outbound/solid) bubble the channel color would vanish
   into a same-hue background - fall back to the bubble's own white text. */
.dh-thread-bubble.is-outbound .dh-ch-icon { color: #fff; }
/* The list row's avatar circle sizes its own icon differently than the
   14px meta-line usage above. */
.dh-msg-avatar .dh-ch-icon { width: 20px; height: 20px; }
.dh-msg-avatar .dh-ch-icon.is-sms, .dh-msg-avatar .dh-ch-icon.is-email { font-size: 20px; }

/* Blocks pinch-to-zoom in the installed PWA only - the `dh-pwa-standalone`
   class is added to <html> by divershub.js when running standalone
   (Pablo, 2026-09-16: "it does not work" after the viewport-meta-tag +
   JS gesturestart approach - confirmed dead on a real iPad; touch-action
   is the one mechanism modern Safari still actually respects for this).
   pan-x/pan-y explicitly keep normal one-finger scrolling/dragging
   working (sliders, swipeable chip rows, charts) - only pinch and
   double-tap zoom get dropped. Wrapped in :where() so this carries
   effectively zero specificity, same as a bare `*` - existing
   component-level touch-action rules (e.g. noUiSlider's own
   `.noUi-target, .noUi-target * { touch-action: none }`, needed for its
   drag handles) still win and are left completely alone. */
:where(.dh-pwa-standalone) * {
  touch-action: pan-x pan-y;
}

/* Reusable "action in progress" overlay - same visual language as the boot
   splash (#dh-splash, page-template.blade.php's <x-pwa-splash>) but a
   separate element, since that one deletes itself from the DOM the first
   time it hides and can't be shown a second time. Used wherever a
   same-page action has to wait on a real server round trip long enough to
   read as "frozen" otherwise (Pablo, 2026-09-19: Deco Planner's Calculate
   button - "show the splash immediately...the return takes a couple of
   seconds because the plan is calculated in the server"). */
.dh-action-splash {
  display: none; position: fixed; inset: 0; z-index: 99999;
  align-items: center; justify-content: center; background: #0b2a3a;
}
.dh-action-splash.is-visible { display: flex; }
.dh-action-splash img {
  width: 88px; height: 88px; border-radius: 22px;
  animation: dhActionSplashPulse 1.1s ease-in-out infinite;
}
@keyframes dhActionSplashPulse {
  0%, 100% { transform: scale(1); opacity: .82; }
  50% { transform: scale(1.08); opacity: 1; }
}

/* "Chat with us" floating button (2026-09-14). Sits well above the mobile
   tab bar (60px) and the install-prompt bar's own band above that, so the
   three never stack on top of each other; desktop has neither, so it can
   sit lower. */
.dh-chat-fab {
  position: fixed; right: 16px; bottom: calc(140px + env(safe-area-inset-bottom, 0px)); z-index: 1035;
  width: 52px; height: 52px; border-radius: 50%; border: 0; background: var(--dh-sea); color: #fff;
  display: flex; align-items: center; justify-content: center; box-shadow: 0 6px 18px rgba(11,42,58,.28); cursor: pointer;
}
.dh-chat-fab:hover { background: var(--dh-deep); }
.dh-chat-fab .material-icons-round { font-size: 26px; }
@media (min-width: 992px) { .dh-chat-fab { bottom: 24px; } }

/* Admin console: icon-chip channel picker (2026-09-14), New message modal + reply form. */
.dh-channel-picker { display: flex; flex-wrap: wrap; gap: 8px; row-gap: 6px; }
.dh-channel-chip {
  flex: 1 1 0; display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 10px; border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill);
  background: var(--dh-paper); color: var(--dh-muted); font-weight: 700; font-size: .82rem; cursor: pointer;
}
.dh-channel-chip .material-icons-round { font-size: 17px; }
.dh-channel-chip svg { width: 17px; height: 17px; flex: 0 0 auto; }
.dh-channel-chip.is-active { background: var(--dh-ink); border-color: var(--dh-ink); color: #fff; }
.dh-channel-chip:hover:not(.is-active) { border-color: var(--dh-sea); color: var(--dh-sea); }
.dh-channel-chip.is-sms.is-active { background: var(--dh-sea); border-color: var(--dh-sea); }
.dh-channel-chip.is-whatsapp.is-active { background: var(--dh-good); border-color: var(--dh-good); }
.dh-channel-chip.is-email.is-active { background: var(--dh-avg); border-color: var(--dh-avg); }
.dh-channel-chip.is-sms:hover:not(.is-active) { border-color: var(--dh-sea); color: var(--dh-sea); }
.dh-channel-chip.is-whatsapp:hover:not(.is-active) { border-color: var(--dh-good); color: var(--dh-good); }
.dh-channel-chip.is-email:hover:not(.is-active) { border-color: var(--dh-avg); color: var(--dh-avg); }
/* Registered-account-only chip (Multi Level, Pablo, 2026-09-25) - visible
   and clickable (opens the guest sign-up modal), just visually muted so
   it doesn't read as a normal, immediately-usable option. */
.dh-channel-chip.is-locked { background: var(--dh-foam); color: var(--dh-muted); }
.dh-channel-chip.is-locked:hover { border-color: var(--dh-line); color: var(--dh-muted); }

/* Advanced settings gear, next to "Open a dive" (Pablo, 2026-09-25) - a
   round icon button on the light page background, same round-chip
   footprint as .dh-corner-delete but blue (an action, not a delete). */
.dh-gear-btn {
  width: 30px; height: 30px; border-radius: 50%; border: 0; flex: 0 0 auto;
  background: var(--dh-sea); color: #fff; display: inline-flex; align-items: center; justify-content: center;
  padding: 0; cursor: pointer;
}
.dh-gear-btn:hover { background: var(--dh-deep); }
.dh-gear-btn .material-icons-round { font-size: 17px; }

/* Save GF/setpoint pill on the Search dive sites row (Pablo, 2026-09-19:
   "They need to be new pills. Put them at the line with search dive sites
   aligned to the right"). Briefly flashes green/red after a save attempt. */
#saveDecoPrefsPill.is-success { background: var(--dh-good); border-color: var(--dh-good); color: #fff; }
#saveDecoPrefsPill.is-error { background: var(--dh-danger); border-color: var(--dh-danger); color: #fff; }

/* Thread header: "Send registration invite" - one chip per channel that
   actually reaches this contact (SMS+WhatsApp for a phone, Email for an
   address), sized down to fit inline next to the contact's name. */
.dh-thread-invite { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.dh-thread-invite-label { font-size: .72rem; color: var(--dh-muted); font-weight: 700; }
.dh-thread-invite .dh-channel-chip { flex: 0 0 auto; padding: 5px 9px; font-size: .74rem; }
.dh-thread-invite .dh-channel-chip .material-icons-round { font-size: 15px; }
.dh-thread-invite .dh-channel-chip svg { width: 15px; height: 15px; }

/* Best Gases: pill inputs + result pills, slider and input on one row,
   input always BEFORE (to the left of) the slider (Pablo, 2026-09-15 -
   corrected from an initial "right of the slider" pass). Trialled on
   Open Circuit > Nitrox + the shared Max Depth control first - not yet
   applied to the rest of the page (Trimix, CCR, Gas Mix), which still
   use the older right-label-* classes below untouched. */
.dh-gas-label { display: block; font-size: .8rem; font-weight: 700; color: var(--dh-muted); margin-bottom: 6px; }
.dh-gas-row { display: flex; align-items: center; gap: 10px; }
.dh-gas-row .slider-styled { flex: 1 1 auto; min-width: 0; }
.dh-gas-input-wrap { display: flex; align-items: center; gap: 5px; flex: 0 0 auto; }
.dh-gas-unit { font-size: .74rem; color: var(--dh-muted); font-weight: 600; }

/* Every pill (editable input or read-only result) shares one fixed
   height/padding/font-size so they always line up, whichever kind sits
   next to whichever slider (Pablo: "I want all pills to be the same
   height"). */
.dh-gas-input, .dh-gas-result-pill {
  height: 32px; font-family: var(--dh-font); font-weight: 700; font-size: .82rem;
  border-radius: var(--dh-radius-pill);
}

/* Editable pill input - always a white/paper background per Pablo's
   convention ("text inputs are with white background"); only the border
   and text color move through the safe/warn/danger ladder. */
.dh-gas-input {
  width: 66px; text-align: center; background: var(--dh-paper); border: 2px solid var(--dh-line);
  padding: 0 16px 0 6px; color: var(--dh-ink); -moz-appearance: textfield; cursor: text;
}
.dh-gas-input::-webkit-outer-spin-button, .dh-gas-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.dh-gas-input:focus { outline: none; box-shadow: 0 0 0 3px var(--dh-foam); }
.dh-gas-input:hover { filter: brightness(.97); }

/* iOS Safari (including the installed PWA) auto-zooms the page on focus of
   any text input whose computed font-size is under 16px, and never zooms
   back out on its own once the keyboard closes - it isn't scoped to the
   input, so the whole page is left zoomed in until pinched back out by
   hand (Pablo, 2026-09-19: "once the keyboard is shown, the page zooms in
   but never goes back...I only saw this on my iPhone [not sure about
   iPad]"). This is a touch-keyboard behavior, not a narrow-screen one - an
   iPad's viewport is as wide as a laptop's, so a max-width breakpoint would
   miss it there; (hover:none)+(pointer:coarse) targets touch-primary
   devices (phones and tablets) specifically, leaving an actual desktop/
   laptop's pill size untouched. 16px is the documented threshold that
   avoids the zoom entirely. */
@media (hover: none) and (pointer: coarse) {
  .dh-gas-input { font-size: 16px; }
}

/* Pencil icon so the pill reads as "type here", not a static badge - shown
   at rest (works on touch, where there's no hover to rely on) and hidden
   the moment the field actually has focus, since the caret says it now
   (Pablo, 2026-09-15: "how can we make it evident... they can type a
   number"). Absolutely positioned over the input's own right padding
   rather than a flex sibling, so the existing safe/warn/danger classList
   toggle (already targeting the input directly) didn't need to move. */
.dh-gas-editable { position: relative; display: inline-flex; }
.dh-gas-edit-icon {
  position: absolute; right: 5px; top: 50%; transform: translateY(-50%);
  font-size: 12px; color: var(--dh-muted); opacity: .65; pointer-events: none;
}
.dh-gas-input:focus + .dh-gas-edit-icon { opacity: 0; }
.dh-gas-input.is-safe { border-color: var(--dh-sea); color: var(--dh-sea); }
.dh-gas-input.is-safe:focus { border-color: var(--dh-sea); }
.dh-gas-input.is-warn { border-color: var(--dh-warn); color: var(--dh-warn); }
.dh-gas-input.is-warn:focus { border-color: var(--dh-warn); }
.dh-gas-input.is-danger { border-color: var(--dh-danger); color: var(--dh-danger); }
.dh-gas-input.is-danger:focus { border-color: var(--dh-danger); }

/* Read-only result pill - the OTHER half of the convention ("labels
   showing results of calculations are with colored background"): solid
   fill, white text. Green when the result is the ideal value for this
   depth, theme blue otherwise - never red/orange, since this isn't a
   safety threshold, just "matches the calculated best mix or not". */
.dh-gas-result-pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  padding: 0 16px; color: #fff; background: var(--dh-sea); vertical-align: middle;
}
.dh-gas-result-pill.is-ideal { background: var(--dh-good); }

/* Small delta badge sitting on a pill's corner (Deco Planner's "What if"
   new run/deco time vs baseline) instead of a second free-floating pill -
   red for worse, green for better, grey "-" when there's no change. */
/* Left margin keeps room for a 3-digit result (e.g. "123") without it
   crowding the label to its left in the What-if summary table (Pablo,
   2026-09-17: "3 digit numbers overlap with the text to the left"). */
.dh-gas-pill-wrap { position: relative; display: inline-flex; margin: 0 10px 0 10px; }
.dh-gas-pill-badge {
  position: absolute; top: -7px; right: -8px; min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: var(--dh-radius-pill); font-size: .62rem; font-weight: 800; color: #fff;
  display: flex; align-items: center; justify-content: center; line-height: 1;
  background: var(--dh-muted); border: 2px solid var(--dh-paper);
}
.dh-gas-pill-badge.is-danger { background: var(--dh-danger); }
.dh-gas-pill-badge.is-ideal { background: var(--dh-good); }

/* Some result pills (Gas Density) aren't "ideal vs not" - they're a real
   safety reading, so they use the same warn/danger ladder as the
   editable inputs, just as a fill instead of a border. */
.dh-gas-result-pill.is-warn { background: var(--dh-warn); }
.dh-gas-result-pill.is-danger { background: var(--dh-danger); }

/* Eye toggle inside the "Gas allows..." pill - overlays that scenario's
   own profile on the chart (Pablo, 2026-09-26). Translucent white circle
   at rest so it reads as part of the pill, solid white with a dark icon
   once active so the on/off state is obvious at a glance. */
.dh-gas-limit-eye-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; margin-left: 4px; padding: 0; border: none;
  border-radius: 50%; background: rgba(255,255,255,.25); color: #fff; cursor: pointer;
  flex: 0 0 auto;
}
.dh-gas-limit-eye-btn .material-icons-round { font-size: 14px; }
.dh-gas-limit-eye-btn:hover { background: rgba(255,255,255,.4); }
.dh-gas-limit-eye-btn.is-active { background: #fff; color: var(--dh-ink); }

/* Gas symbol tag baked into the pill itself instead of a separate caption
   underneath (Pablo, 2026-09-15: "remove the O2 % content label... add O2
   in the Nitrox result pill") - generated content, never part of the
   element's real textContent, so every existing calculation that reads
   #bestNitrox/#txbestNitrox/#txbestHe via .textContent keeps working
   completely unchanged. */
.dh-gas-result-pill.is-o2::before { content: "O\2082"; opacity: .75; font-weight: 800; font-size: .68rem; }
.dh-gas-result-pill.is-he::before { content: "He"; opacity: .75; font-weight: 800; font-size: .68rem; }
/* O2 = green, He = blue everywhere a split pill shows both side by side
   (Pablo, 2026-09-16) - same mapping the tank-mix legend (is-mix-o2/
   is-mix-he) already used, just extended to the plain is-o2/is-he pills. */
.dh-gas-result-pill.is-o2 { background: var(--dh-good); }
.dh-gas-result-pill.is-he { background: var(--dh-sea); }
/* "Ideal" (matches best mix) still wins over the O2 color mapping above -
   both are single-class selectors so declaration order would otherwise
   decide it; this two-class selector outranks either on its own. He stays
   its own blue regardless of is-ideal (Pablo, 2026-09-24: "the split pill
   for He...is not blue, it's green...it needs to be blue") - is-ideal
   marking a match makes sense for O2 (the number the diver is dialing in)
   but not for He, which isn't a "good/bad" target the same way. */
.dh-gas-result-pill.is-o2.is-ideal { background: var(--dh-good); }

/* Pure air (21/0) and pure O2 (100/0) show a text label ("Air"/"Pure O2")
   instead of the plain O2% - Air gets its own neutral grey, Pure O2 keeps
   the normal green is-o2 background. The ::before "O2"/::after "%" content
   suppression these need lives further down (see is-gas-label near the
   ::before/::after rules themselves) - a bare .dh-gas-result-pill.is-gas-label
   selector here loses to .dh-gas-split-pill .dh-gas-result-pill.is-o2::after's
   higher specificity below, which is exactly the "Air%" bug this replaced
   (Pablo, 2026-09-26: "it should be just 'Air'"). */
.dh-gas-result-pill.is-air { background: var(--dh-muted); }

/* Gas density: a calculation result like the others, but a supporting
   figure rather than the headline the split pill above it is - smaller,
   with its unit baked in the same way (Pablo, 2026-09-15: "put g/L
   inside the pill after the number"). */
.dh-gas-result-pill.is-compact { height: 24px; padding: 0 10px; font-size: .72rem; }
.dh-gas-result-pill.is-density::after { content: " g/L"; opacity: .8; font-weight: 600; font-size: .66rem; }

/* Gas density moved onto the same line as the split pill; its caption
   sits directly under the density pill only, not centered across the
   whole row (Pablo, 2026-09-15: "the gas density legend NEEDS to be
   right under and centered with the gas density result"). */
.dh-gas-split-pill-row { display: inline-flex; align-items: center; gap: 8px; }
.dh-gas-density-col { display: flex; flex-direction: column; align-items: center; }
.dh-gas-density-caption { margin-top: -3px; font-size: .68rem; font-weight: 600; color: var(--dh-muted); line-height: 1; }

/* Tank card's Gas Mix legend - the actual final blend, distinct from
   the calculators' own safe/ideal color logic, so its own dedicated tag
   classes rather than reusing is-o2/is-he (which are already dynamic
   elsewhere). Fixed colors matching what Oxygen/Helium/Nitrogen used to
   be shown in before (green/blue/grey) - a 2-way split for Nitrox (no
   Helium), 3-way for Trimix (Pablo, 2026-09-15). */
.dh-gas-result-pill.is-mix-o2::before { content: "O\2082"; opacity: .75; font-weight: 800; font-size: .62rem; }
.dh-gas-result-pill.is-mix-he::before { content: "He"; opacity: .75; font-weight: 800; font-size: .62rem; }
.dh-gas-result-pill.is-mix-n2::before { content: "N\2082"; opacity: .75; font-weight: 800; font-size: .62rem; }
.dh-gas-result-pill.is-mix-o2 { background: var(--dh-good); }
.dh-gas-result-pill.is-mix-he { background: var(--dh-sea); }
.dh-gas-result-pill.is-mix-n2 { background: var(--dh-muted); }

/* Tank card: graphic on the left, Gas Price (now the same tap-to-open
   <details> card the Weather page's Live Webcam uses, .dh-wx-more) and
   the NDL result on the right (Pablo, 2026-09-15: "align the tank
   graphs to the left... to the right of the tanks have the collapsable
   Gas Price... use the kind of card... like Live Webcam"). The "pull up"
   nudge (the graphic's own asset has transparent padding baked in above
   it) is scoped to the graphic column alone, NOT the whole row - Gas
   Price needs to start level with "PPO2 at max depth" in the calculator
   column beside it, so it stays at this row's natural top. The image
   itself is centered within its column via margin:auto on its own
   wrapper (below) rather than a fixed width on .dh-gas-tank-graphic, so
   the (usually wider) split pill underneath centers against the SAME
   width instead of overflowing past a column sized only to the narrow
   tank image. Extra left padding on the price/NDL side specifically -
   the tank artwork renders at 150% of its own box (width:150% in the
   markup), so it visually overflows past the plain column gap. */
.dh-gas-tank-layout { display: flex; gap: var(--dh-space-4); align-items: flex-start; padding-left: var(--dh-space-4); }
.dh-gas-tank-graphic { flex: 0 0 auto; text-align: center; margin-top: -44px; }
/* Site Details' OC and CC used two different per-element hacks here (a
   -44px margin on .dh-gas-tank-graphic for OC, a -42px margin on just
   .dh-gas-tank-img-wrap for CC, plus a mobile-only padding-top on
   #oc-tank-col) to line the tank art up with .dh-gas-tank-side and clear
   the content above each column. Consolidated into one shared rule on
   .dh-gas-tank-layout itself, scoped to these two ids so Best Gases'
   own use of the shared classes above (a different, larger tank size)
   is untouched (Pablo, 2026-09-24: "all dh-gas-tank-layout [should] have
   the same padding top... more than the current OC[-44]... less than the
   current CC[-42]"). */
#oc-tank-col .dh-gas-tank-layout,
#cc-tank-col .dh-gas-tank-layout {
  margin-top: -43px;
}
/* -43px on the layout alone isn't enough on its own: it shifts
   .dh-gas-tank-side up by the same amount as the graphic, so the two stay
   42px apart just like before (the tank art's own image sits 42px into a
   168px-tall wrap that's 75% image/25% blank on top) - the graphic still
   needs its own extra pull-up to close that gap and land level with
   .dh-gas-tank-side (both are now uniform between OC and CC, unlike the
   graphic-vs-wrap split this used to need). */
#oc-tank-col .dh-gas-tank-graphic,
#cc-tank-col .dh-gas-tank-graphic {
  margin-top: -42px;
}
/* Between the two shifts above, the tank art moves up 85px total (43+42) -
   comfortably clear of whatever's beside it on desktop, but below the md
   breakpoint both columns drop under the Calculate Best Nitrox/Trimix/
   Diluent row instead, so that same 85px pull-up now reaches up into it.
   Cancel it back out and add real breathing room, same fix as OC needed
   on its own before this was unified (Pablo, 2026-09-24). */
@media (max-width: 767.98px) {
  #oc-tank-col, #cc-tank-col { padding-top: 97px; }
}
.dh-gas-tank-img-wrap { margin: 0 auto; }
.dh-gas-tank-side { flex: 1 1 auto; min-width: 0; padding-left: var(--dh-space-3); }
.dh-gas-tank-side .dh-wx-more { margin-top: 0; }

/* Gas Price table rows: Bootstrap's own .table padding reads as too
   airy for a handful of two-column price rows (Pablo, 2026-09-15: "too
   much interline space"). */
.dh-gas-tank-side .dh-wx-more-body { padding-bottom: 8px; }
.dh-gas-tank-side .dh-wx-more-body td { padding: 2px 0 !important; }

/* Closest standard mix: its own block below the three price rows, not a
   4th table row (Pablo, 2026-09-15: "separate from the Gas price table
   ... put it below the table"), one pill carrying the whole legend via
   generated content rather than a separate label + value. */
.dh-gas-closemix { margin-top: 12px; }
.dh-gas-result-pill.is-closemix::before { content: "Closest standard mix "; }

/* "Calculate Best Nitrox/Trimix" shares its row with "Calculate NDL"
   when the latter is visible (Pablo: "make it share the same line") -
   the single NDL button is physically moved into whichever row is
   active by dhSelectGasFuel(). Plain flexbox handles both of Pablo's
   cases for free: two flex-fill buttons split the row evenly, and
   since a display:none NDL button (depth > 130ft) doesn't participate
   in flex sizing at all, the remaining button already stretches to the
   full row width with no extra rule needed. Extra top margin so the
   row doesn't crowd the result pill sitting right above it. */
.dh-gas-btn-row { display: flex; gap: 8px; margin-top: 10px; }

/* NDL result: same card frame as Gas Price (Pablo, 2026-09-15: "use the
   same frame format you used for Gas price to show the NDL results") -
   .dh-wx-more as a plain div here rather than a <details>, since it's
   already conditionally shown/hidden by the Calculate NDL button itself
   and doesn't need its own separate expand/collapse on top of that.
   .dh-wx-more-body's own padding assumes a <summary> supplied the top
   inset, so this gets its own instead. Flowing, centered text with the
   two values as their own pills ("<x ft> and <y m> are pills with blue
   bg color"), the minutes pill color-coded by how much no-deco time is
   actually left (blue > 20, orange 10-20, red < 10 - same fill
   convention as every other result pill on the page) - "Always use a
   dive computer" now lives in the same card instead of duplicated
   under each calculator's own button. */
.dh-gas-ndl-body { padding: 14px 15px; }
.dh-gas-ndl-result { font-size: .82rem; color: var(--dh-ink); line-height: 1.8; text-align: center; }
.dh-gas-ndl-sub { text-align: center; font-size: .68rem; font-weight: 600; color: var(--dh-muted); margin-top: 6px; }
.dh-gas-ndl-result .dh-gas-result-pill { margin: 0 2px; }
.dh-gas-result-pill.is-ndl::after { content: " m"; }

/* Trimix's O2-narcotic toggle, restyled as a compact switch instead of a
   plain Bootstrap checkbox (Pablo, 2026-09-15: "I don't like the O2
   narcotic? toggle... make it more sleek"). The real <input type=
   checkbox> is visually hidden but still there for click/keyboard/
   screen-reader behavior - JS keeps reading O2Narcotic.checked exactly
   as before, nothing about the toggle's logic changed. */
/* A label row that also carries a small auxiliary control (Pablo,
   2026-09-15: "Count O2 as narcotic... is a param to that calculation" -
   put it in line with the "END at max depth" label it feeds, not off in
   its own row next to Gas density). */
.dh-gas-label-row { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; margin-bottom: 6px; }

/* Open Circuit/Closed Circuit and Nitrox/Trimix pickers - real <button>
   chips (Pablo, 2026-09-15: clicking the chip anywhere used to miss when
   not directly over the text - a real form control's whole box is always
   the click target, unlike the <a>/nav-pills markup this replaced), sized
   to their own label rather than stretched to fill the row ("the style
   of the site is not BIG pills... they don't need to cover all the
   width"). */
.dh-gas-picker { justify-content: flex-start; margin-bottom: 10px; }
.dh-gas-picker .dh-channel-chip { flex: 0 0 auto; padding: 3px 12px; font-size: .76rem; }

/* Search dive sites / Save GFs / the selected-site result pill, all forced
   to the exact same box regardless of their different base components (a
   button vs a <label> result pill) - matches the Open Circuit/Close Circuit
   CCR chips above them pixel-for-pixel instead of each keeping its own
   family's padding math (Pablo, 2026-09-19: "make them all with that font
   and the pill height to be the same for all these"). Height is the real
   measured render of .dh-gas-picker .dh-channel-chip, not a guess. Also
   applied to the Decompression plan card's Export PDF/Save Plan buttons
   (Pablo, 2026-09-19: "make these pills the same height and font size as
   the ones in the input card for Close Circuit CCR and Open Circuit") -
   only sizing here, so each keeps its own component's colors. */
.dh-channel-chip.dh-deco-searchrow-pill,
.dh-gas-result-pill.dh-deco-searchrow-pill,
.dh-deco-header-btn.dh-deco-searchrow-pill {
  height: 27px; padding: 0 12px; font-size: .76rem; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}

/* "Search dive sites" and its result now share one button instead of a
   button plus a separate variable-length pill next to it - the button
   itself switches to the colored result-pill look once a site is picked
   (Pablo, 2026-09-19: "replace the pill Search a dive with the result...
   save space in the screen. That will also...prevent the save GFs pill to
   overflow and have no row misalignment"). ID-scoped so it outranks
   .dh-channel-chip's plain white/bordered look regardless of source order. */
#dropdownMenuButton.dh-site-selected {
  background: var(--dh-sea); border-color: var(--dh-sea); color: #fff;
}
#dropdownMenuButton.dh-site-selected:hover { background: var(--dh-sea); color: #fff; }
.dh-gas-toggle { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; margin: 0; }
.dh-gas-toggle input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.dh-gas-toggle-track {
  width: 26px; height: 14px; border-radius: var(--dh-radius-pill); background: var(--dh-line);
  position: relative; flex: 0 0 auto; transition: background .15s ease;
}
.dh-gas-toggle-thumb {
  position: absolute; top: 2px; left: 2px; width: 10px; height: 10px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 2px rgba(11,42,58,.3); transition: transform .15s ease;
}
.dh-gas-toggle input:checked + .dh-gas-toggle-track { background: var(--dh-sea); }
.dh-gas-toggle input:checked + .dh-gas-toggle-track .dh-gas-toggle-thumb { transform: translateX(12px); }
.dh-gas-toggle input:focus-visible + .dh-gas-toggle-track { box-shadow: 0 0 0 2px var(--dh-foam); }
.dh-gas-toggle-label { font-size: .72rem; font-weight: 600; color: var(--dh-ink); display: inline-flex; align-items: center; gap: 2px; }
.dh-gas-info { font-size: 13px; color: var(--dh-muted); cursor: help; }

/* "Calculate Best..." buttons: a real block on clicks once the mix already
   shown IS the best one, not just a grey color (Pablo, 2026-09-15: "I
   would disable the Calculate button, not just put them in grey"). Kept
   as a class + pointer-events rather than the native `disabled` attribute
   so the depth slider's own programmatic .click() (recalculating this tab
   when Set Max Depth changes) still fires even while this looks solved. */
.btn.is-solved { opacity: .55; pointer-events: none; cursor: not-allowed; }

/* Trimix's O2/He result, together above "Calculate Best Trimix" instead of
   separately under each slider (Pablo, 2026-09-15: "I would like to see
   them right above the button... in a split pill"). Two independently-
   colored halves of one pill shape - O2 and He are solved independently,
   so one can be green while the other is still blue. The "O2"/"He" tag
   and the trailing "%" are both generated content (::before/::after),
   never part of the element's real textContent - the same two spans
   (#txbestNitrox/#txbestHe) still get their numeric value written to
   .textContent exactly as before, untouched, so every existing
   calculation that reads them (updateGasMix, gas density, END) keeps
   working with no JS changes beyond the ones already made. */
/* vertical-align:middle because this is an inline-flex box sitting inline
   next to plain text (a table cell's other columns, a chip's label) -
   without it, its default "baseline" alignment reads as visibly shifted up
   or down from that text (Pablo, 2026-09-19, a recurring complaint: "the
   gas split pills are not aligned middle vertically within the wrapper"). */
.dh-gas-split-pill { display: inline-flex; vertical-align: middle; }
.dh-gas-split-pill .dh-gas-result-pill:first-child { border-radius: var(--dh-radius-pill) 0 0 var(--dh-radius-pill); }
.dh-gas-split-pill .dh-gas-result-pill:last-child { border-radius: 0 var(--dh-radius-pill) var(--dh-radius-pill) 0; box-shadow: inset 1px 0 0 rgba(255,255,255,.4); }
/* A middle segment (the He third of a 3-way split) is neither first nor
   last, so it falls square between the two rounded ends (Pablo,
   2026-09-15: "make it with no radius so it looks square in between") -
   a 2-way split (Nitrox, or the Trimix O2/He result pill) has no middle
   child at all, so this never applies there. */
.dh-gas-split-pill .dh-gas-result-pill:not(:first-child):not(:last-child) { border-radius: 0; box-shadow: inset 1px 0 0 rgba(255,255,255,.4); }
/* Trimix's raw .textContent has no "%" (unlike Nitrox's, which appends
   its own) - only here does the pill need one generated for display. */
.dh-gas-split-pill .dh-gas-result-pill.is-o2::after, .dh-gas-split-pill .dh-gas-result-pill.is-he::after { content: "%"; }
/* "Air"/"Pure O2" text labels (is-gas-label, see is-air above) need to beat
   the same-specificity "%" rule directly above - the label text already
   says everything, so "Air%"/"Pure O2%" would be wrong (Pablo, 2026-09-26:
   "it should be just 'Air'"). Matches that selector's own specificity
   (ancestor + 2 classes) and comes after it, so it wins the tie. */
.dh-gas-split-pill .dh-gas-result-pill.is-gas-label::before,
.dh-gas-split-pill .dh-gas-result-pill.is-gas-label::after {
  content: none;
}
/* No He in the mix (Nitrox, not Trimix) - hide its half of the split pill
   and let the O2 half read as one normal, fully-rounded pill instead of
   half a pair (Pablo, 2026-09-16). The He pill keeps `hidden` (still
   first/last-child in the DOM), so this needs its own override rather
   than relying on :first-child/:last-child, which don't know about it. */
.dh-gas-split-pill.is-solo .dh-gas-result-pill { border-radius: var(--dh-radius-pill); box-shadow: none; }

/* Hypoxic-at-surface warning: was a separate "Hypoxic at surface" text
   legend above the split pill - now a small red badge over the O2 pill's
   corner instead (Pablo, 2026-09-24). The wrap wouldn't be needed but for
   this: .dh-gas-split-pill's own :first-child/:last-child rules (above)
   require the O2/He pills to actually BE the first/last child, so the
   badge is a sibling of .dh-gas-split-pill, not a third child inside it. */
.dh-gas-o2-badge-wrap { position: relative; display: inline-flex; vertical-align: middle; }
.dh-gas-hypoxic-badge {
  position: absolute; top: -6px; left: -6px;
  width: 18px; height: 18px; border-radius: 50%;
  background: var(--dh-danger); color: #fff;
  align-items: center; justify-content: center;
  box-shadow: 0 0 0 2px #fff;
}
.dh-gas-hypoxic-badge .material-icons-round { font-size: 12px; }

/* Slider fill/handle in the theme's blue instead of Material Dashboard's
   default purple (Pablo: "slider colors should follow theme") - applies
   to every slider using this shared class across DivePlanner, GasPlanning
   ("Best gases") and SiteDetails' own Best Gases section alike, since
   it's a pure color swap with no layout risk. Handle stays a clearly
   white circle at rest (Pablo, 2026-09-25: "mine [the SAC slider] have a
   white color, yours are all the same theme blue") and turns a lighter
   blue - not darker - while hovered or actively dragged ("they also
   change to a lighter blue when you hold them"). */
.slider-styled.noUi-target { background-color: var(--dh-line); }
.slider-styled .noUi-connect { background: var(--dh-sea); }
/* .slider-styled.noUi-horizontal (both classes land on the same element -
   ours from the markup, noUi-horizontal added by the JS lib), not just
   .slider-styled, to unambiguously outrank material-dashboard.css's own
   .noUi-horizontal .noUi-handle sizing rule. Kept at the original 14px
   size (Pablo, 2026-09-25: "the handles are also bigger now, I don't
   like this...revert to the smaller handles"). Solid theme blue fill,
   not white - matching native accent-color range inputs turned out to
   render inconsistently across browsers, so a plain solid-color handle
   is the reliable choice (Pablo: "change the color of the handle to
   blue?"). Lighter blue, not darker, while hovered/dragged. */
.slider-styled.noUi-horizontal .noUi-handle {
  background-color: var(--dh-sea); border: 1px solid var(--dh-sea);
}
.slider-styled.noUi-horizontal .noUi-handle:hover,
.slider-styled.noUi-horizontal .noUi-handle.noUi-active {
  background-color: var(--dh-shallow); border-color: var(--dh-shallow);
}
/* noUiSlider's own default "grip" stripes (two thin grey vertical lines
   baked into every handle via nouislider.css) - removed on every themed
   slider in the app, not just Tanks (Pablo, 2026-09-26: "I noticed all
   the sliders have like a double vertical grey line in the handle...get
   rid of them EVERYWHERE"). */
.slider-styled.noUi-horizontal .noUi-handle:before,
.slider-styled.noUi-horizontal .noUi-handle:after {
  display: none;
}

/* Tanks card (Pablo, 2026-09-26) - the first dual-handle slider in this
   file: a reserve handle (lower, red - gas below this point doesn't count
   as usable) and a fill handle (upper, blue - how much is actually in the
   tank). Three connect segments come out of noUiSlider in DOM order -
   :nth-child(1) is [0, reserve], :nth-child(2) is [reserve, fill], the
   third (untouched, stays --dh-line) is [fill, max] - unfilled capacity. */
.dh-tank-slider.noUi-horizontal .noUi-connects .noUi-connect:nth-child(1) { background: var(--dh-danger); }
.dh-tank-slider.noUi-horizontal .noUi-connects .noUi-connect:nth-child(2) { background: var(--dh-sea); }
.dh-tank-slider.noUi-horizontal .noUi-handle-lower { background-color: var(--dh-danger); border-color: var(--dh-danger); }
.dh-tank-slider.noUi-horizontal .noUi-handle-lower:hover,
.dh-tank-slider.noUi-horizontal .noUi-handle-lower.noUi-active { background-color: #c9564c; border-color: #c9564c; }
.dh-tank-slider.noUi-horizontal .noUi-handle-upper { background-color: var(--dh-sea); border-color: var(--dh-sea); }
.dh-tank-slider.noUi-horizontal .noUi-handle-upper:hover,
.dh-tank-slider.noUi-horizontal .noUi-handle-upper.noUi-active { background-color: var(--dh-shallow); border-color: var(--dh-shallow); }

/* A small triangle under the track marking the tank type's own rated
   capacity (e.g. 3000 PSI for an AL cylinder) - "a small triangle pointing
   to that point but slightly below the slider (just touching it)"
   (Pablo, 2026-09-26). Positioned in JS via dhUpdateTankCapacityMarker()
   (left: X%), not CSS, since the position depends on the selected tank
   type and the unit-aware max. border-bottom draws the triangle pointing
   up (apex touching the slider's own bottom edge); translateX(-50%)
   centers the apex on the computed left%, rather than using it as the
   triangle's own left edge. */
.dh-tank-slider-wrap { position: relative; padding: 0 7px; }
.dh-tank-capacity-marker {
  position: absolute; top: 100%; left: 0; width: 0; height: 0;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-bottom: 6px solid var(--dh-ink); opacity: .6; pointer-events: none; z-index: 1;
  transform: translateX(-50%);
}
/* Reserve/Fill are editable text boxes now, not plain read-only spans
   (Pablo, 2026-09-26: "make the reserve and fill editable...similar to
   what you did in the sac") - a wider .dh-gas-input than the 66px default,
   since PSI runs to 4 digits where a gas % never does. Reserve sits at the
   start and Fill at the end of the row (space-between), each lined up
   with its own slider handle underneath ("align to the end of the slider
   the Fill textbox"); reserve's own textbox is themed red to match its
   handle/connect-segment color ("I like the reserve in red...make the
   text in the textbox for reserve in red"). */
.dh-tank-readout { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; padding: 0 7px; }
.dh-tank-readout-start, .dh-tank-readout-end { display: flex; align-items: center; gap: 4px; }
.dh-tank-editable .dh-gas-input { width: 76px; }
.dh-tank-reserve-editable .dh-gas-input { color: var(--dh-danger); font-weight: 700; }
.dh-tank-unit-a, .dh-tank-unit-b { color: var(--dh-muted); font-weight: 600; }
/* Nominal volume readout under the Type dropdown - CUFT, or liters in
   metric, doubled when Twins is checked (Pablo, 2026-09-26). */
.dh-tank-volume-label { margin-top: 2px; }

/* Every cell in the Tanks table centers vertically - rows mix a two-line
   Type+select, a one-line Gas pill, and a two-line Reserve/Fill control,
   which look mismatched top-aligned (Pablo, 2026-09-26: "get all
   vertically aligned middle"). */
#dhTanksTable > tbody > tr > td { vertical-align: middle; }

/* Type dropdown - "some theme style" instead of the bare Bootstrap
   .form-select default (Pablo, 2026-09-26). appearance:none + a hand-drawn
   chevron since native select arrows can't take the theme color directly. */
.dh-tank-type-select {
  border: 1px solid var(--dh-line); border-radius: 10px; color: var(--dh-ink);
  background-color: #fff; font-weight: 600; font-size: .85rem;
  -webkit-appearance: none; -moz-appearance: none; appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%235a6b78' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center; padding-right: 28px;
}
.dh-tank-type-select:focus { outline: none; border-color: var(--dh-sea); box-shadow: 0 0 0 3px rgba(14,124,158,.15); }
.dh-tank-type-select:hover { border-color: var(--dh-sea); }

/* Twins - a plain checkbox in its own column now, not a labeled switch
   under the Type select (Pablo, 2026-09-26: "change the toggle to a
   checkbox for twin...an additional column for twin so to make it all
   align") - every row gets the column, only the bottom-gas row gets a
   checkbox in it, so the grid still lines up either way. */
.dh-tank-twins-check { width: 18px; height: 18px; cursor: pointer; }

/* Mobile-only captions for the two controls that have no self-evident
   label once the column headers are hidden below (a bare checkbox, and a
   number that could otherwise be mistaken for the nominal-volume figure
   next to it) - paired with the flex-reorder media query right after,
   both keyed to the same md breakpoint so captions and layout change
   together. */
.dh-tank-mobile-label { display: block; font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--dh-muted); margin-bottom: 3px; }

/* Mobile: each tank becomes a two-line "card" instead of a cramped
   6-column row - Type/Twins/Available gas/SAC on top, the gas pill and
   Reserve/Fill slider below (Pablo, 2026-09-26: "bleed into two rows per
   row...keep type, twins, available gas and SAC in the top row, then put
   the slider with gas and reserve/fill below...light grey separators
   between gases"). A <tr> set to flex-wrap can reorder its own <td>
   children via `order` regardless of source order - column 1/2/5/6 move
   up via order, letting 3 (Gas) and 4 (Reserve/Fill) wrap onto their own
   line for free once the first four already fill the row (their
   flex-basis sums to 100%, same for the second line's two). 767.98px
   matches Bootstrap's own md breakpoint (the .d-md-none captions above),
   not this file's other 768px convention, so the two stay in lockstep. */
@media (max-width: 767.98px) {
  #dhTanksTable, #dhTanksTable tbody { display: block; width: 100%; }
  #dhTanksTable tbody tr[data-tank-slot] {
    display: flex; flex-wrap: wrap; align-items: flex-start;
    padding: 12px 0; border-bottom: 1px solid var(--dh-line);
  }
  #dhTanksTable tbody tr[data-tank-slot]:last-child { border-bottom: none; }
  /* min-width: 0 overrides flex items' default min-width: auto, which
     otherwise sizes each <td> to its content's min-content width (a
     select, a slider, two number inputs) regardless of flex-basis -
     without it, SAC/Reserve-Fill's own natural widths were wider than
     their allotted share and forced an extra wrap instead of landing on
     the intended line. */
  #dhTanksTable td { display: block; padding: 4px 6px; border: none !important; min-width: 0; }

  .dh-tank-col-type        { order: 1; flex: 0 0 38%; }
  .dh-tank-col-twins       { order: 2; flex: 0 0 14%; }
  .dh-tank-col-available   { order: 3; flex: 0 0 22%; }
  .dh-tank-col-sac         { order: 4; flex: 0 0 26%; }
  .dh-tank-col-gas         { order: 5; flex: 0 0 34%; margin-top: 8px; }
  .dh-tank-col-reservefill { order: 6; flex: 1 1 66%; margin-top: 8px; }
}

/* Twins checkbox centered in its column on every viewport (Pablo,
   2026-09-26); Gas column's role label + pill lean toward the Reserve/Fill
   slider they describe rather than the far edge of their own column, on
   mobile that slider sits immediately to the right on the same line
   ("the gas title...aligned to the right of the col"). */
.dh-tank-col-twins { text-align: center; }
.dh-tank-col-gas { text-align: right; }

/* Deco Planner gas selector, v2: a vertical accordion instead of horizontal
   tabs (Pablo, 2026-09-16: tabs "go out of screen" with 4 gases and aren't
   "intuitive or efficient" - picked this over a two-pane layout or carousel
   for lowest risk and because it reuses the collapsible-header language
   already used for Inputs/What-if/Gas consumption on this same page). Each
   gas is one item; tapping its header opens that gas's tank+sliders and
   closes whichever was open, so exactly one gas is ever full width at a
   time - same one-at-a-time intent the tabs had, just stacked instead of
   packed side by side, so it can never overflow no matter how many gases
   exist or how long their "(32% O2 / 45% He)" label gets. */
.dh-gas-accordion { display: flex; flex-direction: column; gap: 10px; }
.dh-gas-accordion-item { border: 1px solid var(--dh-line); border-radius: 12px; overflow: hidden; }
.dh-gas-accordion-head {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 12px 16px; border: 0;
  cursor: pointer; user-select: none; background: var(--dh-paper); color: var(--dh-ink);
  font-family: var(--dh-font); font-weight: 700; font-size: .88rem; text-align: left;
}
.dh-gas-accordion-head:hover { background: var(--dh-foam); }
.dh-gas-accordion-head.is-active { background: var(--dh-ink); color: #fff; }
.dh-gas-accordion-head .material-icons-round { opacity: .8; flex: 0 0 auto; }
.dh-gas-accordion-head-title { flex: 1 1 auto; }
.dh-gas-accordion-chevron { flex: 0 0 auto; transition: transform .15s; }
.dh-gas-accordion-head.is-active .dh-gas-accordion-chevron { transform: rotate(180deg); }
.dh-gas-accordion-body { padding: 16px; border-top: 1px solid var(--dh-line); background: var(--dh-paper); }
.dh-gas-accordion-add {
  display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%;
  padding: 12px 16px; border: 1px dashed var(--dh-line); border-radius: 12px; background: none;
  color: var(--dh-sea); font-family: var(--dh-font); font-weight: 700; font-size: .85rem; cursor: pointer;
}
.dh-gas-accordion-add:hover { background: var(--dh-foam); }
.dh-gas-accordion-add .material-icons-round { font-size: 18px; }

/* Small round icon button - saving GF/setpoint to the profile, and saving
   a gas card's current mix as a custom gas (Pablo, 2026-09-18). Neutral at
   rest; briefly turns green/red after a save attempt via .is-success /
   .is-error (JS toggles the class and swaps the icon glyph for ~1.5s). */
.dh-btn-icon {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 30px; height: 30px; border-radius: 50%; border: none; cursor: pointer;
  background: rgba(255,255,255,.15); color: #fff;
}
.dh-btn-icon:hover { background: rgba(255,255,255,.3); }
.dh-btn-icon .material-icons-round { font-size: 18px; }
.dh-btn-icon.is-success { background: var(--dh-good); color: #fff; }
.dh-btn-icon.is-error { background: var(--dh-danger); color: #fff; }
/* Same accent as the "What if...?" bubble on this same chart card (Pablo,
   2026-09-25: "use the same bg color as the what if...? bubble") - the
   collapse-the-deco-table toggle. */
.dh-btn-icon-accent { background: var(--dh-sea); color: #fff; }
.dh-btn-icon-accent:hover { background: var(--dh-deep); }
/* Same icon button, but living on a light card body instead of the dark
   Inputs header - the gas cards' own save-this-gas button. */
.dh-gas-preset-row .dh-btn-icon { background: var(--dh-paper); color: var(--dh-muted); border: 1px solid var(--dh-line); }
.dh-gas-preset-row .dh-btn-icon:hover { color: var(--dh-ink); border-color: var(--dh-ink); }
.dh-gas-preset-row .dh-btn-icon.is-success { background: var(--dh-good); color: #fff; border-color: var(--dh-good); }
.dh-gas-preset-row .dh-btn-icon.is-error { background: var(--dh-danger); color: #fff; border-color: var(--dh-danger); }
.dh-gas-btn-row { align-items: center; }
/* Deco Planner shortcut next to Calculate Best Nitrox/Trimix/Diluent
   (Pablo, 2026-09-24: replaced the full-width "Decompression planning"
   button with a small icon-only button, same material-icons-round "timer"
   glyph the nav menu/header use for Deco Planner, + tooltip). A real .btn
   like its col-11 sibling, sized to the row via g-2/align-items rather
   than the round .dh-btn-icon used elsewhere on this card. Uses .btn-info
   for its color (blue, matching all the Calculate buttons - Pablo,
   2026-09-24: "make them blue") rather than a custom background here. */
.dh-gas-deco-btn {
  padding-left: 0; padding-right: 0;
}
.dh-gas-deco-btn .material-icons-round {
  /* Under the button's own 17.4px line-height (12px font x 1.45) so the
     icon's line box doesn't force this button taller than its col-11
     sibling (Pablo, 2026-09-24: "same height...perfectly aligned"). */
  font-size: 15px;
  line-height: 1;
  vertical-align: middle;
}
/* "My Gases" reuses the standard preset chip look but pinned to the far
   right of its row, since it opens a picker rather than setting a value
   directly like its siblings. */
.dh-gas-mygases-chip { margin-left: auto; }

/* "My Gases" picker modal: one row per saved gas - the mix itself (click to
   apply) plus a small delete button, same is-o2/is-he pill styling as the
   rest of the app so a saved "21/35" reads the same everywhere. */
.dh-mygases-row { display: flex; align-items: center; gap: 10px; padding: 8px 4px; border-bottom: 1px solid var(--dh-line); }
.dh-mygases-row:last-child { border-bottom: none; }
.dh-mygases-pick { flex: 1 1 auto; display: flex; align-items: center; gap: 8px; background: none; border: none; padding: 4px; cursor: pointer; text-align: left; }
.dh-mygases-pick:hover .dh-gas-result-pill { filter: brightness(1.08); }
.dh-mygases-delete { flex: 0 0 auto; background: none; border: none; color: var(--dh-muted); cursor: pointer; padding: 4px; }
.dh-mygases-delete:hover { color: var(--dh-danger); }
.dh-mygases-empty { text-align: center; color: var(--dh-muted); padding: 24px 8px; font-size: .88rem; }

/* Shared admin list page pattern - search + sort toolbar over a plain
   table, used by User Management and Manage Sites (Pablo, 2026-09-18:
   "retheme...respect paddings as all other pages"). Client-side filter/
   sort, no server round-trip - both lists are small. */
.dh-admin-toolbar { display: flex; flex-wrap: wrap; gap: var(--dh-space-2); align-items: center; margin-bottom: var(--dh-space-3); }
.dh-admin-search { flex: 1 1 220px; display: flex; align-items: center; gap: 8px; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill); padding: 8px 14px; }
.dh-admin-search input { border: none; outline: none; background: none; flex: 1 1 auto; font-size: .88rem; color: var(--dh-ink); font-family: var(--dh-font); }
.dh-admin-search .material-icons-round { color: var(--dh-muted); font-size: 18px; }
.dh-admin-select { border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill); padding: 8px 14px; font-size: .85rem; color: var(--dh-ink); background: var(--dh-paper); font-family: var(--dh-font); }
.dh-admin-sort-dir { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%; border: 1px solid var(--dh-line); background: var(--dh-paper); color: var(--dh-ink); cursor: pointer; }
.dh-admin-sort-dir .material-icons-round { transition: transform .15s; }
.dh-admin-sort-dir.is-desc .material-icons-round { transform: rotate(180deg); }
.dh-admin-card { background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: var(--dh-radius); overflow: hidden; }
.dh-admin-table { width: 100%; border-collapse: collapse; }
.dh-admin-table th { text-align: left; font-size: .7rem; text-transform: uppercase; letter-spacing: .03em; color: var(--dh-muted); padding: 10px 14px; border-bottom: 1px solid var(--dh-line); white-space: nowrap; }
.dh-admin-table td { padding: 10px 14px; border-bottom: 1px solid var(--dh-line); font-size: .86rem; color: var(--dh-ink); vertical-align: middle; }
.dh-admin-table tbody tr:last-child td { border-bottom: none; }
.dh-admin-table tbody tr:hover td { background: var(--dh-sand); }
.dh-admin-table .dh-admin-actions { display: flex; gap: 10px; align-items: center; }
.dh-admin-table .dh-admin-actions a, .dh-admin-table .dh-admin-actions button { color: var(--dh-muted); background: none; border: none; padding: 0; cursor: pointer; display: inline-flex; }
.dh-admin-table .dh-admin-actions a:hover { color: var(--dh-sea); }
.dh-admin-table .dh-admin-actions .is-danger:hover { color: var(--dh-danger); }
.dh-admin-empty-row td { text-align: center; padding: 40px; color: var(--dh-muted); }

/* Google-vs-native signup badge on the User Management avatar (Pablo,
   2026-09-18: dropped in the retheme, put back). Scaled for the current
   36px avatar-sm - the pre-retheme version was a flat 25px sized for the
   old, much bigger avatar-xl thumbnail. */
.dh-user-auth-badge { position: absolute; z-index: 2; bottom: -2px; right: -2px; width: 14px; height: 14px; border-radius: 50%; background: var(--dh-paper); box-shadow: 0 0 0 1.5px var(--dh-paper), 0 0 0 2.5px var(--dh-line); display: inline-flex; align-items: center; justify-content: center; overflow: hidden; }
.dh-user-auth-badge img { width: 100%; height: 100%; object-fit: cover; }

/* Blog (2026-09-17, visual design pass - Pablo: "anybody that is user type
   Creator", SEO content marketing). Headlines use Roboto Slab - already
   preloaded sitewide by page-template.blade.php but never actually used -
   paired with the theme's own Roboto body copy, a deliberate editorial
   pairing distinct from the app's utilitarian UI chrome everywhere else.
   Every other color is a --dh-* token already in use; nothing new. */
.dh-blog-hero {
  background: linear-gradient(135deg, var(--dh-deep), var(--dh-sea));
  color: #fff; border-radius: 18px; padding: var(--dh-space-6) var(--dh-space-4);
  margin-top: var(--dh-space-3); text-align: center;
}
/* Material Dashboard's own h1/h2/h3 rule sets color directly on the
   element (#344767), which wins over the parent's inherited white
   regardless of selector specificity - color has to be set here too. */
.dh-blog-hero h1 { font-family: 'Roboto Slab', serif; font-size: 2rem; font-weight: 700; margin: 0 0 6px; color: #fff; }
.dh-blog-hero p { margin: 0; opacity: .92; font-size: 1rem; color: #fff; }
@media (min-width: 768px) { .dh-blog-hero h1 { font-size: 2.6rem; } }

.dh-blog-filters { display: flex; flex-wrap: wrap; gap: 8px; margin: var(--dh-space-4) 0; }

.dh-blog-eyebrow {
  display: inline-block; font-size: .72rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: .06em; color: var(--dh-sea); margin-bottom: 6px;
}

.dh-blog-byline { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: .85rem; color: var(--dh-muted); }
.dh-blog-avatar {
  width: 28px; height: 28px; border-radius: 50%; background: var(--dh-foam); color: var(--dh-deep);
  display: inline-flex; align-items: center; justify-content: center; font-weight: 800; font-size: .8rem; flex: 0 0 auto;
}
.dh-blog-role { padding: 1px 8px; font-size: .68rem; }
.dh-blog-dot { opacity: .6; }
.dh-blog-excerpt { display: block; color: var(--dh-muted); font-size: .9rem; line-height: 1.5; margin: 6px 0 10px; }

/* Tags: topical/audience labels, deliberately quieter than the category
   eyebrow (2026-09-17) - a post's ONE category vs. the several tags it can
   carry for future targeting ("if tag is tech diving..."). */
.dh-blog-tags { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.dh-blog-tag {
  display: inline-block; font-size: .72rem; font-weight: 600; color: var(--dh-muted);
  border: 1px solid var(--dh-line); border-radius: var(--dh-radius-pill); padding: 3px 10px;
}
.dh-blog-audience { align-items: center; }
.dh-blog-audience p { color: var(--dh-deep); }

/* Blog index's category filters (2026-09-18): "the last article wide, the
   rest below in 3 cols" has to hold true for each filtered category, not
   just the unfiltered "All" view - the featured slot is re-picked from
   whichever posts match the active filter (see Index.blade.php's JS),
   this just constrains the grid under it to exactly 3 columns on desktop
   rather than however many 260px-minimum cards the container fits. */
.dh-blog-grid-3col { grid-template-columns: 1fr; }
@media (min-width: 700px) { .dh-blog-grid-3col { grid-template-columns: repeat(3, 1fr); } }

/* My Dashboard's "From the blog" mini carousel (2026-09-17, reverted back
   from a static grid layout 2026-09-18 - "you broke the carousel. The
   carousel was perfect as it was"): one slide at a time via display
   toggling (not absolute-stacked) - simpler, and every slide is roughly
   the same height (thumb + a 2-line clamped title) so there's no layout
   jump swapping between them. */
/* touch-action tells the browser's OWN gesture recognizer, before any JS
   runs, that this element never pans horizontally - preventDefault() in
   the swipe script's touchmove was already too late on iOS (it decides
   whether to hand a touch off to native scroll/bounce on the very first
   touchmove, not once a threshold is crossed a few pixels in), which is
   why the rubber-band bounce kept happening despite that (Pablo,
   2026-09-18: "the elastic bounce is still there"). pan-y keeps vertical
   page scrolling working normally through this element. */
.dh-mini-carousel { touch-action: pan-y; }
/* overflow: hidden clips whichever slide is mid-transition off past the
   edge, instead of it briefly spilling outside the card (Pablo,
   2026-09-18: slide left/right like a real carousel, on the timer and on
   a swipe alike - see the show() function in Dashboard.blade.php). */
.dh-mini-carousel-track { position: relative; min-height: 92px; overflow: hidden; }
/* Every slide sits stacked in the same spot; JS slides the active one to
   translateX(0) and the previous one off to one side, with this
   transition animating the move. Off-screen by default (matches wherever
   show() last placed a slide, or its initial off-right position before
   ever being touched) so an untouched slide never flashes into view. */
.dh-mini-carousel-slide {
  display: flex; align-items: center; gap: 14px; text-decoration: none; color: inherit;
  position: absolute; top: 0; left: 0; width: 100%;
  transform: translateX(100%); opacity: 0; pointer-events: none;
  transition: transform .35s ease, opacity .35s ease;
}
.dh-mini-carousel-slide.is-active { transform: translateX(0); opacity: 1; pointer-events: auto; }
.dh-mini-carousel-slide img { width: 84px; height: 84px; border-radius: 12px; object-fit: cover; flex: 0 0 auto; background: var(--dh-foam); }
.dh-mini-carousel-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.dh-mini-carousel-title {
  font-family: 'Roboto Slab', serif; font-weight: 700; font-size: 1rem; color: var(--dh-ink); line-height: 1.3;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.dh-mini-carousel-dots { display: flex; gap: 6px; margin-top: 12px; justify-content: center; }
.dh-mini-carousel-dot { width: 7px; height: 7px; border-radius: 50%; border: 0; background: var(--dh-line); padding: 0; cursor: pointer; transition: width .15s, border-radius .15s; }
.dh-mini-carousel-dot.is-active { background: var(--dh-sea); width: 18px; border-radius: 4px; }

/* Featured post: one wide card, image beside the text on desktop, stacked on phones. */
.dh-blog-featured {
  display: grid; grid-template-columns: 1fr; gap: 0; background: var(--dh-paper); border: 1px solid var(--dh-line);
  border-radius: 16px; overflow: hidden; text-decoration: none; color: inherit; box-shadow: 0 2px 10px rgba(11,42,58,.06);
}
@media (min-width: 768px) { .dh-blog-featured { grid-template-columns: 1.1fr 1fr; } }
.dh-blog-featured-img { display: block; aspect-ratio: 16/9; overflow: hidden; background: var(--dh-foam); }
.dh-blog-featured-img img { width: 100%; height: 100%; object-fit: cover; }
/* aspect-ratio above only applies on phones, where the image and body
   stack as separate grid rows and the image needs its own intrinsic
   height. From 768px up they're side-by-side items IN THE SAME ROW, so
   aspect-ratio was sizing the image off its own column width alone -
   shorter than the row the text made, leaving blank space below it
   (Pablo, 2026-09-25). Dropping it there lets the image stretch (grid's
   default align-items) to match the row/card height instead. Must come
   after the base rule above to win the cascade at this breakpoint. */
@media (min-width: 768px) {
  .dh-blog-featured-img { aspect-ratio: auto; height: 100%; }
}
.dh-blog-featured-body { display: flex; flex-direction: column; justify-content: center; padding: var(--dh-space-4) var(--dh-space-6); }
.dh-blog-featured-title { font-family: 'Roboto Slab', serif; font-size: 1.5rem; font-weight: 700; color: var(--dh-ink); line-height: 1.25; margin-bottom: 8px; }
@media (min-width: 768px) { .dh-blog-featured-title { font-size: 1.85rem; } }

.dh-blog-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--dh-space-4); margin: var(--dh-space-4) 0 var(--dh-space-6); }
.dh-blog-card {
  display: flex; flex-direction: column; background: var(--dh-paper); border: 1px solid var(--dh-line);
  border-radius: 14px; overflow: hidden; text-decoration: none; color: inherit; transition: box-shadow .15s, transform .15s;
}
.dh-blog-card:hover { box-shadow: 0 8px 20px rgba(11,42,58,.14); transform: translateY(-2px); }
/* padding-top percentage trick, not aspect-ratio+flex: a card whose flex
   sibling (.dh-blog-card-body) grows taller because of a longer excerpt
   was still stretching this element's height along with it in some
   browsers - this ties the height purely to the element's own width via
   padding, which flex-grow has nothing to distribute against. */
.dh-blog-card-img { position: relative; display: block; height: 0; padding-top: 62.5%; overflow: hidden; background: var(--dh-foam); }
.dh-blog-card-img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.dh-blog-cat-chip { position: absolute; top: 10px; left: 10px; }
.dh-blog-card-body { padding: var(--dh-space-3) var(--dh-space-4) var(--dh-space-4); display: flex; flex-direction: column; flex: 1; }
.dh-blog-card-title { font-family: 'Roboto Slab', serif; font-size: 1.08rem; font-weight: 700; color: var(--dh-ink); line-height: 1.3; }

/* Single post */
/* Sticky so "Close preview" stays reachable while scrolling a long draft,
   which is exactly when a diver stuck on this page (2026-09-18: "gets you
   trapped" in the installed PWA) would otherwise have to scroll back up. */
.dh-preview-banner { position: sticky; top: 0; z-index: 20; display: flex; align-items: center; gap: 8px; color: var(--dh-avg); background: var(--dh-avg-bg); border-radius: var(--dh-radius); padding: 8px 10px; margin: var(--dh-space-3) 0; }
.dh-preview-banner .material-icons-round { font-size: 18px; flex: 0 0 auto; }
.dh-preview-banner > span:nth-child(2) { flex: 1; font-size: .85rem; font-weight: 600; }
.dh-preview-close { flex: 0 0 auto; }
.dh-blog-crumb { display: flex; align-items: center; gap: 2px; font-size: .82rem; color: var(--dh-muted); margin: var(--dh-space-3) 0; }
.dh-blog-crumb a { color: var(--dh-sea); text-decoration: none; }
.dh-blog-crumb .material-icons-round { font-size: 16px; }

.dh-blog-article { max-width: 760px; margin: 0 auto; padding-bottom: var(--dh-space-6); }
.dh-blog-article h1 { font-family: 'Roboto Slab', serif; font-size: 1.9rem; font-weight: 700; color: var(--dh-ink); line-height: 1.25; margin: 0 0 var(--dh-space-3); }
@media (min-width: 768px) { .dh-blog-article h1 { font-size: 2.4rem; } }
.dh-blog-hero-img { width: 100%; border-radius: 16px; margin: var(--dh-space-4) 0; display: block; aspect-ratio: 16/9; object-fit: cover; background: var(--dh-foam); }

.dh-blog-body { font-size: 1.02rem; line-height: 1.75; color: var(--dh-ink); }
.dh-blog-body p { margin: 0 0 var(--dh-space-4); }
.dh-blog-body a { color: var(--dh-sea); font-weight: 600; }
.dh-blog-body h2 {
  font-family: 'Roboto Slab', serif; font-size: 1.4rem; font-weight: 700; color: var(--dh-ink);
  margin: var(--dh-space-6) 0 var(--dh-space-3);
}
.dh-blog-body h3 { font-size: 1.1rem; font-weight: 800; color: var(--dh-ink); margin: 0 0 4px; }
/* Real Creator-written content (2026-09-18, Quill Delta rendered client-side
   into .dh-blog-body - see edit-site.blade.php for the same pattern): the
   hand-built mockup never needed list/quote styling since its "lists" were
   hard-coded .dh-blog-ranked markup, not something a Creator actually
   typed. Quill's own "Quote" toolbar button becomes the callout box for
   free - a Creator never needs a custom block type to get one. */
.dh-blog-body ol, .dh-blog-body ul { margin: 0 0 var(--dh-space-4); padding-left: 1.4em; }
.dh-blog-body li { margin-bottom: 6px; }
.dh-blog-body blockquote {
  margin: 0 0 var(--dh-space-4); padding: var(--dh-space-3) var(--dh-space-4);
  background: var(--dh-foam); border-radius: var(--dh-radius); border: 0;
  font-size: .95rem; color: var(--dh-deep);
}
.dh-blog-lead { font-size: 1.15rem; color: var(--dh-muted); }

.dh-blog-callout {
  display: flex; gap: 10px; align-items: flex-start; background: var(--dh-foam); border-radius: var(--dh-radius);
  padding: var(--dh-space-3) var(--dh-space-4); margin: 0 0 var(--dh-space-4);
}
.dh-blog-callout .material-icons-round { color: var(--dh-sea); flex: 0 0 auto; margin-top: 2px; }
.dh-blog-callout p { margin: 0; font-size: .92rem; color: var(--dh-deep); }

.dh-blog-ranked { list-style: none; margin: 0 0 var(--dh-space-4); padding: 0; display: flex; flex-direction: column; gap: var(--dh-space-3); }
.dh-blog-ranked li { display: flex; gap: var(--dh-space-3); align-items: flex-start; }
.dh-blog-rank {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%; background: var(--dh-ink); color: #fff;
  display: flex; align-items: center; justify-content: center; font-weight: 800; font-family: 'Roboto Slab', serif;
}
.dh-blog-ranked h3 { margin-bottom: 2px; }
.dh-blog-ranked p { margin: 0; color: var(--dh-muted); font-size: .95rem; }

.dh-blog-related-sites { margin-top: var(--dh-space-6); }
.dh-blog-related-sites h2 { font-family: 'Roboto Slab', serif; font-size: 1.3rem; font-weight: 700; color: var(--dh-ink); margin-bottom: var(--dh-space-3); }
.dh-blog-more { margin-top: var(--dh-space-6); }
.dh-blog-more .dh-panel-title { font-family: 'Roboto Slab', serif; font-size: 1.3rem; text-transform: none; letter-spacing: 0; }

/* Blog authoring form (2026-09-18): the related-sites search dropdown and
   the picked-sites list underneath it. */
.dh-related-site-results { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20; background: var(--dh-paper); border: 1px solid var(--dh-line); border-radius: var(--dh-radius); box-shadow: 0 8px 20px rgba(11,42,58,.16); max-height: 240px; overflow-y: auto; }
.dh-related-sites-list { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.dh-related-site-row { border: 1px solid var(--dh-line); border-radius: var(--dh-radius); padding: 10px 12px; }
.dh-related-site-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.dh-related-site-row textarea { width: 100%; border: 1px solid var(--dh-line); border-radius: 8px; padding: 8px 10px; font: inherit; font-size: .88rem; resize: vertical; }
