/*
 * The web app's design system — hand-written, not compiled (no Node/build
 * step in this deployment path). Palette values are copied directly from
 * the iOS app's Theme/Ocean.swift Night palette so the two read as one
 * product, not two.
 *
 * Type: "Outfit" (a geometric-rounded display face — see layouts/app.blade
 * and layouts/guest.blade for the Google Fonts link) carries headings, the
 * wordmark, and card labels, echoing the rounded SF Rounded look the iOS
 * app uses throughout. Body copy and data stay on the system font stack —
 * fast, native, and legible at small sizes, which is most of this UI.
 */

:root {
  --display-font: 'Outfit', -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;

  --deep: #13385f;
  --abyss: #0c2340;
  --shallow: #0e6098;
  --foam: #c8eef2;
  --seafoam: #49c9e6;
  --coral: #fe8a66;
  --kelp: #5ac998;
  --sand: #f2daad;
  --alert-red: #ff5c4f;

  /* The water-column ramp, surface to near-black — used for chart
     backgrounds, matching Ocean.water(at:) in the app. */
  --water-0: #2892a3;
  --water-22: #16739d;
  --water-45: #0e6098;
  --water-68: #083768;
  --water-86: #051e42;
  --water-100: #030e25;

  --ink: #16202b;

  --border: rgba(255, 255, 255, 0.12);
  --card-bg: rgba(255, 255, 255, 0.06);
  --card-bg-strong: rgba(255, 255, 255, 0.09);
  --shadow: 0 8px 24px rgba(3, 14, 37, 0.35);

  --radius-lg: 18px;
  --radius-md: 14px;
  --radius-sm: 10px;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  font-family: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
  color: #fff;
  background: linear-gradient(180deg, var(--deep) 0%, var(--abyss) 100%) fixed;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

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

a:hover {
  text-decoration: underline;
}

.on-surface-100 {
  color: #fff;
}
.on-surface-75 {
  color: rgba(255, 255, 255, 0.75);
}
.on-surface-55 {
  color: rgba(255, 255, 255, 0.55);
}
.on-surface-45 {
  color: rgba(255, 255, 255, 0.45);
}

/* ---------- Layout ---------- */

.shell {
  max-width: 900px;
  margin: 0 auto;
  padding: 0 20px 64px;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 20px;
  max-width: 900px;
  margin: 0 auto;
  gap: 12px;
}
@media (max-width: 640px) {
  .topbar {
    flex-wrap: wrap;
  }
  /*
     Wraps onto as many lines as it needs rather than scrolling sideways.
     As a scroll strip it fitted, but Sign Out sat off the right edge
     behind a swipe nobody would think to make, and "Add Dive" broke
     across two lines mid-label.
  */
  .topbar nav {
    width: 100%;
    flex-wrap: wrap;
    gap: 12px 18px;
  }
  .topbar nav a,
  .topbar nav .logout-btn {
    white-space: nowrap;
    /* Comfortably tappable without spacing the row out on desktop. */
    padding: 3px 0;
  }
}

.wordmark {
  display: flex;
  align-items: center;
  gap: 7px;
  font-family: var(--display-font);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.wordmark .dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--seafoam);
  box-shadow: 0 0 10px var(--seafoam);
}
.wordmark .my {
  color: var(--coral);
}

.topbar nav {
  display: flex;
  align-items: center;
  gap: 18px;
  font-size: 14px;
  font-weight: 600;
}
.topbar nav a {
  color: rgba(255, 255, 255, 0.75);
}
.topbar nav a.active,
.topbar nav a:hover {
  color: #fff;
}
.nav-profile {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.nav-emoji {
  font-size: 15px;
  line-height: 1;
}

.topbar form {
  display: inline;
}
.topbar .logout-btn {
  background: none;
  border: none;
  font: inherit;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.75);
  cursor: pointer;
  padding: 0;
}
.topbar .logout-btn:hover {
  color: #fff;
}

.page-head {
  margin: 8px 0 22px;
}
.page-head h1 {
  font-family: var(--display-font);
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -0.01em;
  margin: 0 0 4px;
}
.page-head p {
  margin: 0;
  color: rgba(255, 255, 255, 0.55);
  font-size: 14px;
}

/* ---------- Auth pages ---------- */

.auth-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.auth-card {
  width: 100%;
  max-width: 380px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 32px 28px;
  animation: auth-card-in 0.4s ease-out;
}
@keyframes auth-card-in {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .auth-card {
    animation: none;
  }
}

.auth-card .wordmark {
  justify-content: center;
  margin-bottom: 22px;
}

.auth-card h1 {
  font-family: var(--display-font);
  font-size: 21px;
  font-weight: 800;
  margin: 0 0 6px;
  text-align: center;
}

