/* ── STAGE PANEL ──────────────────────────────────────────────────────────────
   Shared styles for all "stage" panels — draggable floating overlays that
   co-exist with the main workspace and can expand to full-screen.

   Current stages: Report (report.js), Food (food-stage.js)

   Naming convention:
     .stage-*   — structural / shared (this file)

   Cally style (.stage-cally-*) mirrors reflect.css exactly — single visual
   language across all panels. reflect.css is the master reference.

   Fixed bottom-right by default; draggable anywhere via .stage-panel-header.
   No dark overlay — user sees the day grid behind it.
   Expanded mode: full-height, centered at 600px, black on sides via box-shadow.
   ─────────────────────────────────────────────────────────────────────────── */

.stage-panel {
    position: fixed;
    bottom: 60px;
    right: 20px;
    width: 340px;
    background: var(--bg-panel);
    border: 1px solid var(--box-border);
    border-radius: 12px;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
    z-index: 500;
    overflow: hidden;
    animation: cp-fade-in 0.15s ease;
}

.stage-panel-hidden {
    display: none !important;
}

/* ── Header / drag handle ── */
.stage-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px 10px;
    border-bottom: 1px solid var(--box-border);
    cursor: grab;
    user-select: none;
    position: relative;
    min-height: 52px;
}

.stage-panel-header:active { cursor: grabbing; }
.stage-panel.stage-is-dragging .stage-panel-header { cursor: grabbing; }

/* ── Expanded (full-screen) state ── */
.stage-panel.stage-panel-expanded {
    top:        0 !important;
    left:       50% !important;
    right:      auto !important;
    bottom:     0 !important;
    width:      100% !important;
    max-width:  600px;
    transform:  translateX(-50%);
    max-height: 100vh;
    max-height: 100dvh; /* iOS Safari: dvh excludes browser chrome, vh does not */
    border-radius: 0;
    z-index: 800;
    box-shadow: 0 0 0 100vw rgba(0, 0, 0, 0.85);
    overflow: hidden; /* keep clipping; inner body handles its own scroll */
}

.stage-panel.stage-panel-expanded .stage-panel-body {
    max-height: calc(100vh - 56px);
    max-height: calc(100dvh - 56px); /* iOS Safari dvh fix */
}

/* ── Header actions group ── */
.stage-header-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

.stage-expand-btn { padding: 4px; }

.stage-header-left {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.stage-title {
    font-size: 0.8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1px;
    color: var(--text-muted);
}

.stage-date {
    font-size: 0.78rem;
    color: var(--accent-color);
    font-weight: 500;
    letter-spacing: 0.2px;
}

/* ── Scrollable body ── */
.stage-panel-body {
    padding: 12px 16px 16px;
    max-height: 70vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch; /* iOS: momentum scroll inside fixed panel */
    overscroll-behavior: contain;       /* prevent scroll chaining to page */
    scrollbar-width: thin;
    scrollbar-color: var(--box-border) var(--bg-main);
}

.stage-panel-body::-webkit-scrollbar         { width: 4px; }
.stage-panel-body::-webkit-scrollbar-track   { background: var(--bg-main); }
.stage-panel-body::-webkit-scrollbar-thumb   { background-color: var(--box-border); border-radius: 2px; }

/* Report panel — extra bottom padding so last content item is never clipped.
   Both daily and weekly views need breathing room so the user can scroll the
   final line fully into view. 56px = comfortable thumb-sized gap. */
#report-panel .stage-panel-body {
    padding-bottom: 56px;
}

/* ── Section divider HR ── */
.stage-section-divider {
    border: none;
    border-top: 1px solid var(--box-border);
    margin: 4px 0 16px;
    opacity: 0.5;
}

/* ── Shared section wrapper ── */
.stage-section { margin-bottom: 16px; }

.stage-section-label {
    display: block;
    font-size: 0.72rem;
    font-weight: 600;
    color: color-mix(in srgb, var(--text-main) 50%, transparent);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 6px;
}

