/* Default = Pumpkin Spice (light mode). Dark mode = Sunset Surf, applied by
   app.js via the header toggle / admin theme selector. These values must
   mirror the 'pumpkin-spice' preset in app.js THEMES. */
* { box-sizing: border-box; }
:root {
  --bg: #f5f0e8;          /* warm cream */
  --panel: #fff8f0;       /* lighter cream panel */
  --muted: #e8dcc8;       /* warm sand */
  --accent: #ff6b35;      /* the brand orange (chips, rings, highlights) */
  --accent-strong: #e85d2a;
  --text: #2d2416;        /* espresso ink */
  --ok: #2d8659;
  --warn: #a8560f;
  --input-bg: #ffffff;
  --input-border: #d4c4a8;
  --card-border: #d4c4a8;
  --on-accent: #ffffff;   /* text on button/active-tab fills — white passes on btn-bg */
  --accent-text: #b54a17; /* accent used AS text — darkened for light-bg contrast */
  --danger: #ff4444;      /* one red for all destructive UI */
  /* Button/active-tab fill: deeper than the brand orange so WHITE text passes
     WCAG (white on #ff6b35 is 2.8:1; on this pair it's 4.6-5.2:1). Themes
     without these fall back to accent/accent-strong. */
  --btn-bg: #d1470f;
  --btn-bg-strong: #c2410c;
  --money: #1e7a47;       /* pledged-dollars green (dark themes override lighter) */
}
html, body { margin: 0; padding: 0; height: 100%; background: var(--bg); color: var(--text); font: 15px/1.4 system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; }
.app-header, .app-footer { background: var(--panel); padding: 10px 14px; display: flex; align-items: center; gap: 12px; z-index: 10; border-bottom: 2px solid var(--accent); }
/* Wrapping header + swipeable tab strip: 6 tabs used to force the whole page
   to pan sideways on phones (490px document at a 375px viewport). */
.app-header { position: sticky; top: 0; left: 0; right: 0; justify-content: space-between; flex-wrap: wrap; row-gap: 2px; padding: 8px 12px; padding-top: calc(8px + env(safe-area-inset-top)); }
.app-footer { justify-content: space-between; font-size: 12px; opacity: 0.8; border-top: 2px solid var(--accent); border-bottom: none; padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
.brand { font-weight: 700; letter-spacing: 0.5px; color: var(--accent-text); display: inline-flex; align-items: center; gap: 8px; }
.brand-logo { width: 30px; height: 30px; display: block; }
.app-version { font-size: 11px; color: var(--text); opacity: 0.45; letter-spacing: 0.4px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.tabs { display: flex; gap: 8px; flex: 1 1 auto; justify-content: flex-end; overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; padding: 2px 0; }
.tabs::-webkit-scrollbar { display: none; }
.tabs a { color: var(--text); text-decoration: none; padding: 10px 12px; border-radius: 6px; background: transparent; transition: all 0.2s ease; flex: 0 0 auto; white-space: nowrap; }
.tabs a:hover { background: var(--muted); }
.tabs a.active { background: var(--btn-bg, var(--accent)); color: var(--on-accent); font-weight: 600; }
main { padding: 12px; display: block; }
.page { display: none; }
.page.active { display: block; }
.grid { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); margin-bottom: 12px; }
/* Grid items refuse to shrink below their content by default (min-width:auto),
   so the Type select's longest option overflowed its column and slid under the
   Duration inputs on desktop. Let controls shrink to their track instead. */
.grid label { min-width: 0; }
.grid input, .grid select, .grid textarea { min-width: 0; width: 100%; }
/* align-content start: without it a tall neighbor in the same .grid row
   (photo cell, textarea) stretches every input in the row to match */
label { display: grid; gap: 6px; font-size: 14px; align-content: start; }
.hidden { display: none !important; }
/* 16px on form controls is load-bearing: anything smaller makes iOS Safari
   auto-zoom on every field focus and strand the user zoomed-in. */
input, select, textarea { border-radius: 8px; border: 1px solid var(--input-border); background: var(--input-bg); color: var(--text); padding: 10px 12px; transition: all 0.2s ease; font-size: 16px; }
input[type="checkbox"] { accent-color: var(--accent); }
/* Theme-aware focus: a hardcoded navy here turned inputs near-black on light themes */
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); background: var(--input-bg); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent); }
input::placeholder, textarea::placeholder { color: color-mix(in srgb, var(--text) 45%, transparent); }
input:disabled, select:disabled, textarea:disabled { opacity: 0.5; cursor: not-allowed; }
/* Shadows follow the theme's accent — a fixed orange glow looked wrong on teal/blue/pink themes */
button { border-radius: 8px; padding: 10px 12px; font-size: 15px; transition: all 0.2s ease; background: linear-gradient(135deg, var(--btn-bg, var(--accent)) 0%, var(--btn-bg-strong, var(--accent-strong)) 100%); color: var(--on-accent); font-weight: 600; border: none; box-shadow: 0 4px 6px color-mix(in srgb, var(--accent) 30%, transparent); cursor: pointer; }
button:active { transform: translateY(2px); box-shadow: 0 2px 4px color-mix(in srgb, var(--accent) 30%, transparent); }
/* Button hierarchy: primary = accent gradient (default), secondary = quiet, warn = destructive */
button.btn-secondary { background: var(--muted); color: var(--text); border: 1px solid var(--card-border); box-shadow: none; }
button.warn { background: color-mix(in srgb, var(--danger) 16%, var(--panel)); color: var(--text); border: 1px solid color-mix(in srgb, var(--danger) 70%, var(--card-border)); box-shadow: none; }
button:focus-visible, a:focus-visible, summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Hover only where hover exists — on touch screens these stuck after every tap */
@media (hover: hover) and (pointer: fine) {
  button:hover { filter: brightness(1.1); }
  button.btn-secondary:hover { filter: brightness(1.12); }
  button.warn:hover { background: color-mix(in srgb, var(--danger) 28%, var(--panel)); filter: none; }
  .card:hover { transform: translateY(-2px); }
}
.tabs a { transition: all 0.2s ease; }
.tabs a:active { transform: translateY(1px); }
.card, .cards .card { transition: transform 0.2s ease; }