.auth-card .sub {
  text-align: center;
  color: rgba(255, 255, 255, 0.55);
  font-size: 13.5px;
  margin: 0 0 24px;
}

.auth-links {
  margin-top: 18px;
  text-align: center;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.55);
}

/* ---------- Forms ---------- */

.field {
  margin-bottom: 16px;
}
.field label {
  display: block;
  font-size: 12.5px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.65);
  margin-bottom: 6px;
  letter-spacing: 0.01em;
}
.field input,
.field select,
.field textarea {
  width: 100%;
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: #fff;
  font: inherit;
  font-size: 15px;
  padding: 11px 13px;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--seafoam);
  box-shadow: 0 0 0 3px rgba(73, 201, 230, 0.18);
}
.field textarea {
  resize: vertical;
  min-height: 80px;
}
.field .hint {
  margin-top: 5px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.4);
}
.field .error {
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--alert-red);
  font-weight: 600;
}

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 480px) {
  .field-row {
    grid-template-columns: 1fr;
  }
}

.checkbox-field {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 16px;
}
.checkbox-field input {
  width: 17px;
  height: 17px;
}
.checkbox-field label {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.8);
  margin: 0;
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  border: none;
  border-radius: 100px;
  font: inherit;
  font-size: 14.5px;
  font-weight: 700;
  padding: 11px 20px;
  cursor: pointer;
  text-decoration: none !important;
  transition: filter 0.15s, background 0.15s, transform 0.1s;
}
.btn:active {
  transform: scale(0.98);
}
.btn:focus-visible {
  outline: 2px solid var(--seafoam);
  outline-offset: 2px;
}

.btn-primary {
  background: var(--seafoam);
  color: var(--ink);
  width: 100%;
}
.btn-primary:hover {
  filter: brightness(1.06);
}

.btn-ghost {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}
.btn-ghost:hover {
  background: rgba(255, 255, 255, 0.14);
}

.btn-danger {
  background: rgba(255, 92, 79, 0.14);
  color: var(--alert-red);
  border: 1px solid rgba(255, 92, 79, 0.35);
}
.btn-danger:hover {
  background: rgba(255, 92, 79, 0.22);
}

.btn-sm {
  padding: 7px 14px;
  font-size: 13px;
}

/* ---------- Cards ---------- */

.card {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 18px;
  margin-bottom: 16px;
  transition: border-color 0.2s, background 0.2s;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
}
.card-head h2 {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  margin: 0;
}

/* ---------- Dive list ---------- */

.dive-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 16px;
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: 10px;
  transition: background 0.15s;
}
.dive-row:hover {
  background: var(--card-bg-strong);
  text-decoration: none;
}

.depth-badge {
  flex-shrink: 0;
  width: 56px;
  height: 56px;
  border-radius: 13px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, var(--water-22), var(--water-68));
  border: 1.2px solid rgba(73, 201, 230, 0.5);
  box-shadow: 0 4px 12px rgba(73, 201, 230, 0.25);
}
.depth-badge .val {
  color: #fff;
  font-weight: 800;
  font-size: 17px;
  line-height: 1.1;
}
.depth-badge .unit {
  color: var(--seafoam);
  font-weight: 800;
  font-size: 8px;
  letter-spacing: 0.05em;
}

.dive-row .info {
  flex: 1;
  min-width: 0;
}
.dive-row .site {
  font-weight: 700;
  font-size: 15px;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dive-row .meta {
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.5);
  margin-top: 2px;
}

.dive-row .stat {
  text-align: right;
  flex-shrink: 0;
}
.dive-row .stat .num {
  font-weight: 800;
  font-size: 15px;
  color: var(--seafoam);
}
.dive-row .stat .label {
  font-size: 10.5px;
  color: rgba(255, 255, 255, 0.4);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: rgba(255, 255, 255, 0.5);
}
.empty-state .icon {
  font-size: 40px;
  margin-bottom: 12px;
  opacity: 0.6;
}

/* ---------- Chips / pills ---------- */

.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 100px;
  background: rgba(73, 201, 230, 0.16);
  color: var(--seafoam);
}
.chip-kelp {
  background: rgba(90, 201, 152, 0.16);
  color: var(--kelp);
}
.chip-coral {
  background: rgba(254, 138, 102, 0.16);
  color: var(--coral);
}
.chip-red {
  background: rgba(255, 92, 79, 0.16);
  color: var(--alert-red);
}

/* ---------- Dive detail stat tiles ---------- */

