/* ── PANEL CHROME ────────────────────────────────────────────────────────────
   Phase 2 of panel-unification. Single source of truth for panel chrome:
   the box, header, body scroll behavior, expanded mode, mobile rules, Cally.
   Per-panel CONTENT lives in each panel's own *-content.css file.

   Step 10 cleanup (2026-05-06): all 8 stage panels migrated and reflect
   migrated. The legacy `.stage-panel-*` comma-grouped aliases that paired
   each `.panel-*` rule have been removed — every panel now emits `.panel-*`
   directly via the factory.

   `.stage-cally-*` and `.panel-cally-*` retain distinct margins by
   intentional design (stage: edge-to-edge `10px 0 24px 0`, reflect: inset
   `10px 12px 10px 12px`). Both look right; both stay. See feedback memory
   "Lead with the delta on cleanup passes."

   Loaded after stage.css and reflect.css in index.html so panel.css's rules
   win the cascade for migrated panels.

   Phase 2 PRD v4 §5.1 / §5.2 / §6.10.
   ─────────────────────────────────────────────────────────────────────────── */


/* ── Base container ────────────────────────────────────────────────────────── */

.panel {
    position: fixed;
    bottom: 60px;     /* anchored 60px above viewport bottom */
    right:  20px;
    width: 340px;
    /* Cap so the panel's top edge can't grow above 220px from the viewport top
       (which would cover the score-strip's quick-access icons). The 280
       below = 60 (bottom anchor) + 220 (top edge cap). On tall viewports the
       panel may end shorter than this cap when content is sparse — intrinsic
       sizing wins, top edge sits even higher (further from the UI). Mobile
       overrides below in @media (max-width: 600px). */
    max-height: calc(100vh - 280px);
    max-height: calc(100dvh - 280px); /* iOS Safari: dvh excludes browser chrome */
    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;
    display: flex;
    flex-direction: column;
}

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


/* ── Header / drag handle ──────────────────────────────────────────────────── */

.panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* May 27 2026: reduced from 14px/10px to 8px/4px — shrinks the header
       strip by 6px above + 6px below the title/close-button row (12px total).
       min-height drops from 52 to 40 to match the padding reduction. */
    padding: 8px 16px 4px;
    border-bottom: 1px solid var(--box-border);
    cursor: grab;
    user-select: none;
    position: relative;
    min-height: 40px;
}

.panel-header:active {
    cursor: grabbing;
}

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


/* ── Header layout: title-group (left) / actions (right) ──────────────────── */

.panel-title-group {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

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

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

.panel-header-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-shrink: 0;
}

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


/* ── Scrollable body ──────────────────────────────────────────────────────── */

.panel-body {
    /* 56px bottom = scroll breathing room so the last row clears the panel edge.
       Was duplicated per-panel (#report-panel, #coach-panel, #food-panel, …);
       consolidated here so every factory panel gets it. Mobile bumps it further
       below for the iOS home indicator. */
    padding: 12px 16px 56px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
    /* Disable browser scroll-anchoring during content updates while keyboard
       is open. Unconditional rather than scoped to .panel-keyboard-open
       because no current panel uses append-on-load / infinite-scroll
       patterns where anchoring would be desirable. */
    overflow-anchor: none;
    -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);
}

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

/* Comfortable minimum panel height for ALL factory panels (was the factory's
   per-panel body min-height: '70dvh', which broke shrink-to-scroll and clipped
   tall content). Lives on the PANEL, not the body, so the body stays free to
   shrink and scroll. Clamped with min() to the docked max-height
   [calc(100dvh - 280px)] so the floor can never exceed the ceiling on short
   screens (which would push the panel off the top of the viewport). The clamp
   value is <= every breakpoint's max-height (mobile ~100dvh-16px, expanded
   100dvh — no per-panel overrides anymore), so this one rule is safe at all
   sizes; flex-grow still lets the panel reach its full max-height when content
   is tall. */
.panel {
    min-height: min(70dvh, calc(100dvh - 280px));
}

/* Extra bottom breathing room on mobile so the last row clears the iOS home
   indicator + Safari toolbar. Was duplicated per-panel; consolidated here. */
@media (max-width: 600px) {
    .panel:not(.panel-expanded) .panel-body {
        padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    }
}


/* ── Expanded (full-screen) state ─────────────────────────────────────────── */

.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 */
    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 */
}

/* No max-height here. The old calc(100dvh - 56px) subtracted only the header,
   not the tab bar — so on tabbed panels (Score, Coach, Food, Mood) the expanded
   body ran ~one tab-bar taller than its slot and .panel-expanded{overflow:hidden}
   clipped the last row. .panel-expanded is a flex column with overflow:hidden, so
   the body (flex:1 1 auto; min-height:0) already fills exactly the space left after
   header + tab bar and scrolls internally. This is CLAUDE.md invariant #208's
   prescribed fix ("the fix is the flex chain, not another max-height calc"). */