textarea { resize: vertical; }
.checkbox { align-items: center; grid-template-columns: 20px 1fr; }
.actions { display: flex; gap: 8px; }
.duration-inputs { display: flex; align-items: center; gap: 6px; }
.duration-inputs input { width: 70px; }
.card-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 8px; }
/* v1.39–v1.40.2: heavier borders on every card/panel — the 1px hairline
   washed out. Landed on 1.5px in a border ink nudged toward the text color
   (the % below is THE tuning knob; derives from the active theme's vars, so
   it tracks light/dark automatically). Known trade-off, chosen knowingly:
   Chrome FLOORS fractional border widths to whole device pixels, so a 1x
   monitor paints this as 1 physical pixel — the darker ink is what keeps it
   readable there; 2x/3x screens (every phone, Retina Macs) paint a true
   3-device-pixel line. */
:root { --card-border-mixed: color-mix(in srgb, var(--text) 18%, var(--card-border)); }
.card, .cards .card { background: var(--panel); border: 1.5px solid var(--card-border-mixed); border-radius: 12px; padding: 12px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18); }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 8px; }
.table { width: 100%; overflow-x: auto; }
.table table { width: 100%; border-collapse: collapse; }
.table th, .table td { text-align: left; padding: 10px 8px; border-bottom: 1px solid var(--card-border); font-size: 13px; }
.table th { color: var(--accent-text); font-weight: 600; }
.table td:first-child { white-space: nowrap; }
.hint { color: color-mix(in srgb, var(--text) 62%, transparent); }
.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12px; background: var(--muted); font-weight: 600; white-space: nowrap; }
.badge.platinum { background: linear-gradient(90deg, #e5e4e2, #b8b8b8); color: #000; font-weight: 700; border: 2px solid #ffd700; }
.badge.gold { background: linear-gradient(90deg, #ffd700, #ffb700); color: #000; }
.badge.silver { background: linear-gradient(90deg, #c0c0c0, #9e9e9e); color: #000; }
.badge.bronze { background: linear-gradient(90deg, #cd7f32, #b8722c); color: #241505; font-weight: 700; }
.badge.participant { background: linear-gradient(90deg, #48ba74, #339363); color: #06130c; font-weight: 700; }
.badge.ok { background: color-mix(in srgb, var(--ok) 20%, var(--panel)); color: var(--text); border: 1px solid var(--ok); }
.badge.frozen { background: color-mix(in srgb, #6ea8d8 22%, var(--panel)); color: var(--text); border: 1px solid #6ea8d8; }
pre { white-space: pre-wrap; word-wrap: break-word; }

/* Toasts */
.toast-container { position: fixed; bottom: calc(16px + env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%); z-index: 1000; display: grid; gap: 8px; width: min(92vw, 460px); }
.toast { padding: 12px 14px; border-radius: 10px; border: 1px solid var(--card-border); background: var(--panel); color: var(--text); box-shadow: 0 8px 24px rgba(0,0,0,0.25); display: flex; align-items: center; gap: 8px; }
/* Tinted from the theme panel so toast text stays readable on light themes too
   (older browsers without color-mix fall back to the plain panel background) */
.toast.success { border-color: var(--ok); background: color-mix(in srgb, var(--ok) 14%, var(--panel)); }
.toast.warn { border-color: var(--warn); background: color-mix(in srgb, var(--warn) 14%, var(--panel)); }
.toast.error { border-color: var(--danger); background: color-mix(in srgb, var(--danger) 14%, var(--panel)); }
.toast .close { padding: 10px; margin: -10px -10px -10px auto; opacity: .8; cursor: pointer; }

/* Live status */
.live { color: var(--ok); font-weight: 600; }

/* Edit icons and links — padding/negative-margin expands the tap target without moving layout.
   .edit-link is global (tiles use it outside .table) so it always reads as a link. */
.edit-link, .table .ev-view, .table .ev-activate { color: var(--accent-text); text-decoration: underline; cursor: pointer; }
.table .edit-link, .table .ev-view, .table .ev-activate { display: inline-block; padding: 8px 6px; margin: -8px -6px; }
.edit-link:hover, .table .ev-view:hover, .table .ev-activate:hover { color: var(--accent-strong); }
.table td.nowrap { white-space: nowrap; }

/* Heading hierarchy: accent for page titles, plain text for section heads —
   when everything was orange, nothing was */
h2 { color: var(--accent-text); font-size: 24px; margin: 8px 0 16px; }
h3 { color: var(--text); font-size: 16px; margin: 24px 0 10px; }
.card h3 { margin: 0 0 8px; }
.card p { margin: 0 0 10px; }

/* v1.5: events + audio notes */
.event-banner { background: color-mix(in srgb, var(--warn) 12%, transparent); border: 1px solid var(--warn); border-radius: 10px; padding: 10px 14px; margin-bottom: 12px; font-size: 14px; }
.event-banner a { color: var(--accent-text); }
.event-notice { margin-bottom: 10px; color: var(--warn); }
.event-scope { align-self: center; font-size: 13px; }
.filters { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; margin-bottom: 10px; }
#me-sessions audio { max-width: 230px; height: 32px; vertical-align: middle; }
#field-audio input[type="file"] { padding: 8px; }
#field-audio > label { margin-bottom: 6px; }
.audio-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
#btn-record-audio.recording { background: var(--danger); color: #fff; }
@media (prefers-reduced-motion: no-preference) {
  #btn-record-audio.recording { animation: rec-pulse 1.2s ease-in-out infinite; }
}
@keyframes rec-pulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 50%, transparent); } 50% { box-shadow: 0 0 0 8px transparent; } }
#audio-preview-wrap { display: flex; align-items: center; gap: 10px; margin-top: 6px; }
#audio-preview-wrap a { color: var(--accent-text); }
#audio-preview { max-width: 280px; height: 36px; }
button:disabled { opacity: 0.5; cursor: not-allowed; filter: none; }

/* v1.5.4: color scheme selector (Admin) */
.theme-grid { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.theme-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--muted); color: var(--text); border: 2px solid var(--card-border); box-shadow: none; font-weight: 500; padding: 8px 12px; }
.theme-chip.active { border-color: var(--accent); font-weight: 700; }
.theme-chip .sw { width: 14px; height: 14px; border-radius: 4px; border: 1px solid rgba(255, 255, 255, 0.25); display: inline-block; }
#theme-custom { margin-top: 8px; }
#theme-custom summary { cursor: pointer; color: var(--accent-text); }
#theme-custom.active summary::after { content: " (active)"; font-weight: 700; }
.theme-pickers { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; margin: 10px 0; }
.theme-pickers label { font-size: 12px; }
.theme-pickers input[type="color"] { padding: 2px; height: 36px; width: 100%; cursor: pointer; }

/* v1.5.5: log-form breathing room, Sessions sub-tabs, readable Journal column */
#field-audio { margin: 16px 0 6px; }
#field-audio > label { display: block; margin-bottom: 8px; }
#log-form .actions { margin-top: 20px; }
.subtabs { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.subtab { background: var(--muted); color: var(--text); box-shadow: none; border: 2px solid var(--card-border); font-weight: 600; }
/* subtabs rendered as <a> (Account → Awards/Admin) look like the buttons */
a.subtab { text-decoration: none; display: inline-block; padding: 10px 12px; border-radius: 8px; font-size: 15px; }
.subtab.active { background: linear-gradient(135deg, var(--accent) 0%, var(--accent-strong) 100%); border-color: transparent; color: #fff; }
.subtabs .event-scope { margin-left: auto; }
.view-toggle { display: inline-flex; gap: 4px; margin-left: 6px; }
.subtab.small { padding: 8px 10px; font-size: 13px; }
/* v1.33: "Session Log" heading + the List/Tiles toggle share one row — the
   toggle lives next to the list it controls instead of the page subtabs.
   v1.34: left-aligned as a group (space-between shoved the toggle to the far
   right edge on desktop, a screen-width away from the heading). */
.log-list-head { display: flex; align-items: center; justify-content: flex-start; gap: 14px; flex-wrap: wrap; margin: 24px 0 10px; }
.log-list-head h3 { margin: 0; }

/* v1.7: avatars + tile view */
.avatar { width: 48px; height: 48px; border-radius: 12px; object-fit: cover; border: 2px solid var(--card-border); }
.avatar-lg { width: 96px; height: 96px; margin-top: 6px; border-radius: 16px; }
/* v1.29: drag the Account preview to pick the avatar crop */
#profile-photo-preview { cursor: grab; touch-action: none; user-select: none; -webkit-user-drag: none; }
#profile-photo-preview.dragging { cursor: grabbing; }
.photo-nudge-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.photo-nudge-row button { padding: 6px 10px; font-size: 13px; }
/* v1.31: pinch/scroll crop editor — bakes a square 512px avatar from the
   2048px archive, so zooming gains real detail instead of upscaling. */
.crop-modal { position: fixed; inset: 0; z-index: 120; display: none; align-items: center; justify-content: center; background: rgba(0,0,0,0.72); padding: 16px; }
.crop-modal.open { display: flex; }
.crop-box { background: var(--panel); border: 1px solid var(--card-border); border-radius: 14px; padding: 16px; max-width: 340px; width: 100%; box-shadow: 0 12px 40px rgba(0,0,0,0.4); }
.crop-viewport { width: 280px; height: 280px; max-width: 100%; margin: 0 auto; overflow: hidden; border-radius: 16px; background: var(--muted); position: relative; touch-action: none; cursor: grab; }
.crop-viewport.dragging { cursor: grabbing; }
.crop-viewport img { position: absolute; top: 0; left: 0; transform-origin: 0 0; user-select: none; -webkit-user-drag: none; max-width: none; }
.crop-zoom-label { display: block; font-size: 13px; margin: 12px 0 4px; }
.crop-zoom-label input { width: 100%; }
.crop-hint { font-size: 12px; margin: 4px 0 12px; text-align: center; }
.crop-actions { display: flex; gap: 8px; }
.crop-actions button { flex: 1; }
.cam-viewport { width: 280px; height: 280px; max-width: 100%; margin: 0 auto; overflow: hidden; border-radius: 16px; background: #000; }
/* Mirrored preview (selfie convention); the CAPTURE is deliberately not
   mirrored — a flipped photo looks wrong to everyone but its subject. */
.cam-viewport video { width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1); }
.profile-head { display: flex; align-items: center; gap: 14px; }
.profile-head h3 { margin: 0; }
/* v1.58.1: the person card is the header of a surfer's page, so its photo
   matches the Account preview size (96px) instead of the 48px list avatar. */
.profile-head .avatar { width: 96px; height: 96px; border-radius: 16px; }
.fun-comment { font-style: italic; color: color-mix(in srgb, var(--text) 75%, transparent); margin: 8px 0 10px; }
#me-sessions .card-list { margin-top: 4px; }
#field-photo > label { margin-bottom: 8px; }
#log-start-time { width: 140px; justify-self: start; } /* a time is 8 chars — no need for a full column */

/* Post-submit stoke splash */
.celebrate { position: fixed; inset: 0; z-index: 2000; display: flex; align-items: center; justify-content: center; background: color-mix(in srgb, var(--bg) 55%, transparent); pointer-events: none; animation: celebrate-fade 1.1s ease forwards; }
.celebrate-inner { font-size: 26px; font-weight: 700; color: var(--text); background: var(--panel); border: 2px solid var(--accent); border-radius: 16px; padding: 18px 28px; box-shadow: 0 12px 40px color-mix(in srgb, var(--accent) 35%, transparent); animation: celebrate-pop 1.1s cubic-bezier(0.2, 0.9, 0.3, 1.15) forwards; }
@keyframes celebrate-fade { 0% { opacity: 0; } 12% { opacity: 1; } 80% { opacity: 1; } 100% { opacity: 0; } }
@keyframes celebrate-pop { 0% { transform: scale(0.6) translateY(24px); } 30% { transform: scale(1.06) translateY(-4px); } 55% { transform: scale(1) translateY(0); } 100% { transform: scale(1) translateY(-10px); } }
/* Journal entries are meant to be read, not squeezed into a sliver */
.table th.journal-cell { min-width: 340px; }
.table td.journal-cell { min-width: 340px; max-width: 560px; line-height: 1.5; }
@media (max-width: 640px) {
  .table th.journal-cell, .table td.journal-cell { min-width: 200px; }
}

/* v1.5.6: long journals clamp to 4 lines with a Show more toggle */
.journal-text { display: -webkit-box; -webkit-line-clamp: 4; line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; white-space: pre-wrap; }
.journal-text.expanded { display: block; -webkit-line-clamp: unset; line-clamp: unset; overflow: visible; }
.journal-more { display: inline-block; margin-top: 3px; color: var(--accent-text); font-size: 12px; text-decoration: underline; cursor: pointer; padding: 8px 6px; margin: -5px -6px -8px; }

/* v1.6: obvious edit mode — title swaps, actions dock to the header, form gets an accent ring */
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.page-head .actions { margin: 0; }
#log-form.editing { border: 2px solid var(--accent); border-radius: 12px; padding: 14px; background: color-mix(in srgb, var(--accent) 6%, transparent); }

/* v1.8.3: pledged total lives in the leaderboard page header */
/* The Main page's mid-page "Leaderboard" heading, right above the table */
.lb-heading { margin: 18px 0 4px; }

/* Conditions + Comment Board share a row on wide screens (stacked below 900px,
   chat first — the mobile order). Hidden members leave the other full-width. */
.lb-row { display: flex; flex-wrap: wrap; gap: 0 10px; align-items: flex-start; }
.lb-row > * { flex: 1 1 100%; min-width: 0; }
@media (min-width: 900px) {
  /* Equal heights: stretch subtracts an item's own margins, so the tiles'
     top/bottom margins move onto the row itself here */
  .lb-row { align-items: stretch; margin: 10px 0 16px; }
  .lb-row > * { flex: 1 1 0; }
  .lb-row > .surf-report { order: 1; display: flex; margin-bottom: 0; } /* OB info left… */
  .lb-row > .msg-board { order: 2; margin-top: 0; }                     /* …chat right */
  .lb-row > .surf-report .surf-strips { display: flex; flex: 1; }
  .lb-row > .surf-report .surf-strips .surf-main { flex: 1; margin-top: 0; }
}

/* Session Strip: per-session conditions card (expands under the session) */
.strip-link { color: var(--accent-text); white-space: nowrap; }
/* Multiple bonuses stack vertically in the table cell */
.badge-stack { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }
.session-strip-wrap { margin-top: 8px; }
.session-strip-wrap svg.session-strip { display: block; width: 100%; max-width: 280px; height: auto; }
tr.strip-row > td { padding: 6px 10px 14px; }

/* Crew message board tile (Leaderboard) */
.msg-board { background: var(--panel); border: 1.5px solid var(--card-border-mixed); border-radius: 12px; padding: 12px 14px; margin-top: 10px; }
/* v1.38: the title is a collapse toggle (a real <button>, restyled flat).
   Phones start collapsed — renderMessageBoard owns the state. */
.msg-title { font-weight: 700; margin-bottom: 8px; display: flex; align-items: center; gap: 6px; width: 100%; text-align: left; background: transparent; border: none; box-shadow: none; padding: 0; color: var(--text); font-size: 15px; cursor: pointer; }
.msg-title:active { transform: none; }
.msg-chevron { margin-left: auto; opacity: 0.65; transition: transform 0.15s ease; }
.msg-board.collapsed .msg-chevron { transform: rotate(-90deg); }
.msg-board.collapsed .msg-title { margin-bottom: 0; }
.msg-board.collapsed #msg-form, .msg-board.collapsed .msg-list { display: none; }
.msg-show-all { display: block; color: var(--accent-text); font-size: 13px; padding: 4px 0; }
.msg-row { display: flex; gap: 8px; }
.msg-row input { flex: 1; min-width: 0; }
.msg-wa { display: inline-flex; gap: 6px; align-items: center; font-size: 13px; margin-top: 8px; opacity: 0.9; }
.msg-wa input { width: auto; }
.msg-wa .wa-logo { width: 16px; height: 16px; vertical-align: -3px; margin-right: 2px; }
.msg-list { margin-top: 10px; max-height: 180px; overflow-y: auto; display: grid; gap: 10px; }
/* Phones: NO nested scrollbox — the inner scroll region ate page-scroll
   gestures (a thumb landing on the board scrolled the list, not the page).
   Natural height instead; renderMessageBoard caps how many render. */
@media (max-width: 640px) {
  .msg-list { max-height: none; overflow-y: visible; }
}
.msg:not(:last-child) { border-bottom: 1px solid var(--card-border); padding-bottom: 10px; }
.msg-meta { font-size: 12px; opacity: 0.75; margin-bottom: 2px; }
.msg-meta a { color: var(--accent-text); }
.msg-body { font-size: 14px; white-space: pre-wrap; overflow-wrap: anywhere; }

/* Totals tile: one card, dollars raised + hours surfed side by side */
.totals-tile { display: flex; flex-wrap: wrap; gap: 10px 0; margin-top: 10px; background: var(--panel); border: 1.5px solid var(--card-border-mixed); border-radius: 12px; padding: 10px 14px; }
.total-stat { flex: 1 1 140px; min-width: 0; }
.total-stat + .total-stat { border-left: 1px solid var(--card-border); padding-left: 18px; margin-left: 18px; }
.total-label { display: block; font-size: 11px; letter-spacing: 1.2px; text-transform: uppercase; opacity: 0.65; }
.total-value { font-size: 24px; font-weight: 800; line-height: 1.3; display: inline-flex; align-items: center; gap: 7px; }
.total-value.money { color: var(--money, #1e7a47); }
.money-icon { width: 21px; height: 21px; flex: 0 0 auto; }

/* v1.8.2: Ocean Beach surf report on the leaderboard */
.surf-report { margin-bottom: 16px; }
/* v1.10: combined conditions + tide card with the Hoff-o-meter */
/* v1.40: Main-page panels match the app-wide card border weight (totals
   tile, Comment Board, conditions/today cards — .surf-main is the last two) */
.surf-main { background: var(--panel); border: 1.5px solid var(--card-border-mixed); border-radius: 12px; padding: 10px 12px; min-width: 0; }
.surf-main-top { display: flex; justify-content: space-between; align-items: flex-end; gap: 12px; }
.surf-main-left { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; align-self: flex-start; }
.surf-wind { display: inline-flex; align-items: center; gap: 5px; font-size: 13px; font-weight: 600; }
.surf-wind svg { width: 15px; height: 17px; flex: 0 0 auto; }
.surf-main-right { display: flex; align-items: flex-end; gap: 12px; min-width: 0; }
.surf-main-height { text-align: right; }
.surf-label { font-size: 13px; font-weight: 600; opacity: 0.85; }
.surf-chip { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; color: #10202e; white-space: nowrap; }
.surf-ft { font-size: 20px; font-weight: 800; }
.surf-rel { font-size: 12px; opacity: 0.7; }
.hoff { position: relative; width: 28px; overflow: hidden; flex: 0 0 auto; }
.hoff-fig { position: absolute; left: 0; width: 100%; height: 64px; }
.hoff-fig svg { display: block; width: 100%; height: 100%; }
.hoff-waterline { position: absolute; top: 0; left: 0; right: 0; height: 2px; border-radius: 2px; opacity: 0.85; }
.surf-main-tide { margin-top: 10px; border-top: 1px solid var(--card-border); padding-top: 8px; }
.surf-main-tide .surf-tide-text { font-size: 13px; margin-top: 6px; }

/* v1.9.3: tide + water share a row when the page is wide enough */
.surf-strips .surf-main { margin-top: 10px; }

/* v1.9: tide curve + now-dot (curve fills the combined card's width) */
.surf-tide-curve { position: relative; }
.surf-tide-curve svg { width: 100%; height: 34px; display: block; color: var(--text); }
.surf-tide-now { position: absolute; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); transform: translate(-50%, -50%); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 30%, transparent); }
/* Water-quality line sits along the bottom of the conditions card, divided
   from the tide (the Surfline credit stays above the divider) */
.surf-water { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; border-top: 1px solid var(--card-border); padding-top: 10px; font-size: 13px; }
.water-drop { width: 15px; height: 15px; flex: 0 0 auto; color: #3d9bd6; }
.surf-card-meta { margin-top: 8px; font-size: 12px; opacity: 0.7; }
.surf-card-meta a { color: var(--accent-text); }
.bwtf-link { white-space: nowrap; }
/* v1.50: tide + water quality share one row under the conditions (Chase:
   fine if the tide curve gets squished); each column keeps its own credit line */
.surf-row2 { display: flex; gap: 12px; margin-top: 10px; border-top: 1px solid var(--card-border); padding-top: 8px; }
.surf-col { flex: 1 1 0; min-width: 0; }
.surf-col + .surf-col { border-left: 1px solid var(--card-border); padding-left: 12px; }
.surf-col .surf-main-tide, .surf-col .surf-water { margin-top: 0; border-top: 0; padding-top: 0; }
.surf-col .surf-card-meta { margin-top: 6px; }
/* v1.50: today tile header — day label + "See All Sessions" link */
.today-title { display: inline-flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.today-all-link { font-size: 12px; font-weight: 600; color: var(--accent-text); text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.bwtf-mark { width: 14px; height: 14px; vertical-align: -3px; }

/* v1.9.2: medal thresholds as real chips instead of a text line */
.medal-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 14px; }
.medal-key { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: color-mix(in srgb, var(--text) 72%, transparent); white-space: nowrap; }

/* v1.11: dark/light toggle in the header */
.mode-toggle { background: transparent; border: 1px solid transparent; box-shadow: none; padding: 8px 10px; font-size: 17px; line-height: 1; flex: 0 0 auto; }
.mode-toggle:hover { background: var(--muted); filter: none; }
.mode-toggle:active { transform: translateY(1px); box-shadow: none; }

/* v1.12: "Today at Surftober" tile under the OB conditions row */
#today-tile .surf-main { margin-top: 10px; }
.today-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.today-stat { font-size: 14px; }
.today-feature { margin-top: 8px; border-top: 1px solid var(--card-border); padding-top: 8px; }
.today-feature-head { font-size: 12px; opacity: 0.75; }
.today-quote { margin: 6px 0 4px; font-size: 14px; font-style: italic; line-height: 1.45; }
.today-feature audio { width: 100%; max-width: 420px; margin-top: 4px; display: block; }

/* v1.12.1: flame streak icon + sortable leaderboard headers */
.streak-cell { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; }
.streak-icon { width: 13px; height: 13px; color: var(--accent); flex: 0 0 auto; }
th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.sort-arrow { opacity: 0.85; }

/* v1.12.2: iOS date/time inputs have an intrinsic native width that
   overflows narrow grid columns — flatten to plain fields */
input[type="date"], input[type="time"] { -webkit-appearance: none; appearance: none; min-width: 0; max-width: 100%; }
/* Static "Name" display on the log form (name is profile-owned, not editable here) */
.log-as { display: grid; gap: 6px; font-size: 14px; align-content: start; }
.log-as strong { font-size: 16px; padding: 10px 0; }

/* v1.49.0: browsable today tile — ONE pair of full-height edge arrows walks
   the session timeline left-to-right in time (‹ older, rolling into the
   previous day; › newer) */
.today-card { display: flex; align-items: stretch; gap: 0; padding: 0; overflow: hidden; }
.today-body { flex: 1 1 auto; min-width: 0; padding: 10px 10px; }
.today-edge { flex: 0 0 30px; display: flex; align-items: center; justify-content: center; padding: 0; margin: 0; border: 0; border-radius: 0; background: var(--muted); color: var(--text); box-shadow: none; font-size: 24px; font-weight: 700; line-height: 1; cursor: pointer; }
.today-edge:first-child { border-right: 1px solid var(--card-border); }
.today-edge:last-child { border-left: 1px solid var(--card-border); }
.today-edge:hover:not(:disabled) { background: var(--card-border); }
.today-edge:active { transform: none; box-shadow: none; }
.today-edge:disabled { opacity: 0.3; cursor: default; }
.today-sess-count { font-size: 12px; white-space: nowrap; opacity: 0.9; }
.today-feature-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }
.today-user { color: var(--accent-text); font-weight: 700; text-decoration: underline; text-underline-offset: 2px; }

/* v1.13: bonuses dropdown + session-type hint */
.type-hint { font-size: 12px; line-height: 1.4; }
.bonus-dd { position: relative; }
.bonus-dd summary { list-style: none; cursor: pointer; user-select: none; border: 1px solid var(--input-border); background: var(--input-bg); border-radius: 8px; padding: 10px 12px; font-size: 16px; }
.bonus-dd summary::-webkit-details-marker { display: none; }
.bonus-dd summary::after { content: '▾'; float: right; opacity: 0.6; }
.bonus-dd[open] summary { border-color: var(--accent); }
.bonus-menu { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30; background: var(--panel); border: 1px solid var(--card-border); border-radius: 10px; padding: 12px; display: grid; gap: 12px; box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28); }
.bonus-menu .checkbox { margin: 0; font-weight: 400; }
.bonus-menu .checkbox strong { font-weight: 700; }

/* v1.16: session photos + crew album link */
a.mode-toggle { display: inline-flex; align-items: center; border-radius: 8px; text-decoration: none; }
.session-photo-thumb { width: 56px; height: 56px; object-fit: cover; border-radius: 8px; display: block; border: 1px solid var(--card-border); }
.session-photo-card { width: 100%; max-height: 340px; object-fit: cover; border-radius: 10px; display: block; margin: 6px 0; border: 1px solid var(--card-border); }
/* Desktop: don't stretch photos across the whole tile (a wide tile + the
   340px cap crops them badly) — show a smaller natural-ratio image instead;
   tap still opens the original. Phones keep the full-width look. */
@media (min-width: 641px) {
  .session-photo-card { width: auto; max-width: min(420px, 100%); }
}
/* v1.27: full-size photo overlay (replaces opening a new tab) */
.photo-lightbox {
  position: fixed; inset: 0; z-index: 100; display: none;
  align-items: center; justify-content: center; padding: 24px;
  background: rgba(0, 0, 0, 0.82); cursor: zoom-out;
}
.photo-lightbox.open { display: flex; }
.photo-lightbox img {
  max-width: 100%; max-height: 100%; width: auto; height: auto;
  border-radius: 10px; cursor: default;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
}
.photo-lightbox-close {
  position: absolute; top: 12px; right: 14px; z-index: 1;
  width: 40px; height: 40px; padding: 0; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.35); background: rgba(0, 0, 0, 0.45);
  color: #fff; font-size: 18px; line-height: 1; cursor: pointer;
}
.photo-lightbox-close:hover { background: rgba(0, 0, 0, 0.7); }
/* Don't let the page scroll behind the overlay (mobile especially) */
body.lightbox-open { overflow: hidden; }
a.photo-zoom { cursor: zoom-in; display: inline-block; }
#photo-preview { max-width: 220px; max-height: 220px; border-radius: 10px; display: block; margin: 8px 0 4px; border: 1px solid var(--card-border); }
#photo-preview-wrap a { font-size: 13px; }
/* Photo field mirrors the audio field's layout so the two stack evenly */
#field-session-photo { margin: 16px 0 6px; }
#field-session-photo > label { display: block; margin-bottom: 8px; }
#field-session-photo a { color: var(--accent-text); }
.photo-controls { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* v1.42: logo + wordmark link to Main; Today-tile fallback note. (The
   phone bottom tab bar lives on the mobile-nav branch until it's approved.) */
.brand-link { display: inline-flex; align-items: center; gap: 8px; color: inherit; text-decoration: none; }
.today-fallback { font-size: 12px; margin-top: 4px; }

/* Account → Navigation card: the bottom-bar/header-tabs choice only exists on
   phones (the bar CSS below is ≤640px), so hide the control on wider screens
   instead of showing one that does nothing. */
.nav-style-toggle { margin-bottom: 0; }
@media (min-width: 641px) { .nav-style-card { display: none; } }

/* Bottom tab bar on phones (Chase's board idea, 2026-08-17; shipped v1.43.0).
   The two-row sticky header ate ~100px of every phone screen — nav moves to
   thumb reach and the header becomes one slim row. Desktop keeps tabs inline.
   The single <nav class="tabs"> serves both layouts (CSS only), so the
   viewer/admin tab-visibility logic in app.js is untouched. */
/* Bottom tab bar — only when <html class="bottom-nav">, set by the
   MOBILE_BOTTOM_NAV flag in the <head> of index.html (see there). Without
   the class, phones get the original header tabs. */
@media (max-width: 640px) {
  html.bottom-nav .tabs { position: fixed; left: 0; right: 0; bottom: 0; z-index: 50; margin: 0; padding: 6px 8px calc(6px + env(safe-area-inset-bottom)); background: var(--panel); border-top: 2px solid var(--accent); justify-content: space-around; gap: 4px; overflow: visible; }
  html.bottom-nav .tabs a { flex: 1 1 0; text-align: center; padding: 11px 4px; font-size: 14px; line-height: 1.2; border-radius: 10px; }
  html.bottom-nav .app-header { flex-wrap: nowrap; }
  /* keep the footer text and toasts clear of the bar */
  html.bottom-nav .app-footer { padding-bottom: calc(10px + 72px + env(safe-area-inset-bottom)); }
  html.bottom-nav .toast-container { bottom: calc(16px + 72px + env(safe-area-inset-bottom)); }
}

/* Sessions → Other Surfers → "All surfers": the surfer's name on each tile/row */
.tile-surfer { margin-bottom: 2px; }
.surfer-link { color: var(--accent); font-weight: 700; text-decoration: none; }
.surfer-link:hover { text-decoration: underline; }

/* v1.51: compact header for phones on the HEADER-TABS nav style (bottom-nav
   flag off / "Header tabs" in Account). Wordmark hidden (icon stays the link
   to Main), toggle + album moved to the top of Main by app.js, so the icon
   and all four tabs share one header row. Bottom-bar mode and desktop are
   untouched. */
/* v1.52: Main header row — title · relocated tools (phones, header-tabs
   mode) · "Jump to leaderboard" (all devices). Wraps on narrow screens. */
.main-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 0 6px; }
.main-title { margin: 0; font-size: 1.3rem; }
.main-tools { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 14px; margin: 0 0 10px; }
.main-tools[hidden] { display: none; }
/* A "tool" = icon button/link + its text label, moved as one unit between the
   header and Main. Labels show wherever the tool lives, except in the header
   on phones with the bottom bar (no room next to the wordmark). */
.tool { display: inline-flex; align-items: center; gap: 2px; }
.tool[hidden] { display: none; }
.tool-label { font-size: 12px; font-weight: 500; letter-spacing: 0; color: var(--accent-text); text-decoration: none; cursor: pointer; white-space: nowrap; }
.tool-label:hover { text-decoration: underline; }
/* hovering anywhere on a tool (text or icon) shades its icon and underlines
   its text — the album tool's text is a plain link, so it can't borrow the
   <label for> hover the theme tool gets for free */
.tool:hover .mode-toggle { background: var(--muted); }
.tool:hover .tool-label { text-decoration: underline; }
@media (max-width: 640px) { html.bottom-nav .brand .tool-label { display: none; } }
.jump-leaderboard { font-size: 13px; font-weight: 600; color: var(--accent-text); text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.lb-heading { scroll-margin-top: 72px; } /* clears the sticky header when jumped to */
/* desktop: let the header icons breathe next to the wordmark */
@media (min-width: 641px) { .brand-link { margin-right: 8px; } }
@media (max-width: 640px) {
  html:not(.bottom-nav) .app-header { flex-wrap: nowrap; gap: 8px; }
  html:not(.bottom-nav) .brand-name { display: none; }
  html:not(.bottom-nav) .tabs { justify-content: flex-end; gap: 4px; } /* right-justified, not spread (Chase) */
  html:not(.bottom-nav) .tabs a { padding: 10px 9px; font-size: 14px; }
}