.stat-tiles {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin-bottom: 16px;
}
.stat-tile {
  background: var(--card-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: 13px 12px;
  text-align: center;
}
.stat-tile .icon {
  color: var(--seafoam);
  font-size: 13px;
  margin-bottom: 4px;
}
.stat-tile .val {
  font-size: 19px;
  font-weight: 800;
}
.stat-tile .label {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.5);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 2px;
}

/* ---------- Detail rows ---------- */

.detail-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 11px 4px;
  border-bottom: 1px solid var(--border);
  font-size: 14px;
}
.detail-row:last-child {
  border-bottom: none;
}
.detail-row .label {
  color: rgba(255, 255, 255, 0.55);
  display: flex;
  align-items: center;
  gap: 8px;
}
.detail-row .value {
  font-weight: 600;
}

/* ---------- Legal & support pages ---------- */

/*
   Long-form reading, so the rules here are the opposite of the app's:
   a measured line length, generous leading, and headings that separate
   rather than decorate.
*/
.legal-page {
  max-width: 680px;
  margin: 0 auto;
  padding: 32px 22px 64px;
}
.legal-wordmark {
  display: inline-flex;
  color: #fff;
  text-decoration: none;
  margin-bottom: 26px;
}
.legal-body {
  /* ~68 characters at this size — past about 75 the eye loses the start of
     the next line on a return sweep. */
  font-size: 15.5px;
  line-height: 1.72;
  color: rgba(255, 255, 255, 0.82);
}
.legal-body h1 {
  font-size: 30px;
  margin: 0 0 6px;
}
.legal-body h2 {
  font-size: 19px;
  margin: 38px 0 10px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}
.legal-body h3 {
  font-size: 15.5px;
  margin: 24px 0 6px;
  color: var(--seafoam);
}
.legal-body p { margin: 0 0 14px; }
.legal-body ul {
  margin: 0 0 16px;
  padding-left: 20px;
}
.legal-body li { margin-bottom: 7px; }
.legal-body a { color: var(--seafoam); }
.legal-body strong { color: #fff; }
.legal-body code {
  font-size: 13.5px;
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.09);
}
.legal-dates {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.5);
  margin-bottom: 26px !important;
}

/*
   The safety disclaimer. Called out rather than left as body copy because
   it's the one section on the page where being skimmed past could actually
   hurt somebody.
*/
.legal-callout {
  margin: 26px 0 10px;
  padding: 4px 20px 6px;
  border-radius: var(--radius-lg);
  background: rgba(255, 92, 79, 0.09);
  border: 1px solid rgba(255, 92, 79, 0.32);
}
.legal-callout h2 {
  border-top: none;
  padding-top: 0;
  margin-top: 20px;
  color: var(--alert-red);
}

.legal-footer {
  display: flex;
  gap: 20px;
  margin-top: 46px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  font-size: 13.5px;
}
.legal-footer a {
  color: rgba(255, 255, 255, 0.55);
  text-decoration: none;
}
.legal-footer a:hover,
.legal-footer a:focus-visible {
  color: var(--seafoam);
}

/* ---------- Diver's exhaust ---------- */

/*
   A burst of bubbles from below, then a long gap, then another — the way a
   regulator actually vents. The bubbles grow as they climb, because the
   pressure around them is dropping the whole way up.

   Each burst spends most of its cycle invisible, which is what makes it read
   as occasional rather than as a permanent stream of bubbles.
*/
.exhale {
  position: absolute;
  bottom: -8vh;
}
.exhale span {
  position: absolute;
  bottom: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, rgba(255, 255, 255, 0.9), rgba(198, 242, 252, 0.3) 52%, rgba(198, 242, 252, 0.06) 76%);
  box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.45);
  opacity: 0;
  animation: exhale-rise linear infinite;
}

.exhale-a { left: 17%; }
.exhale-a span { animation-duration: 34s; }
.exhale-b { left: 68%; }
.exhale-b span { animation-duration: 47s; }

/* Staggered so the burst streams out of one point rather than appearing
   all at once, and scattered sideways so it widens as it goes. */
.exhale span:nth-child(1) { width: 13px; height: 13px; left: 0px;   animation-delay: -30s; }
.exhale span:nth-child(2) { width: 9px;  height: 9px;  left: 14px;  animation-delay: -29.4s; }
.exhale span:nth-child(3) { width: 16px; height: 16px; left: -12px; animation-delay: -28.9s; }
.exhale span:nth-child(4) { width: 7px;  height: 7px;  left: 8px;   animation-delay: -28.4s; }
.exhale span:nth-child(5) { width: 11px; height: 11px; left: -6px;  animation-delay: -27.8s; }
.exhale span:nth-child(6) { width: 14px; height: 14px; left: 20px;  animation-delay: -27.2s; }
.exhale span:nth-child(7) { width: 6px;  height: 6px;  left: -18px; animation-delay: -26.7s; }
.exhale span:nth-child(8) { width: 10px; height: 10px; left: 4px;   animation-delay: -26.1s; }
.exhale span:nth-child(9) { width: 8px;  height: 8px;  left: -9px;  animation-delay: -25.5s; }