/* ── Cally row (unified) ──────────────────────────────────────────────────── */
/* Stage Cally and reflect Cally are visually IDENTICAL except for the row
   margin (stage: `10px 0 24px 0`, reflect: `10px 12px 10px 12px`). Comma-
   grouping `.stage-cally-*` is safe (identical values); `.reflect-cally-*`
   stays out of the group and continues to be governed by reflect.css until
   step 9 Cally unification. */

.panel-cally-row,
.stage-cally-row {
    display: flex;
    align-items: center;
    margin: 10px 0 24px 0;
    gap: 0;
}

.panel-cally-bubble,
.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;
}

.panel-cally-bubble::after,
.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);
}

.panel-cally-bubble::before,
.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;
}

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

.panel-cally-sprite,
.stage-cally-sprite {
    width: 48px;
    height: 48px;
    image-rendering: pixelated;
    object-fit: contain;
    flex-shrink: 0;
    padding-left: 10px;
    filter: var(--icon-accent-filter);
}

/* Trigger button on the day grid (ritual-reflect row). Renamed from
   .reflect-cally-trigger in step 9. No standalone CSS rule today — styling
   inherits from .nav-icon-button. Listed here as a hook for step 10. */
.panel-cally-trigger {
    /* (intentionally empty — class is a hook, not a styled selector) */
}


/* ── Mobile rules ─────────────────────────────────────────────────────────── */

@media (max-width: 600px) {
    /* Edge-to-edge gutter, top-anchor when not expanded.
       !important wins over inline-style positions JS may have written from
       desktop drag state. (Phase 1 §5.1 root-cause.) */
    .panel {
        left: 8px;
        right: 8px;
        width: auto;
    }

    .panel:not(.panel-expanded) {
        top: 2px !important;   /* sits near the very top (was 3px → 8px historically) */
        bottom: auto !important;
        /* FIXED height on mobile (min-height == max-height) so EVERY panel is the
           same height regardless of how much content it has. Without the matching
           min-height, panels were content-sized between the .panel floor (70dvh)
           and this ceiling — so content-light panels (Mood, Self-Care) rendered
           shorter than content-heavy ones (Food, Coach). Fills nearly the whole
           viewport: dvh excludes the iOS toolbar and env(safe-area) clears the home
           indicator, so it's tall yet safe. One shared rule → uniform height for
           ALL panels (per-panel 92dvh overrides removed June 2026).
           June 23 2026: tightened the bottom subtraction 16px → 4px (and top 3→2px)
           to reclaim ~13px the panel was leaving above the home indicator — the
           Today-view "Completed" button was clipping on iOS. The body cap below
           was lowered by the SAME 12px (124→112) so #218's "cap stays below the
           flex slot" margin is preserved. ~4px bottom gap remains as toolbar slack. */
        min-height: calc(100vh - 4px);                                     /* fallback: older iOS Safari */
        min-height: calc(100dvh - 4px - env(safe-area-inset-bottom, 0px)); /* iOS 15.4+ */
        max-height: calc(100vh - 4px);
        max-height: calc(100dvh - 4px - env(safe-area-inset-bottom, 0px));
    }

    /* ⚠️ iOS Safari: the body MUST keep a DEFINITE max-height that stays BELOW the
       flex slot (panel − header − tab bar). If the cap is raised above the slot the
       body becomes flex-driven, and iOS mis-sizes the nested flex row inside it —
       which COLLAPSED the Food panel's body-weight column (June 2026 regression).
       A definite height keeps overflow:auto scrolling correctly. So this is a real
       magic number, NOT the #208 "let flex drive it" case (that's for EXPANDED
       panels). 112px ≈ top(2) + header(52) + tab bar(~44) + a safety margin so the
       cap never crosses into the flex slot on any panel. It tracks the panel's own
       bottom subtraction (June 23 2026: 124→112, in lockstep with the 16→4 panel
       change above) so the cap-below-slot safety margin is unchanged — both moved
       12px together. More content shows; the rest scrolls. */
    .panel:not(.panel-expanded) .panel-body {
        max-height: calc(100vh - 112px);
        max-height: calc(100dvh - 112px - env(safe-area-inset-bottom, 0px));
        padding-bottom: calc(48px + env(safe-area-inset-bottom, 0px));
    }

    /* Lock background scroll while any panel is visible. Prevents iOS
       from auto-scrolling the document during keyboard show, and matches
       the single-panel mobile UX model. position:fixed is the robust lock
       iOS Safari respects (overflow:hidden alone can be bypassed when a
       focused input triggers iOS's scroll-into-view).

       The factory's _lockBodyScroll captures window.scrollY before adding
       this class, sets body.style.top to -scrollY (preserving visual
       position), and restores scrollY after class removal. PRD v6 R16 +
       Phase 1 §5.7 + the 2026-05-06 panel-close-scroll-unlock fix. */
    body.panel-open-mobile {
        overflow: hidden;
        position: fixed;
        left: 0;
        right: 0;
        width: 100%;
    }
}
