/* style-weather-panels.css — Phase 2 of Weather Panels.
 *
 * Strict no-rounded-corners design (briefing § 5). All radii are 0;
 * even buttons render as flat rectangles. Default body font for panel
 * content is Google Sans Text, exposed via the bzWeather Type token
 * (--bzWeather-family) so bzDesign overrides cascade in naturally.
 *
 * Animation (briefing § 6 + operator Q8 = B):
 *   - Panel opens via scaleX(0 → 1) with transform-origin: left
 *     center, ~200ms cubic-bezier ease-out. While the shell expands,
 *     backdrop fades in + blurs the content underneath.
 *   - After the shell lands, content fades in column-by-column with
 *     a 50ms stagger (CSS-driven via :nth-child).
 *   - Close reverses: columns fade out first, then shell collapses
 *     scaleX(1 → 0).
 *   - prefers-reduced-motion: reduce → all transitions disabled, snap
 *     to final state.
 */

/* ─────────────────────────────────────────────────────────────────
   Backdrop — full-screen blurred overlay above the beach view.
   z-index 9000 sits below the panel itself (9001) but above every-
   thing in the consumer SPA. Match the .bz-rating-* backdrop pattern
   in style-ratings.css for cubic-bezier values + blur depth.
   ───────────────────────────────────────────────────────────────── */
.bz-wp-backdrop {
    position: fixed;
    inset: 0;
    z-index: 9000;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(0px);
    -webkit-backdrop-filter: blur(0px);
    opacity: 0;
    pointer-events: none;
    transition:
        opacity 200ms cubic-bezier(.2, .8, .2, 1),
        backdrop-filter 200ms cubic-bezier(.2, .8, .2, 1),
        -webkit-backdrop-filter 200ms cubic-bezier(.2, .8, .2, 1);
}
.bz-wp-backdrop.is-open {
    opacity: 1;
    pointer-events: auto;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}

/* ─────────────────────────────────────────────────────────────────
   Panel shell — centered modal. Width adapts to viewport; on phones
   it spans the full width with a thin gutter.
   transform-origin: left center → scaleX collapses leftward visually
   so the open-anim grows from the left edge into final centered pos
   (operator Q8 = B + briefing § 6 "expands left → right").
   ───────────────────────────────────────────────────────────────── */