/*
   The rise takes about a quarter of the cycle; the rest is the gap before
   the next breath.
*/
@keyframes exhale-rise {
  0%   { transform: translate3d(0, 0, 0) scale(0.45);        opacity: 0; }
  2%   {                                                     opacity: 0.85; }
  12%  { transform: translate3d(16px, -42vh, 0) scale(1.1);  opacity: 0.7; }
  24%  { transform: translate3d(-10px, -92vh, 0) scale(1.5); opacity: 0.35; }
  28%  { transform: translate3d(-4px, -116vh, 0) scale(1.7); opacity: 0; }
  100% { transform: translate3d(-4px, -116vh, 0) scale(1.7); opacity: 0; }
}

/* ---------- Sea life ---------- */

/*
   Things swimming past, seen from below and at distance. Silhouettes only,
   in the water's own colour rather than in black — a shark lit from above
   reads as a shape slightly darker than the water around it, not as a hole
   cut in it.

   Depth carries the composition: the far animals are smaller, fainter and
   much slower than the near ones.
*/
.sea-life-defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.sea-life {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.swimmer {
  position: absolute;
  left: 0;
  animation: swim-by linear infinite;
  will-change: transform;
}
/* Right-to-left swimmers travel the other way and face the way they go. */
.swimmer.rtl {
  animation-name: swim-by-rtl;
}
.swimmer.rtl svg {
  transform: scaleX(-1);
}

/* Nested so the horizontal crossing and the vertical bob don't fight over
   the same transform property. */
.swimmer .bob {
  animation: swim-bob ease-in-out infinite;
}

.swimmer svg {
  display: block;
  fill: currentColor;
}

.swimmer.whale-far {
  top: 11%;
  /* Fainter than anything else out there — at this size it would otherwise
     dominate a page whose actual job is a sign-in form. */
  color: rgba(11, 46, 80, 0.38);
  animation-duration: 175s;
  animation-delay: -55s;
}
.swimmer.whale-far svg { width: 230px; }
.swimmer.whale-far .bob { animation-duration: 19s; }

.swimmer.shark-mid {
  top: 62%;
  color: rgba(10, 40, 70, 0.55);
  animation-duration: 74s;
  animation-delay: -22s;
}
.swimmer.shark-mid svg { width: 150px; }
.swimmer.shark-mid .bob { animation-duration: 13s; }

.swimmer.fish-a {
  top: 34%;
  color: rgba(16, 60, 96, 0.6);
  animation-duration: 46s;
  animation-delay: -9s;
}
.swimmer.fish-a svg { width: 54px; }
.swimmer.fish-a .bob { animation-duration: 6s; }

.swimmer.fish-b {
  top: 78%;
  color: rgba(14, 52, 86, 0.55);
  animation-duration: 38s;
  animation-delay: -26s;
}
.swimmer.fish-b svg { width: 40px; }
.swimmer.fish-b .bob { animation-duration: 5s; }

.swimmer.school {
  top: 46%;
  color: rgba(18, 66, 104, 0.5);
  animation-duration: 58s;
  animation-delay: -34s;
}
.swimmer.school .bob {
  display: flex;
  align-items: center;
  gap: 6px;
  animation-duration: 7s;
}
/* Staggered vertically, because a school swimming in a straight line reads
   as a row of icons. */
.swimmer.school svg { width: 22px; }
.swimmer.school svg:nth-child(2) { margin-top: 16px; }
.swimmer.school svg:nth-child(3) { margin-top: -12px; }
.swimmer.school svg:nth-child(4) { margin-top: 9px; }
.swimmer.school svg:nth-child(5) { margin-top: -6px; }

/* Starts and ends well clear of the viewport, so nothing appears or
   vanishes at the edge of the screen. */
@keyframes swim-by {
  from { transform: translateX(-40vw); }
  to   { transform: translateX(140vw); }
}
@keyframes swim-by-rtl {
  from { transform: translateX(140vw); }
  to   { transform: translateX(-40vw); }
}
@keyframes swim-bob {
  0%, 100% { transform: translateY(-7px); }
  50%      { transform: translateY(7px); }
}

/* ---------- Underwater sign-in ---------- */

/*
   The sign-in screen, from a few metres down: sunlight breaking on the
   surface overhead, shafts of it swinging through the water column, and
   bubbles going the other way.

   All decorative, all built from empty elements the layout marks
   aria-hidden, and all of it stops dead under prefers-reduced-motion —
   this sits behind a form somebody is trying to type into.
*/
.auth-body {
  /* The water column itself. Anchored, not repeated, so the gradient reads
     as depth rather than as a tiling texture. */
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(103, 219, 240, 0.30), transparent 60%),
    linear-gradient(180deg, var(--water-22) 0%, var(--water-45) 26%, var(--water-68) 58%, var(--water-100) 100%);
  background-attachment: fixed;
}