/* Larger variant — used for LOG FOOD heading */
.stage-section-label-lg {
    font-size: 0.82rem;
    margin-bottom: 10px;
}

/* ── Generic text input ── */
.stage-goal-input {
    width: 100%;
    box-sizing: border-box;
    resize: none;
}

/* ── Activity / content header row ── */
.stage-content-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}

.stage-content-header .stage-section-label { margin-bottom: 0; }

/* ── Stars ── */
.stage-stars-row {
    display: flex;
    gap: 5px;
    align-items: center;
    cursor: pointer;
    border-radius: 4px;
    padding: 2px 4px;
    transition: opacity 0.1s;
}

.stage-stars-row:hover { opacity: 0.75; }
.stage-stars-row:focus { outline: 2px solid var(--accent-color); outline-offset: 2px; }

.stage-star {
    width: 13px;
    height: 13px;
    image-rendering: pixelated;
    filter: var(--icon-accent-filter);
    opacity: 0.2;
}

/* Stars 2× in expanded view */
.stage-panel.stage-panel-expanded .stage-star {
    width: 26px;
    height: 26px;
}

/* ── Activity rings grid (Report) ── */
.stage-rings-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px 6px;
}

/* Expanded: 4+3 two-row layout, 2× ring size */
.stage-panel.stage-panel-expanded .stage-rings-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 20px 10px;
    max-width: 100%;
}

.stage-ring-cell {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.stage-ring-wrap {
    position: relative;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
}

.stage-panel.stage-panel-expanded .stage-ring-wrap {
    width: 80px;
    height: 80px;
}

.stage-ring-svg {
    width: 44px;
    height: 44px;
    transform: rotate(-90deg);
    overflow: visible;
}

.stage-panel.stage-panel-expanded .stage-ring-svg {
    width: 80px;
    height: 80px;
}

.stage-ring-track {
    fill: none;
    stroke: color-mix(in srgb, var(--accent-color) 12%, transparent);
    stroke-width: 3.5;
}

.stage-ring-fill {
    fill: none;
    stroke: var(--accent-color);
    stroke-width: 3.5;
    stroke-linecap: round;
    transition: stroke-dashoffset 0.45s ease;
}

.stage-ring-icon {
    position: absolute;
    inset: 0;
    width: 20px;
    height: 20px;
    margin: auto;
    image-rendering: pixelated;
    object-fit: contain;
    filter: var(--icon-accent-filter);
    opacity: 0.85;
}

.stage-panel.stage-panel-expanded .stage-ring-icon { width: 36px; height: 36px; }

.stage-ring-label {
    font-size: 0.64rem;
    color: var(--text-muted);
    text-align: center;
    white-space: nowrap;
    line-height: 1.2;
}

.stage-panel.stage-panel-expanded .stage-ring-label { font-size: 0.82rem; }

.stage-ring-hours {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--accent-color);
    line-height: 1;
}

.stage-panel.stage-panel-expanded .stage-ring-hours { font-size: 0.9rem; }

.stage-ring-none {
    font-size: 0.7rem;
    color: var(--text-muted);
    opacity: 0.4;
    line-height: 1;
}

.stage-panel.stage-panel-expanded .stage-ring-none { font-size: 0.88rem; }

/* ── Food: "Today" section — rings LEFT (centered), goals RIGHT (~30%) ──────
   Default (collapsed 340px): rings take natural width, goals fill remainder.
   Expanded (600px): rings column is 70% of content, goals start at ~70%.
   ─────────────────────────────────────────────────────────────────────────── */
.stage-today-layout {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}

.stage-today-rings {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center; /* rings centered within their column */
    gap: 10px;
}

/* Expanded: rings column takes 70%, goals get remaining 30% */
.stage-panel.stage-panel-expanded .stage-today-rings {
    flex: 0 0 68%;
    align-items: center;
}

.stage-today-goals {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding-top: 2px;
}