.bz-weather-panel {
    position: fixed;
    top: 50%;
    left: 50%;
    z-index: 9001;
    width: min(880px, calc(100vw - 24px));
    max-height: calc(100vh - 48px);
    /* overflow: visible — no scrollbars. Sizing on inner elements
       keeps content within max-height; if a future operator dials a
       size that overflows, they'll see it and can fix in Properties
       rather than a horizontal scrubber appearing inside the panel.
       Operator complaint: scrolling controllers (the browser scrollbar
       thumb) were appearing at small viewports — gone now. */
    overflow: visible;
    /* No hardcoded background — operator's bzDesign Fill on wp-panel
       owns the surface colour (default transparent so the operator can
       layer per-zone backgrounds on wp-header / wp-body without the
       panel root painting over them). */
    background: transparent;
    border-radius: 0;
    /* No default border or surrounding shadow — keeps the panel
       outline-free per operator request. If a border/shadow is
       wanted later, set it via bzDesign Properties → Border or
       Shadow on the 'wp-panel' Library entry. */
    border: 0;
    box-shadow: none;
    padding: 20px 22px;
    font-family: var(--bzWeather-family, 'Google Sans Text', -apple-system, BlinkMacSystemFont, system-ui, sans-serif);
    font-size: var(--bzWeather-size, 14px);
    font-weight: var(--bzWeather-weight, 400);
    line-height: var(--bzWeather-line-height, 1.4);
    color: var(--bzWeather-color, #f4f6f8);

    transform: translate(-50%, -50%) scaleX(0);
    transform-origin: left center;
    opacity: 0.6;   /* slight pre-anim opacity so the shell isn't pitch-black */
    transition:
        transform 200ms cubic-bezier(.2, .8, .2, 1),
        opacity 200ms cubic-bezier(.2, .8, .2, 1);
}
.bz-weather-panel.is-open {
    transform: translate(-50%, -50%) scaleX(1);
    opacity: 1;
}

/* Anchored variant — JS positions the panel via inline top / left
   to align with the .val row the operator clicked. Static rules
   override the centered translate so the panel grows rightward
   from the row instead of from the viewport centre. */
.bz-weather-panel.is-anchored {
    top: auto;
    left: auto;
    transform: scaleX(0);
    transform-origin: left top;
    /* No outer padding — wp-body owns its own padding so the
       columns row sits at panel-top, which (with JS shifting
       panel.top up by the column's intrinsic top offset) lands
       on the same y as the clone's reading digits. */
    padding: 0;
    /* Hard width cap so the panel never overflows the viewport
       even at tablet / phone-landscape widths. JS still sizes
       width by available space, but this is the safety net. */
    max-width: calc(100vw - 12px);
    /* In anchored mode the panel becomes a flex column with the
       body (columns) on top and the header (toggle) below. Use
       natural column direction + explicit `order` per child
       rather than column-reverse — the body has a static
       negative bottom margin (- 20 px, to negate the panel's
       static padding) that interacted badly with column-reverse
       and pulled the toggle up over the column bottom row. */
    display: flex;
    flex-direction: column;
    align-items: center;
}
.bz-weather-panel.is-anchored.is-open {
    transform: scaleX(1);
}
/* Mobile / narrow viewports: panel anchors BELOW the val row and
   spans the full screen width. Override transform so the open
   animation drops down from the top edge instead of unfurling
   from the left (which looked wrong full-width). */
.bz-weather-panel.is-anchored.is-anchored-below {
    transform-origin: top center;
    transform: scaleY(0);
}
.bz-weather-panel.is-anchored.is-anchored-below.is-open {
    transform: scaleY(1);
}
/* Suppress the IPMA "honesty note" in the below-anchor mobile
   layout. It only applies to the water 1D fallback and on a narrow
   panel the centred full-width line visually rides over the column
   secondary row. The caveat is preserved in the live data semantics
   and in the desktop beside-anchor layout. */
.bz-weather-panel.is-anchored.is-anchored-below .bz-wp-note {
    display: none;
}
/* Toggle floats to the RIGHT of the last column, vertically
   centred with the column row. Close button is retired in
   anchored mode — operator closes via Esc / backdrop click /
   re-clicking the val row that opened the panel. */
.bz-weather-panel.is-anchored .bz-wp-header {
    /* Sits below the body (columns) via flex `order: 2` and is
       horizontally centred by align-items:center on the panel.
       margin-top creates positive clearance from the columns'
       bottom row so the toggle's pill background doesn't sit
       at the same Y as the column tertiary labels. */
    order: 2;
    position: static;
    flex: 0 0 auto;
    transform: none;
    margin: 14px 0 0;
    padding: 6px 12px 10px;
    background: transparent;
    border: 0;
    gap: 0;
    height: auto;
}
.bz-weather-panel.is-anchored .bz-wp-title {
    /* The clone on the left already signals what the panel is. */
    display: none;
}
.bz-weather-panel.is-anchored .bz-wp-close {
    /* Close button retired in anchored mode — saves the horizontal
       space the toggle now needs at the column row's right edge.
       Esc + backdrop click still close. */
    display: none;
}
.bz-weather-panel.is-anchored .bz-wp-body {
    /* Body holds the columns and sits above the toggle (header
       gets order: 2). Override the static negative bottom margin
       so the toggle doesn't ride up into the columns. Internal
       gap kept tight so the note hugs the columns. */
    order: 1;
    flex: 0 0 auto;
    align-self: stretch;
    min-width: 0;
    padding: 8px 12px;
    margin: 0;
    gap: 6px;
}
.bz-weather-panel.is-anchored .bz-wp-columns {
    min-height: 0;
    /* Inter-column gap is operator-controlled via Properties → Stack
       → Gap on the wp-columns Library entry (writes
       --bzd-stack-prop-gap). Falls back to a clamp so 7 cols still
       fit when the operator hasn't set a value yet. */
    gap: var(--bzd-stack-prop-gap, clamp(2px, 1vw, 8px));
}
.bz-weather-panel.is-anchored .bz-wp-col {
    /* Tighter padding so columns don't bloat horizontally. */
    padding: 4px 2px;
    gap: 2px;
    /* Allow the column to shrink below its content's intrinsic
       width — otherwise "KM/H" forces a min-width that breaks
       the grid layout at narrow viewports. overflow:hidden
       paired with the existing minmax(0, 1fr) means children
       wrap/clip rather than blowing out the grid. */
    min-width: 0;
}
/* On phone landscape and tighter — drop the per-column horizontal
   padding entirely so the 7 cols read at the smallest sensible
   width. The labels still centre via text-align: center. */
@media (max-width: 720px) {
    .bz-weather-panel.is-anchored .bz-wp-body   { padding: 10px 8px; }
    .bz-weather-panel.is-anchored .bz-wp-header { padding: 4px 8px 8px; }
    .bz-weather-panel.is-anchored .bz-wp-col  { padding: 4px 0; }
}

/* Clicked-val sharp-clone. The clicked .val row sits inside
   #val-stack, which has z-index:18 AND its own stacking context
   (transforms from operator's bzDesign Layout create one). Lifting
   the child's z-index can't escape that context, so the backdrop
   (z-index 9000) always painted over the original — that's why the
   "reading disappears" screenshot showed nothing on the left.
   Robust fix: JS clones the row into a direct child of <body> with
   position: fixed + z-index: 9002. A body-child has no parent
   stacking context to fight; the clone paints above the backdrop
   unconditionally. The ORIGINAL row stays in flex flow (so the
   val-stack's height doesn't collapse and the panel anchor coords
   stay correct), gets blurred normally, and is visually covered by
   the sharp clone in the same x/y slot. */
.bz-wp-anchor-clone {
    /* JS sets top/left/width/height inline from the original's
       getBoundingClientRect. */
    position: fixed;
    z-index: 9002;     /* backdrop 9000, panel 9001, clone 9002 */
    margin: 0;
    pointer-events: none;
    /* Force white throughout the clone — operator request. Each
       descendant carries its own colour binding (style.css's
       .val-ico, theme-bridge's bzWeather*-color cascade), so the
       parent `color` alone wouldn't be enough; override every
       text/icon node directly. */
    color: #FFFFFF !important;
    text-shadow: 0 3px 14px rgba(0, 0, 0, 0.55),
                 0 1px 4px  rgba(0, 0, 0, 0.45);
}
.bz-wp-anchor-clone .val-ico,
.bz-wp-anchor-clone .val-num,
.bz-wp-anchor-clone .val-num span,
.bz-wp-anchor-clone .val-num sup,
.bz-wp-anchor-clone .val-unit {
    color: #FFFFFF !important;
    opacity: 1 !important;
}

/* Header — title left, toggle center, close right.
   Independent background surface so the operator can style it
   separately from the panel body in bzDesign. Negative margins
   extend it to the panel's full width (panel has 20-22px padding);
   padding inside the header restores comfortable spacing. */
.bz-wp-header {
    display: flex;
    align-items: center;
    gap: 16px;
    margin: -20px -22px 18px;
    padding: 14px 22px;
    /* Transparent default + no border. bzDesign Fill on the
       'wp-header' Library entry owns the top-zone surface; bzDesign
       Border on the same entry adds a divider if the operator
       wants one. Default is outline-free. */
    background: transparent;
    border-bottom: 0;
}
/* ─────────────────────────────────────────────────────────────────
   Type-token bindings — every text node reads its DEDICATED w* type
   style. Operator request: the weather panels must NOT share type
   styles with any other site element. The wForecast* namespace was
   added in theme-applier.js + admin-design-stage9.js for that
   isolation. Editing one of these affects ONLY the weather panels.
   ───────────────────────────────────────────────────────────────── */
.bz-wp-title {
    flex: 0 0 auto;
    /* wForecastHead — panel title. Isolated from bzHeading. */
    font-family:    var(--wForecastHead-family);
    font-size:      var(--wForecastHead-size);
    font-weight:    var(--wForecastHead-weight);
    line-height:    var(--wForecastHead-line-height);
    letter-spacing: var(--wForecastHead-letter-spacing);
    font-style:     var(--wForecastHead-style);
    text-transform: var(--wForecastHead-transform);
    color:          var(--wForecastHead-color, inherit);
    display: inline-flex;
    align-items: center;
    gap: 8px;
}
.bz-wp-title-icon {
    /* Icon next to title — sized to wForecastHead so the glyph scales
       with the title as the operator tunes it. */
    font-size:   var(--wForecastHead-size);
    line-height: 1;
    color: inherit;
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.bz-wp-title-text {
    /* Inherits the wrapper's wForecastHead binding above. */
    line-height: inherit;
    color: inherit;
}

.bz-wp-toggle {
    flex: 1 1 auto;
    display: flex;
    justify-content: center;
    gap: 0;
    /* Transparent default + no border so the toggle reads as plain
       text labels until the operator chooses to surround them via
       bzDesign Properties → Fill / Border on 'wp-toggle'. */
    background: transparent;
    border: 0;
    padding: 2px;
}
.bz-wp-toggle__btn {
    border: 0;
    background: transparent;
    /* wForecastToggle — isolated from bzButton elsewhere on the site. */
    font-family:    var(--wForecastToggle-family);
    font-size:      var(--wForecastToggle-size);
    font-weight:    var(--wForecastToggle-weight);
    line-height:    var(--wForecastToggle-line-height);
    letter-spacing: var(--wForecastToggle-letter-spacing);
    font-style:     var(--wForecastToggle-style);
    text-transform: var(--wForecastToggle-transform);
    color: var(--wForecastToggle-color, inherit);
    opacity: 0.6;
    cursor: pointer;
    padding: 7px 14px;
    border-radius: 0;
    transition: opacity 120ms, background 120ms;
}
.bz-wp-toggle__btn:hover { opacity: 1; }
.bz-wp-toggle__btn.is-active {
    background: rgba(255, 255, 255, 0.14);
    opacity: 1;
}

.bz-wp-close {
    border: 0;
    background: transparent;
    /* Shares wForecastToggle with the toggle row for visual cohesion. */
    font-family: var(--wForecastToggle-family);
    color: var(--wForecastToggle-color, inherit);
    opacity: 0.7;
    cursor: pointer;
    padding: 4px;
    line-height: 1;
    border-radius: 0;
}
.bz-wp-close:hover { opacity: 1; }
.bz-wp-close .material-symbols-outlined { font-size: 22px; }

/* Body + column grid — wp-body gets padding so its bounding box is
   visible when the operator paints it via bzDesign Fill on the
   'wp-body' Library entry. Without padding the body collapsed onto
   the columns and Fill looked like it wasn't applying. */
.bz-wp-body  {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 14px 22px;
    margin: 0 -22px -20px;   /* negate panel padding so wp-body spans edge-to-edge */
    background: transparent; /* bzDesign Fill on 'wp-body' owns this surface */
}
.bz-wp-columns {
    display: grid;
    /* Operator-controllable column width via Properties → Stack →
       Column width on wp-columns. When unset, columns auto-split
       (minmax(0, 1fr)) — same as before. When set, all 7 columns
       take the chosen px width. Per-breakpoint by default
       (__wp-col-width is NOT in MIRROR_PROPS). */
    grid-template-columns: repeat(var(--bz-wp-col-count, 7), var(--bz-wp-col-width, minmax(0, 1fr)));
    /* Operator-controllable inter-column gap via Properties → Stack
       → Gap on wp-columns. Falls back to 8 px when unset. */
    gap: var(--bzd-stack-prop-gap, 8px);
    min-height: 160px;
}

/* Loading + empty states bind to wForecastNote — isolated. */
.bz-wp-columns[data-state='loading']::before {
    content: '…';
    grid-column: 1 / -1;
    text-align: center;
    color: inherit;
    opacity: 0.5;
    font-size: var(--wForecastDigit-size);
    line-height: 160px;
}
.bz-wp-empty {
    grid-column: 1 / -1;
    color: var(--wForecastNote-color, inherit);
    opacity: 0.55;
    text-align: center;
    padding: 32px 12px;
    font-family:    var(--wForecastNote-family);
    font-size:      var(--wForecastNote-size);
    font-weight:    var(--wForecastNote-weight);
    line-height:    var(--wForecastNote-line-height);
    letter-spacing: var(--wForecastNote-letter-spacing);
}

/* Individual column. Transparent by default per operator request;
   the operator can re-add a column background later in bzDesign via
   the 'wp-col' Library entry → Properties → Fill. */
.bz-wp-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 10px 4px;
    background: transparent;
    border: 0;
    border-radius: 0;
    text-align: center;

    /* Initial state for the per-column stagger animation. */
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 280ms cubic-bezier(.2,.8,.2,1),
                transform 280ms cubic-bezier(.2,.8,.2,1);
}
.bz-weather-panel.content-loaded .bz-wp-col {
    opacity: 1;
    transform: none;
}
/* 50ms stagger per column. 7 columns → final at 300ms after the shell
   finishes its 200ms expand, so total open-to-fully-loaded ~500ms. */
.bz-weather-panel.content-loaded .bz-wp-col:nth-child(1) { transition-delay: 0ms;   }
.bz-weather-panel.content-loaded .bz-wp-col:nth-child(2) { transition-delay: 50ms;  }
.bz-weather-panel.content-loaded .bz-wp-col:nth-child(3) { transition-delay: 100ms; }
.bz-weather-panel.content-loaded .bz-wp-col:nth-child(4) { transition-delay: 150ms; }
.bz-weather-panel.content-loaded .bz-wp-col:nth-child(5) { transition-delay: 200ms; }
.bz-weather-panel.content-loaded .bz-wp-col:nth-child(6) { transition-delay: 250ms; }
.bz-weather-panel.content-loaded .bz-wp-col:nth-child(7) { transition-delay: 300ms; }

/* Every text element below binds to a dedicated w* var. All edits
   in those Type styles affect ONLY the weather panels. */
.bz-wp-col__label {
    /* wForecastLabel — small label above each column ("22H", "Mon"). */
    font-family:    var(--wForecastLabel-family);
    font-size:      var(--wForecastLabel-size);
    font-weight:    var(--wForecastLabel-weight);
    line-height:    var(--wForecastLabel-line-height);
    letter-spacing: var(--wForecastLabel-letter-spacing);
    font-style:     var(--wForecastLabel-style);
    text-transform: var(--wForecastLabel-transform);
    color: var(--wForecastLabel-color, inherit);
    opacity: 0.55;
}
.bz-wp-col__icon {
    /* Sized to wForecastDigit so the glyph tracks the digit. */
    font-size: var(--wForecastDigit-size);
    color: inherit;
    margin: 2px 0 4px;
    font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.bz-wp-col__values {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    margin-top: 2px;
}
.bz-wp-col__primary {
    /* wForecastDigit — the column's main reading (the digit). */
    font-family:    var(--wForecastDigit-family);
    font-size:      var(--wForecastDigit-size);
    font-weight:    var(--wForecastDigit-weight);
    line-height:    var(--wForecastDigit-line-height);
    letter-spacing: var(--wForecastDigit-letter-spacing);
    font-style:     var(--wForecastDigit-style);
    text-transform: var(--wForecastDigit-transform);
    color: var(--wForecastDigit-color, inherit);
}
.bz-wp-col__primary--class {
    /* Wind class modifier (e.g. "MOD") — sized down from wForecastLabel. */
    font-family:    var(--wForecastLabel-family);
    font-size:      var(--wForecastLabel-size);
    font-weight:    var(--wForecastLabel-weight);
    line-height:    var(--wForecastLabel-line-height);
    letter-spacing: var(--wForecastLabel-letter-spacing);
    text-transform: var(--wForecastLabel-transform);
    padding: 4px 0 0;
}
.bz-wp-col__secondary {
    /* wForecastLabel — unit text under the digit ("km/h", "UV"). */
    font-family:    var(--wForecastLabel-family);
    font-size:      var(--wForecastLabel-size);
    font-weight:    var(--wForecastLabel-weight);
    line-height:    var(--wForecastLabel-line-height);
    letter-spacing: var(--wForecastLabel-letter-spacing);
    font-style:     var(--wForecastLabel-style);
    text-transform: var(--wForecastLabel-transform);
    color: var(--wForecastLabel-color, inherit);
    opacity: 0.6;
}
.bz-wp-col__wave {
    margin-top: 2px;
    color: inherit;
    opacity: 0.6;
}

.bz-wp-arrow {
    font-size: 20px;
    color: inherit;
    opacity: 0.8;
    margin-top: 2px;
    transform-origin: center center;
    transition: transform 200ms cubic-bezier(.2, .8, .2, 1);
}

.bz-wp-note {
    /* wForecastNote — the "honesty note" under the columns. */
    font-family:    var(--wForecastNote-family);
    font-size:      var(--wForecastNote-size);
    font-weight:    var(--wForecastNote-weight);
    line-height:    var(--wForecastNote-line-height);
    letter-spacing: var(--wForecastNote-letter-spacing);
    color: var(--wForecastNote-color, inherit);
    opacity: 0.5;
    text-align: center;
    margin-top: 4px;
}
.bz-wp-note:empty { display: none; }

/* ─────────────────────────────────────────────────────────────────
   Body lock — prevent the underlying page from scrolling while a
   panel is open. The blur backdrop alone doesn't disable scroll.
   ───────────────────────────────────────────────────────────────── */
body.bz-wp-open {
    overflow: hidden;
    /* On iOS Safari the address bar collapse can shift layout; lock
       touch-action too so the page doesn't scroll under the panel. */
    touch-action: none;
}

/* ─────────────────────────────────────────────────────────────────
   Phone tweaks — keep the panel readable at narrow widths.
   ───────────────────────────────────────────────────────────────── */
@media (max-width: 600px) {
    .bz-weather-panel {
        width: calc(100vw - 12px);
        padding: 14px 12px;
    }
    .bz-wp-header { gap: 10px; }
    /* Font-sizes intentionally NOT shrunk here — they bind to the
       Type tab vars (bzHeading / bzWeatherNumber / etc.). Operator
       owns mobile sizing by setting per-bp tokens in the Type tab. */
    .bz-wp-toggle__btn { padding: 6px 10px; }
    .bz-wp-columns { gap: 4px; }
    .bz-wp-col     { padding: 7px 2px; gap: 2px; }
    .bz-wp-arrow         { font-size: 16px; }
}

/* ─────────────────────────────────────────────────────────────────
   prefers-reduced-motion — skip transitions, snap to final state.
   ───────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
    .bz-wp-backdrop,
    .bz-weather-panel,
    .bz-wp-col,
    .bz-wp-arrow {
        transition: none !important;
        animation: none !important;
    }
}

/* Trigger affordance — the .val cells become pointers when the
   panel module is loaded. We only set this for the three kinds that
   open a panel (air/wind/water) — UV stays inert until/unless its
   own panel ships. */
#screen-beach .val[data-val='air'],
#screen-beach .val[data-val='wind'],
#screen-beach .val[data-val='water'] {
    cursor: pointer;
    transition: opacity 120ms;
}
#screen-beach .val[data-val='air']:hover,
#screen-beach .val[data-val='wind']:hover,
#screen-beach .val[data-val='water']:hover {
    opacity: 0.85;
}