.underwater {
  position: fixed;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

/* The surface seen from below — brightest directly overhead, and rippling. */
.underwater .surface {
  position: absolute;
  top: -18vh;
  left: -10%;
  width: 120%;
  height: 46vh;
  background: radial-gradient(60% 100% at 50% 100%, rgba(160, 236, 250, 0.42), transparent 70%);
  filter: blur(22px);
  animation: surface-swell 11s ease-in-out infinite;
}

/*
   Light shafts. Skewed rather than rotated so they stay parallel, and
   blurred hard — a crisp-edged shaft reads as a graphic, a soft one reads
   as light.
*/
.underwater .shafts span {
  position: absolute;
  top: -30vh;
  height: 150vh;
  background: linear-gradient(180deg, rgba(186, 244, 255, 0.46), rgba(174, 240, 252, 0.10) 52%, transparent 82%);
  filter: blur(14px);
  transform-origin: top center;
  animation: shaft-sway 14s ease-in-out infinite;
}
.underwater .shafts span:nth-child(1) { left: 6%;  width: 90px;  animation-duration: 15s; animation-delay: -2s;  opacity: 0.95; }
.underwater .shafts span:nth-child(2) { left: 24%; width: 54px;  animation-duration: 19s; animation-delay: -9s;  opacity: 0.7; }
.underwater .shafts span:nth-child(3) { left: 48%; width: 120px; animation-duration: 13s; animation-delay: -5s;  opacity: 0.8; }
.underwater .shafts span:nth-child(4) { left: 71%; width: 68px;  animation-duration: 17s; animation-delay: -12s; opacity: 0.72; }
.underwater .shafts span:nth-child(5) { left: 88%; width: 100px; animation-duration: 21s; animation-delay: -7s;  opacity: 0.62; }

/*
   Bubbles. Each drifts as it rises rather than going straight up, because
   a column of perfectly vertical bubbles looks like falling snow played
   backwards.
*/
.underwater .bubbles span {
  position: absolute;
  bottom: -10vh;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgba(255, 255, 255, 0.85), rgba(190, 240, 250, 0.22) 55%, rgba(190, 240, 250, 0.05) 78%);
  box-shadow: inset 0 0 4px rgba(255, 255, 255, 0.4);
  opacity: 0;
  animation: bubble-rise linear infinite;
}
.underwater .bubbles span:nth-child(1)  { left: 4%;  width: 7px;  height: 7px;  animation-duration: 15s; animation-delay: -1s; }
.underwater .bubbles span:nth-child(2)  { left: 12%; width: 12px; height: 12px; animation-duration: 21s; animation-delay: -7s; }
.underwater .bubbles span:nth-child(3)  { left: 19%; width: 5px;  height: 5px;  animation-duration: 12s; animation-delay: -3s; }
.underwater .bubbles span:nth-child(4)  { left: 27%; width: 9px;  height: 9px;  animation-duration: 18s; animation-delay: -11s; }
.underwater .bubbles span:nth-child(5)  { left: 34%; width: 4px;  height: 4px;  animation-duration: 14s; animation-delay: -6s; }
.underwater .bubbles span:nth-child(6)  { left: 42%; width: 14px; height: 14px; animation-duration: 24s; animation-delay: -15s; }
.underwater .bubbles span:nth-child(7)  { left: 50%; width: 6px;  height: 6px;  animation-duration: 16s; animation-delay: -2s; }
.underwater .bubbles span:nth-child(8)  { left: 58%; width: 10px; height: 10px; animation-duration: 20s; animation-delay: -9s; }
.underwater .bubbles span:nth-child(9)  { left: 65%; width: 5px;  height: 5px;  animation-duration: 13s; animation-delay: -4s; }
.underwater .bubbles span:nth-child(10) { left: 73%; width: 11px; height: 11px; animation-duration: 22s; animation-delay: -13s; }
.underwater .bubbles span:nth-child(11) { left: 80%; width: 7px;  height: 7px;  animation-duration: 17s; animation-delay: -8s; }
.underwater .bubbles span:nth-child(12) { left: 87%; width: 4px;  height: 4px;  animation-duration: 11s; animation-delay: -5s; }
.underwater .bubbles span:nth-child(13) { left: 93%; width: 9px;  height: 9px;  animation-duration: 19s; animation-delay: -16s; }
.underwater .bubbles span:nth-child(14) { left: 97%; width: 6px;  height: 6px;  animation-duration: 15s; animation-delay: -10s; }