.stage-today-goals .stage-section-label { margin-bottom: 0; }

/* ── Big display rings (Food: calorie + protein) ── */
.stage-big-ring-wrap {
    position: relative;
    flex-shrink: 0;
}

/* 110% of original sizes → rounded to clean px values */
.stage-big-ring-wrap.is-cal {
    width: 130px;
    height: 130px;
}

.stage-big-ring-wrap.is-protein {
    width: 90px;
    height: 90px;
}

.stage-big-ring-svg {
    width: 100%;
    height: 100%;
    transform: rotate(-90deg);
    overflow: visible;
}

.stage-big-ring-track {
    fill: none;
    stroke: color-mix(in srgb, var(--accent-color) 12%, transparent);
    stroke-width: 5;
}

.stage-big-ring-fill {
    fill: none;
    stroke: var(--accent-color);
    stroke-width: 5;
    stroke-linecap: round;
    transition: stroke-dashoffset 0.45s ease;
}

.stage-big-ring-center {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    pointer-events: none;
}

.stage-big-ring-number {
    font-weight: 700;
    color: var(--text-main);
    line-height: 1;
}

.stage-big-ring-wrap.is-cal     .stage-big-ring-number { font-size: 1.55rem; }
.stage-big-ring-wrap.is-protein .stage-big-ring-number { font-size: 1.05rem; }

.stage-big-ring-unit {
    font-size: 0.62rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    line-height: 1;
}

/* ── Food goals (right column of today layout) ── */
.stage-goal-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.stage-goal-field label {
    font-size: 0.68rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
}

.stage-goal-number-input {
    width: 60%;
    box-sizing: border-box;
    text-align: center;
    font-size: 0.9rem;
    font-weight: 600;
}

/* ── Food entry form ─────────────────────────────────────────────────────────
   Row 1: food name full width
   Row 2: Calories | Protein | Weight+unit — equal flex, 90px gap in expanded
   ─────────────────────────────────────────────────────────────────────────── */
.stage-food-form {
    display: flex;
    flex-direction: column;
    gap: 0; /* spacing handled per-element below */
}

.stage-food-name-input {
    width: 100%;
    box-sizing: border-box;
    margin-bottom: 12px; /* padding between food input and cal/protein row */
}

/* Row 2: all three fields in one line */
.stage-food-cpw-row {
    display: flex;
    align-items: flex-end;
    gap: 8px; /* collapsed default */
}

/* Expanded: ~90px (15% of 600px) gap between cal→protein and protein→weight */
.stage-panel.stage-panel-expanded .stage-food-cpw-row {
    gap: 90px;
}

.stage-food-input-wrap {
    display: flex;
    flex-direction: column;
    gap: 3px;
    flex: 1;
    min-width: 0;
}

/* Weight+unit wrapper keeps the unit select inline */
.stage-food-input-wrap.is-weight {
    flex: 0 0 auto; /* don't stretch — weight takes natural width */
}

.stage-food-input-label {
    font-size: 0.65rem;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.4px;
    white-space: nowrap;
}

.stage-food-weight-row {
    display: flex;
    gap: 3px;
    align-items: center;
}

.stage-food-weight-row input {
    width: 52px;
    flex: 0 0 auto;
}

.stage-food-unit-select {
    flex: 0 0 auto;
    font-size: 0.7rem;
    padding: 4px 3px;
    background: var(--bg-input);
    border: 1px solid var(--box-border);
    border-radius: 6px;
    color: var(--text-muted);
    cursor: pointer;
}