@keyframes surface-swell {
  0%, 100% { transform: translateX(-2%) scaleY(1);    opacity: 0.9; }
  50%      { transform: translateX(2%)  scaleY(1.08); opacity: 1; }
}

@keyframes shaft-sway {
  0%, 100% { transform: skewX(-9deg)  translateX(-14px); }
  50%      { transform: skewX(-15deg) translateX(14px); }
}

/* Fades in off the bottom and out again before the surface, so a bubble
   never visibly pops into or out of existence mid-screen. */
@keyframes bubble-rise {
  0%   { transform: translate3d(0, 0, 0) scale(0.9);            opacity: 0; }
  8%   {                                                        opacity: 0.7; }
  50%  { transform: translate3d(22px, -55vh, 0) scale(1);       opacity: 0.55; }
  88%  {                                                        opacity: 0.35; }
  100% { transform: translate3d(-14px, -115vh, 0) scale(1.06);  opacity: 0; }
}

/* Above the water, below the form. */
.auth-body .auth-wrap {
  position: relative;
  z-index: 1;
}

/*
   The card gets a little more body than the in-app one: it's floating over
   moving water now, and the translucent version let shafts drift through
   the input fields.
*/
.auth-body .auth-card {
  background: rgba(9, 32, 58, 0.82);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-color: rgba(140, 220, 240, 0.22);
  box-shadow: 0 18px 50px rgba(2, 12, 28, 0.55);
}

@media (prefers-reduced-motion: reduce) {
  .underwater .surface,
  .underwater .shafts span,
  .underwater .bubbles span,
  .exhale span,
  .swimmer,
  .swimmer .bob {
    animation: none;
  }
  /* Parked mid-screen rather than at the keyframe's start position, which
     is off the edge — frozen there they'd simply be missing. */
  .swimmer {
    transform: translateX(30vw);
  }
  /* Held at a readable point in the cycle rather than at 0%, where every
     bubble is fully transparent. */
  .underwater .bubbles span {
    opacity: 0.4;
    transform: translate3d(0, -55vh, 0);
  }
}

/* ---------- Back link ---------- */

/*
   A way out of a detail page that doesn't rely on the browser's own back
   button — which isn't there at all when a page is opened from a link
   somebody shared.
*/
.back-link {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 14px;
  font-size: 13px;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.6);
  text-decoration: none;
}
.back-link:hover,
.back-link:focus-visible {
  color: var(--seafoam);
}
.back-link span {
  font-size: 15px;
  line-height: 1;
}

/* ---------- Certification list ---------- */

/*
   Every card the diver holds, with the date each was issued. Laid out as a
   list rather than as `.detail-row`s: each entry carries three lines of its
   own, and a label/value pair can't hold that without the agency and the
   number colliding on narrow screens.
*/
.cert-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.cert-item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
  padding: 11px 4px;
  border-bottom: 1px solid var(--border);
}
.cert-item:last-child {
  border-bottom: none;
}
.cert-item-main {
  min-width: 0;
}
.cert-item-title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 14px;
  font-weight: 600;
}
.cert-item-meta {
  margin-top: 2px;
  font-size: 12.5px;
  color: rgba(255, 255, 255, 0.55);
}
/* Right-aligned and fixed, so the dates line up down the column however
   long the certification names beside them are. */
.cert-item-date {
  flex-shrink: 0;
  text-align: right;
}
.cert-item-date .label {
  display: block;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
}
.cert-item-date .value {
  font-size: 13.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 420px) {
  .cert-item {
    flex-direction: column;
    gap: 6px;
  }
  .cert-item-date {
    text-align: left;
  }
  .cert-item-date .label {
    display: inline;
    margin-right: 6px;
  }
}

/* ---------- Charts ---------- */

.chart-tabs {
  display: flex;
  gap: 6px;
  margin-bottom: 12px;
}
.chart-tab {
  padding: 7px 14px;
  border-radius: 100px;
  font-size: 12.5px;
  font-weight: 700;
  background: rgba(255, 255, 255, 0.07);
  color: rgba(255, 255, 255, 0.6);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 5px;
}
.chart-tab.active {
  background: var(--seafoam);
  color: var(--ink);
}
.chart-panel {
  display: none;
}
.chart-panel.active {
  display: block;
}

.chart-frame {
  border-radius: 16px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.1);
  position: relative;
}
.chart-caption {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.45);
  margin-top: 9px;
  line-height: 1.5;
}

/* ---------- Alerts ---------- */

.alert {
  padding: 12px 16px;
  border-radius: var(--radius-sm);
  font-size: 13.5px;
  margin-bottom: 18px;
}
.alert-error {
  background: rgba(255, 92, 79, 0.12);
  border: 1px solid rgba(255, 92, 79, 0.35);
  color: #ffb3ac;
}
.alert-list {
  margin: 0;
  padding-left: 18px;
}
.alert-list li + li {
  margin-top: 4px;
}
.alert-success {
  background: rgba(90, 201, 152, 0.12);
  border: 1px solid rgba(90, 201, 152, 0.35);
  color: #a6e8c9;
}

.flex-between {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.recovery-codes {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  background: rgba(0, 0, 0, 0.25);
  border-radius: var(--radius-sm);
  padding: 14px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  font-size: 13px;
}

/* ---------- Profile identity ---------- */

.profile-identity {
  display: flex;
  align-items: center;
  gap: 16px;
}

.emoji-badge {
  flex-shrink: 0;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30px;
  background: linear-gradient(160deg, var(--water-22), var(--water-68));
  border: 1.5px solid rgba(73, 201, 230, 0.5);
  box-shadow: 0 4px 14px rgba(73, 201, 230, 0.25);
}
.emoji-badge.is-empty {
  font-family: var(--display-font);
  font-size: 20px;
  font-weight: 800;
  color: var(--seafoam);
}

.profile-identity .name {
  font-family: var(--display-font);
  font-size: 21px;
  font-weight: 700;
  color: #fff;
}
.profile-identity .cert-line {
  margin-top: 3px;
  font-size: 13px;
  color: var(--seafoam);
  font-weight: 600;
}
.profile-identity .cert-number {
  color: rgba(255, 255, 255, 0.45);
  font-weight: 500;
}

.emoji-picker-toggle > summary {
  list-style: none;
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--seafoam);
  margin-top: 12px;
  user-select: none;
}
.emoji-picker-toggle > summary::-webkit-details-marker {
  display: none;
}
.emoji-picker-toggle > summary:hover {
  color: var(--foam);
}
.emoji-picker-toggle[open] > summary {
  margin-bottom: 12px;
}

.emoji-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 8px;
}
@media (max-width: 420px) {
  .emoji-grid {
    grid-template-columns: repeat(5, 1fr);
  }
}
.emoji-grid button {
  aspect-ratio: 1;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.05);
  font-size: 20px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.emoji-grid button:hover {
  background: rgba(73, 201, 230, 0.16);
  border-color: var(--seafoam);
  transform: scale(1.06);
}
.emoji-grid button.selected {
  background: rgba(73, 201, 230, 0.22);
  border-color: var(--seafoam);
}
.emoji-grid .clear-option {
  font-size: 11px;
  font-weight: 700;
  color: rgba(255, 255, 255, 0.55);
}

/* ---------- Admin table ---------- */

.admin-table {
  width: 100%;
  /* Below this, columns have no room for real content (a full date, the
     "Disable" button) — the .card wrapper's own overflow-x: auto takes
     over instead of squeezing them, same escape valve a narrow phone
     screen needs anyway. */
  min-width: 620px;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 13.5px;
}
/* Explicit widths — table-layout: fixed needs them, otherwise every column
   past the wide "User" one collapses to its content's natural width and
   the short ones (a single digit, a status chip) all crowd together. */
.admin-table th:nth-child(1),
.admin-table td:nth-child(1) {
  width: 32%;
}
.admin-table th:nth-child(2),
.admin-table td:nth-child(2) {
  width: 14%;
}
.admin-table th:nth-child(3),
.admin-table td:nth-child(3) {
  width: 8%;
}
.admin-table th:nth-child(4),
.admin-table td:nth-child(4) {
  width: 10%;
}
.admin-table th:nth-child(5),
.admin-table td:nth-child(5) {
  width: 12%;
}
.admin-table th:nth-child(6),
.admin-table td:nth-child(6) {
  width: 24%;
}
.admin-table th {
  text-align: left;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.45);
  padding: 0 14px 12px;
  white-space: nowrap;
}
.admin-table td {
  padding: 14px;
  border-top: 1px solid var(--border);
  vertical-align: middle;
  white-space: nowrap;
}
.admin-table .user-name,
.admin-table .user-email {
  white-space: normal;
}
.admin-table tr.disabled td {
  opacity: 0.55;
}
.admin-table .user-name {
  font-weight: 700;
  color: #fff;
}
.admin-table .user-email {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
}