.stage-food-add-btn {
    width: 100%;
    margin-top: 16px;    /* space above */
    margin-bottom: 24px; /* big space below before Log */
    padding: 12px;       /* taller button */
    border-radius: 8px;
    font-size: 0.8rem;
    font-weight: 600;
    background: var(--accent-color);
    color: var(--bg-dark, #0a0a0a);
    border: none;
    cursor: pointer;
    transition: opacity 0.15s;
    letter-spacing: 0.3px;
}

.stage-food-add-btn:hover   { opacity: 0.85; }
.stage-food-add-btn:active  { opacity: 0.7; }
.stage-food-add-btn:disabled { opacity: 0.35; cursor: not-allowed; }

/* ── Cally nudge ─────────────────────────────────────────────────────────────
   Mirrors reflect.css EXACTLY — this is the master visual language for Cally
   across all panels. If reflect.css changes, update here too.

   Layout: [bubble text] → [sprite icon]
   Bubble: var(--bg-panel) bg, 1px accent border, right-pointing tail
   Sprite: 48px, padding-left 10px (matching reflect-cally-sprite)
   ─────────────────────────────────────────────────────────────────────────── */

.stage-cally-row {
    display: flex;
    align-items: center;
    margin: 10px 0 24px 0; /* extra bottom margin = padding above log section */
    gap: 0;
}

.stage-cally-bubble {
    position: relative;
    flex: 1;
    margin-right: 8px;
    background: var(--bg-panel);
    border: 1px solid var(--accent-color);
    border-radius: 8px;
    padding: 8px 10px;
    min-height: 40px;
    display: flex;
    align-items: center;
}

/* Tail — border layer, pointing right toward sprite */
.stage-cally-bubble::after {
    content: '';
    position: absolute;
    right: -8px;
    top: 50%;
    transform: translateY(-50%);
    border-width: 7px 0 7px 8px;
    border-style: solid;
    border-color: transparent transparent transparent var(--accent-color);
}

/* Tail — fill layer (covers with bg-panel colour) */
.stage-cally-bubble::before {
    content: '';
    position: absolute;
    right: -6px;
    top: 50%;
    transform: translateY(-50%);
    border-width: 6px 0 6px 7px;
    border-style: solid;
    border-color: transparent transparent transparent var(--bg-panel);
    z-index: 1;
}

.stage-cally-bubble-text {
    font-size: 0.78rem;
    color: var(--accent-color);
    margin: 0;
    line-height: 1.4;
}

/* Sprite — matches reflect-cally-sprite exactly */
.stage-cally-sprite {
    width: 48px;
    height: 48px;
    image-rendering: pixelated;
    object-fit: contain;
    flex-shrink: 0;
    padding-left: 10px;
    filter: var(--icon-accent-filter);
}

/* ── Report: activity log star picker ── */
/* Separate class from .stage-star so reportRender()'s day-rating update
   doesn't accidentally touch these interactive picker stars. */
.report-activity-star {
    width: 20px;
    height: 20px;
    image-rendering: pixelated;
    cursor: pointer;
    filter: var(--icon-accent-filter);
    opacity: 0.2;
    transition: opacity 0.1s, transform 0.1s;
}

.report-activity-star:hover { transform: scale(1.2); opacity: 0.7; }

/* ★/☆ unicode display in the activity log list */
.report-activity-star-display {
    color: var(--accent-color);
    letter-spacing: 1px;
}

/* Log button — compact inline variant (not full-width like stage-food-add-btn) */
.report-activity-log-btn {
    flex-shrink: 0;
    padding: 7px 18px;
    border-radius: 7px;
    font-size: 0.78rem;
    font-weight: 600;
    background: var(--accent-color);
    color: var(--bg-dark, #0a0a0a);
    border: none;
    cursor: pointer;
    opacity: 0.35;
    transition: opacity 0.15s;
    letter-spacing: 0.3px;
}

.report-activity-log-btn:not(:disabled) { opacity: 1; }
.report-activity-log-btn:hover:not(:disabled) { opacity: 0.85; }
.report-activity-log-btn:active:not(:disabled) { opacity: 0.7; }

/* ── Log Activity section — extra breathing room ── */
.report-log-activity-section {
    padding-top: 6px;
    padding-bottom: 10px;
}

/* Controls row: quick emojis + [+] on left | stars on right */
.report-activity-controls-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
}

/* Quick emoji wrapper: flex:1 so it takes available space, never overflows into stars */
.report-quick-emoji-wrap {
    display: flex;
    align-items: center;
    gap: 3px;
    flex: 1;
    min-width: 0;
}

.report-quick-emoji-slots {
    display: flex;
    gap: 2px;
}

/* 28px slots: 5×28 + 4×2 + 3 + 28([+]) = 199px left; 5×18 + 4×4 = 106px stars → 305px < 308px ✓ */
.report-quick-emoji-slot {
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    cursor: pointer;
    border: 2px solid transparent;
    transition: border-color 0.12s, background 0.12s;
    flex-shrink: 0;
}

.report-quick-emoji-slot:hover {
    background: color-mix(in srgb, var(--accent-color) 10%, transparent);
}

.report-quick-emoji-selected {
    border-color: var(--accent-color);
    background: color-mix(in srgb, var(--accent-color) 15%, transparent);
}

.report-emoji-expand-btn {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 2px solid var(--accent-color);
    background: transparent;
    color: var(--accent-color);
    font-size: 1.1rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    transition: background 0.12s;
}

.report-emoji-expand-btn:hover {
    background: color-mix(in srgb, var(--accent-color) 15%, transparent);
}

/* flex-shrink:0 guarantees all 5 stars are always visible */
.report-activity-stars-group {
    display: flex;
    gap: 4px;
    align-items: center;
    flex-shrink: 0;
}

/* 18px stars in this row: 5×18 + 4×4 = 106px */
.report-activity-controls-row .report-activity-star {
    width: 18px;
    height: 18px;
}

/* No color filter on emoji images — ever */
.report-quick-emoji-img {
    filter: none !important;
    image-rendering: pixelated;
}

/* ── Emoji toggle button ── */
.report-emoji-toggle-btn {
    padding: 4px;
    flex-shrink: 0;
}

/* ── Emoji picker grid ── */
.emoji-picker-grid {
    display: grid;
    grid-template-rows: repeat(6, 1fr); /* 6 rows → items fill down each column */
    grid-auto-flow: column;              /* column 1 fills first, then column 2, etc. */
    gap: 4px;
    padding: 8px;
    background: var(--bg-input);
    border: 1px solid var(--box-border);
    border-radius: 8px;
    margin-bottom: 4px;
}

/* display:grid beats the browser's built-in [hidden]{display:none} — override it */
.emoji-picker-grid[hidden] {
    display: none !important;
}

.emoji-picker-tile {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 6px;
    cursor: pointer;
    border: 2px solid transparent;
    transition: border-color 0.1s, background 0.1s;
}

.emoji-picker-tile:hover {
    background: color-mix(in srgb, var(--accent-color) 12%, transparent);
}

.emoji-picker-tile-selected {
    border-color: var(--accent-color);
    background: color-mix(in srgb, var(--accent-color) 15%, transparent);
}

/* ── Emoji images — NO color filter, ever ────────────────────────────────────
   Emojis are explicitly colored pixel-art. They must NEVER receive the
   --icon-accent-filter tint used by regular icons for theme coloring.
   filter:none !important is Layer 2 (Layer 1 = el.style.filter='none' set
   inline by emojiApplyToElement). Never assign .stage-star, .stage-ring-icon,
   .stage-cally-sprite, .report-activity-star, or any class that carries
   filter:var(--icon-accent-filter) to an emoji element. ─────────────────────── */
.emoji-picker-img,
.report-log-emoji,
.emoji-toggle-img {
    filter: none !important;
    image-rendering: pixelated;
}

/* ── Activity log entry: emoji + text side by side ── */
.report-log-content-row {
    display: flex;
    align-items: center;
    gap: 5px;
    flex-wrap: wrap;
    min-width: 0;
}

.report-log-content-row .stage-log-text {
    flex: 1;
    min-width: 0;
}

/* ── Activity log entry: source label (spotlight-logged entries only) ─────────
   Shown above the entry content when entry.activityLabel is set.
   Identifies which activity the entry was logged against
   (e.g. "Cable SA Lateral Raise") so the report log has context.
   Uses accent color at reduced opacity — present but not dominant. ─────────── */
.report-log-activity-label {
    display: inline-block;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--accent-color);
    opacity: 0.85;
    margin-bottom: 3px;
}