/* ---------- Trip checklist ---------- */

.checklist-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}
.checklist-head h1 {
  font-family: var(--display-font);
  font-size: 28px;
  font-weight: 800;
  margin: 0;
  color: #fff;
}
.checklist-sub {
  margin: 4px 0 0;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.55);
}
.checklist-synced {
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  color: var(--kelp);
}

.checklist-progress {
  margin-bottom: 16px;
}
.checklist-bar {
  height: 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.10);
  overflow: hidden;
}
.checklist-bar span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--seafoam), var(--kelp));
  transition: width 0.25s ease;
}
.checklist-count {
  margin: 8px 0 0;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.6);
}
.checklist-count strong {
  color: #fff;
}

.checklist-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 20px;
}
.checklist-actions button {
  font: inherit;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
  background: var(--card-bg-strong);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 9px 18px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.checklist-actions button:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.28);
}

.checklist-card h2 {
  font-family: var(--display-font);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--seafoam);
  margin: 0 0 10px;
}
.checklist-card ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.checklist-card li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.checklist-card li:first-child {
  border-top: 0;
}
.checklist-card label {
  display: flex;
  align-items: center;
  gap: 11px;
  flex: 1;
  cursor: pointer;
  font-size: 14.5px;
  color: rgba(255, 255, 255, 0.88);
  /* 44px of touch target on a phone, without moving the text. */
  min-height: 30px;
}
.checklist-card input[type="checkbox"] {
  width: 20px;
  height: 20px;
  flex: none;
  accent-color: var(--seafoam);
  cursor: pointer;
}
.checklist-card input:checked + span {
  color: rgba(255, 255, 255, 0.45);
  text-decoration: line-through;
}
.checklist-card li.is-auto label {
  cursor: default;
}
.checklist-auto {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.04em;
  color: var(--kelp);
  background: rgba(90, 201, 152, 0.14);
  border-radius: 999px;
  padding: 3px 9px;
  white-space: nowrap;
}

/* The old page had a print stylesheet and it was clearly used — this list
   gets carried to the dive shop on paper. */
@media print {
  .topbar,
  .checklist-actions,
  .checklist-synced {
    display: none !important;
  }
  body,
  .card,
  .checklist-card {
    background: #fff !important;
    color: #000 !important;
    box-shadow: none !important;
  }
  .checklist-head h1,
  .checklist-card label,
  .checklist-count,
  .checklist-count strong {
    color: #000 !important;
  }
  .checklist-card h2 {
    color: #333 !important;
  }
  .checklist-card li {
    border-top-color: #ddd !important;
    break-inside: avoid;
  }
  .checklist-card input:checked + span {
    color: #666 !important;
  }
}

/* ---------- Destructive actions ---------- */

.danger-card {
  border-color: rgba(255, 92, 79, 0.30);
}
.danger-card .card-head h2 {
  color: var(--alert-red);
}
.danger-copy {
  font-size: 13px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.6);
  margin: 0 0 16px;
}
.btn-danger {
  background: rgba(255, 92, 79, 0.16);
  border: 1px solid rgba(255, 92, 79, 0.42);
  color: var(--alert-red);
  font-weight: 700;
}
.btn-danger:hover {
  background: rgba(255, 92, 79, 0.26);
  border-color: rgba(255, 92, 79, 0.6);
}

/* ---------- Logbook cards ---------- */

.dive-no {
  font-size: 12px;
  font-weight: 800;
  color: var(--seafoam);
  margin-right: 5px;
  font-variant-numeric: tabular-nums;
}

.dive-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 7px;
}
.dive-chips .chip {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.72);
  background: rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  padding: 2px 8px;
  white-space: nowrap;
}

/* The dive's depth profile. Fixed size and never allowed to grow: it's a
   glanceable aside, and the site name and date come first. Colour lives on
   the SVG attributes so a stale stylesheet can't leave it a black blob. */
.dive-spark {
  flex: 0 0 100px;
  width: 100px;
  height: 26px;
  align-self: center;
  opacity: 0.9;
}

/* Narrow screens have no room for it beside the text. */
@media (max-width: 640px) {
  .dive-spark {
    display: none;
  }
}

.admin-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}

/* ---------- Checklist rows ---------- */

/*
   44px minimum, which is Apple's own tap target and about the width of an
   adult fingertip. These rows were 30px — fine with a mouse, fiddly on the
   boat deck this list exists for.
*/
.checklist-card li label {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 2px 0;
  /* The whole row, not just the box — the label is what makes the text
     tappable too, and at this size that's most of the target. */
  cursor: pointer;
}
.checklist-card li label input[type="checkbox"] {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
}