/* Secondary hint — variant label in parens after a custom label.
   e.g. "MORNING RITUAL (Bath)" — hint is same color but lighter weight,
   no uppercase, so the user's custom name reads as the primary identifier. */
.report-log-activity-label-hint {
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    opacity: 0.7;
}

/* ── Fitness + Self-Care panel log custom labels ──────────────────────────────
   Same semantic as .report-log-activity-label but scoped to panel log lists.
   Shown when entry.activityCustomLabel is set — user's name for the event/slice. */
.fitness-log-custom-label,
.selfcare-log-custom-label {
    display: block;
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--accent-color);
    opacity: 0.85;
    margin-bottom: 2px;
}

/* Variant label hint in parens — same subordinate treatment as report panel */
.fitness-log-custom-label-hint,
.selfcare-log-custom-label-hint {
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    opacity: 0.7;
}

/* ── Change log ── */
.stage-log-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
    max-height: 200px;
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: var(--box-border) var(--bg-main);
}

.stage-panel.stage-panel-expanded .stage-log-list { max-height: 320px; }

.stage-log-list::-webkit-scrollbar       { width: 3px; }
.stage-log-list::-webkit-scrollbar-track { background: var(--bg-main); }
.stage-log-list::-webkit-scrollbar-thumb { background-color: var(--box-border); border-radius: 2px; }

.stage-log-entry {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 7px 9px;
    background: var(--bg-input);
    border-radius: 6px;
    border: 1px solid var(--box-border);
}

.stage-log-text {
    font-size: 0.78rem;
    color: var(--text-main);
    line-height: 1.4;
}

.stage-log-time {
    font-size: 0.67rem;
    color: var(--text-muted);
    opacity: 0.75;
}

.stage-log-empty {
    font-size: 0.78rem;
    color: var(--text-muted);
    opacity: 0.5;
    font-style: italic;
    padding: 2px 0;
    list-style: none;
}

/* ── Mobile ── */
@media (max-width: 600px) {
    .stage-panel {
        width: calc(100vw - 24px);
        right: 12px;
    }

    /* Top-anchor on mobile: header + close button always visible regardless of
       panel height. Overrides bottom:60px / top:auto values set by JS with
       !important so this wins over inline styles. Not applied in expanded state
       since expanded has its own full-screen positioning. */
    .stage-panel:not(.stage-panel-expanded) {
        top: 8px !important;
        bottom: auto !important;
        left: auto !important;
        max-height: calc(100vh - 80px);   /* fallback: older iOS Safari */
        max-height: calc(100dvh - 80px);  /* iOS 15.4+: dvh excludes browser chrome */
    }

    /* Body max-height must be derived from dvh — NOT the default 70vh.
       Root cause of Add button clipping: the panel uses dvh-based max-height
       with overflow:hidden; if the body uses vh (which is taller than dvh on iOS),
       the panel clips the body's bottom content.
       Formula: dvh - panel-top(8) - header(52) - safe-area - buffer(90) */
    .stage-panel:not(.stage-panel-expanded) .stage-panel-body {
        max-height: calc(100vh - 150px);  /* vh fallback */
        max-height: calc(100dvh - 150px - env(safe-area-inset-bottom, 0px));
        /* Padding ensures the bottom-most content scrolls fully into view
           above the iOS browser chrome / home indicator */
        padding-bottom: calc(48px + env(safe-area-inset-bottom, 0px));
    }

    .stage-rings-grid { gap: 10px 4px; }

    .stage-big-ring-wrap.is-cal     { width: 100px; height: 100px; }
    .stage-big-ring-wrap.is-protein { width: 70px;  height: 70px;  }
}
