/*
 * Availability Matrix styles (wsh-availability-matrix.css) — v3.6.0-beta.
 *
 * Speculative demo build pending Michael Lee scope approval. Companion to
 * includes/class-wsh-availability-matrix.php and templates/availability-matrix.php.
 *
 * Token policy: this file imports wsh-design-tokens.css for global palette
 * tokens (--wsh-color-sky, --wsh-color-green, --wsh-color-dark, etc.). Any
 * matrix-only color or spacing not already represented as a global token is
 * defined as a CSS custom property scoped under `.wsh-matrix` below — per
 * Strict Isolation §1.4, wsh-design-tokens.css is NOT modified by this
 * build. If the matrix promotes from beta to production, a follow-up pass
 * can promote whichever of these scoped tokens have stabilized.
 *
 * BEM convention matches existing plugin styles (wsh-property-grid.css,
 * wsh-property-detail.css). Modifier suffixes use double-dash.
 */

@import url("wsh-design-tokens.css");

/* ============================================================
   Matrix-scoped tokens (per Strict Isolation §1.4)
   ============================================================ */
.wsh-matrix {
	/* Cell-state colors — Rev 2 §3.1 spec: pale cyan (avail), pink (booked),
	   orange + cyan diagonal split (changeover). Pass 2.5k-correction:
	   today-outline token repurposed as today-header-text-only — body cells
	   in today's column are no longer outlined, since the amber outline is
	   now reserved as the SELECTED check-in / check-out marker. Token name
	   "today-outline" kept for now to minimize churn; rename in a future
	   cleanup pass. Value updated #ff8c40 → #BA7517 (saturated amber matching
	   the Alohana brand palette today-header swatch in the mockup). */
	--wsh-matrix-color-avail:        var(--wsh-color-sky, #eaf9fe);
	--wsh-matrix-color-booked:       #fadcdc;
	--wsh-matrix-color-changeover:   #ffb877;
	--wsh-matrix-color-today-outline:#BA7517;
	--wsh-matrix-color-cell-border:  rgba(0, 0, 0, 0.06);
	--wsh-matrix-color-row-border:   rgba(0, 0, 0, 0.04);

	/* Category-band header (separator between bedroom groups). */
	--wsh-matrix-color-cat-bg:       #f4f5f0;
	--wsh-matrix-color-cat-text:     var(--wsh-color-dark, #011820);
	--wsh-matrix-color-cat-border:   rgba(0, 0, 0, 0.08);

	/* Sticky surface backgrounds — opaque so scrolled-under content
	   doesn't bleed through. */
	--wsh-matrix-color-sticky-bg:    #ffffff;
	--wsh-matrix-color-header-text:  var(--wsh-color-grey, #656565);

	/* Unit-name anchor (Addition 1 — Pass 2 amendment). Color matches
	   surrounding text by default; underline + slight color shift on
	   hover/focus. */
	--wsh-matrix-color-link:         var(--wsh-color-dark, #011820);
	--wsh-matrix-color-link-hover:   var(--wsh-color-green-dark, #5e6f53);

	/* 30-day-min pill badge. */
	--wsh-matrix-color-badge-bg:     rgba(var(--wsh-color-green-rgb, 123, 142, 110), 0.18);
	--wsh-matrix-color-badge-text:   var(--wsh-color-green-dark, #5e6f53);

	/* Pass 2.5k — selection range visualization. Selected-start / selected-
	   end get a 2px inset outline; in-range fill is a lighter tint sitting
	   behind the availability color so booked / changeover bars still read.
	   Pass 2.5k-correction: palette reassigned from sage-green to amber per
	   the locked mockup. Accent = #EF9F27 (saturated amber); in-range fill
	   = #FAEEDA (amber-50). Today header text uses a darker amber #BA7517
	   in --wsh-matrix-color-today-outline above; the three amber values
	   step the brand palette from light tint (in-range) through saturated
	   accent (selected start/end) to dark/grounded (today header text). */
	--wsh-matrix-color-range-accent:    #EF9F27;
	--wsh-matrix-color-range-fill:      #FAEEDA;
	/* Invalid range-pick feedback (2026-05-29 booking gesture). */
	--wsh-matrix-color-reject:          #d64545;

	/* Hover-quote tooltip. */
	--wsh-matrix-color-quote-bg:     var(--wsh-color-dark, #011820);
	--wsh-matrix-color-quote-text:   #ffffff;

	/* Layout — driven by inline `--wsh-matrix-cols` and `--wsh-matrix-thumb-px`
	   set by the template based on shortcode atts. */
	--wsh-matrix-cell-w:       40px;
	--wsh-matrix-cell-h:       40px;
	--wsh-matrix-unit-col-w:   220px;
	--wsh-matrix-header-h:     60px;   /* 3 lines (Item 2): month / DOW / day-of-month */
	--wsh-matrix-row-padding:  8px;
	--wsh-matrix-thumb-px:     56px;   /* default; overridden by inline style */
	--wsh-matrix-cols:         60;     /* default; overridden by inline style — Pass 2.5h render-cell count */

	/* Box. */
	font-family: var(--wsh-font-body, 'Poppins', sans-serif);
	color: var(--wsh-color-dark, #011820);
	background: var(--wsh-matrix-color-sticky-bg);
	border: 1px solid rgba(0, 0, 0, 0.08);
	border-radius: 4px;
	margin: 1em 0;
}

/* Empty / fallback state. */
.wsh-matrix--empty {
	padding: 24px;
	text-align: center;
	color: var(--wsh-color-grey);
}

/* ============================================================
   Nav bar — prev / label / next
   ============================================================ */
/* Pass 2.5k — justify-content changed from space-between to center, and a
   gap added between the buttons. Pre-2.5k the nav bar held three children
   (prev / month-label / next) so space-between produced the visual balance.
   2.5k removed the buggy month-label (it computed from the full 60-cell
   server render rather than the JS-visible count, giving wrong labels like
   "July – August 2026" when the viewport showed only July dates). With just
   prev + next remaining, space-between would push them to the matrix edges
   — Gary's chat direction: group as a centered nav unit above the grid. */
/* 2026-06-01 (Item 3) — custom scroll control. Replaces the retired
   ?start_date= page-nav buttons (.wsh-matrix__nav / __nav-btn, removed). These
   are real <button>s that scroll .wsh-matrix__scroll via scrollLeft; native
   horizontal scrolling (drag/wheel/trackpad) is kept alongside. End controls
   use the native :disabled state, toggled by JS at the true scroll extremes. */
.wsh-matrix__scroll-nav {
	/* Bookend Prev/Next to opposite ends of the nav row so they line up with
	   the grid's left/right edges — Prev over the unit-info column, Next at the
	   far right. display/justify forced with !important so a theme/Elementor
	   flex or text-align reset can't override the split. width:100% spans the
	   matrix so the edges align to the grid, not the viewport. */
	display: flex !important;
	align-items: center;
	justify-content: space-between !important;
	gap: 24px;
	width: 100%;
	box-sizing: border-box;
	padding: 12px 16px;
	/* ITEM 3 — start Prev at the date-column start (just right of the ~280px
	   unit/property column) instead of the far left, so it sits over the first
	   date column. Next stays pinned to the right edge via space-between. The
	   token tracks the responsive unit-col width (280px desktop / 200px mobile). */
	padding-left: var(--wsh-matrix-unit-col-w);
	border-bottom: 1px solid var(--wsh-matrix-color-cat-border);
	background: var(--wsh-matrix-color-sticky-bg);
}
/* 2026-06-01 — brand-green fill, override-proofed.
   Hello Elementor's reset.css styles bare <button>s pink (#c36 = #cc3366):
     [type=button],[type=submit],button { color:#c36; border:1px solid #c36;
       background-color:transparent }
     [type=button]:hover,…,button:hover { background-color:#c36; color:#fff }
   Our <button type="button"> matched both `button` and `[type=button]`, and
   the old single-class .wsh-matrix__scroll-btn (0,1,0) TIED `[type=button]`
   (0,1,0) — Hello's reset.css loads after the plugin CSS, so it won on source
   order and the buttons rendered pink. Fix: scope to 3 classes (0,3,0) so the
   plugin wins on specificity, AND keep targeted !important on the color trio
   (color / background-color / border-color) as durability insurance against a
   CSS-combining cache (e.g. WP Rocket) reordering the stylesheets. Layout
   props (padding / radius / border-width / font) are unchanged — color only. */
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn,
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn:link,
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn:visited {
	/* 2026-06-01 — match the matrix header/body font (Poppins/--wsh-font-body)
	   instead of --wsh-font-button (Montserrat 600), whose 600 weight isn't
	   loaded and renders faux-bold/blurry. The global --wsh-font-button is left
	   alone (other site buttons use it); override only at the matrix level. */
	font-family: var(--wsh-font-body, 'Poppins', sans-serif);
	font-size: 13px;
	font-weight: 600;
	color: #ffffff !important;
	background-color: var(--wsh-color-green, #7b8e6e) !important;
	padding: 6px 12px;
	border-radius: 4px;
	border: 1px solid var(--wsh-color-green, #7b8e6e);
	border-color: var(--wsh-color-green, #7b8e6e) !important;
	cursor: pointer;
	line-height: 1;
	text-decoration: none !important;
	/* Inheritance-killers — neutralize a leaked theme/Elementor text-shadow
	   (the soft blur on the Prev/Next label), filter, and the mobile tap glow. */
	text-shadow: none !important;
	filter: none !important;
	-webkit-tap-highlight-color: transparent;
}
/* 2026-06-01 — kill the leaked blue. The blue tint/glow on click/focus is the
   browser/UA default focus outline surfacing on :focus-visible — Hello
   Elementor's reset.css only clears the outline for
   `button:focus:not(:focus-visible)`, so a focus that triggers :focus-visible
   shows the UA blue ring. (Secondary blue source: the reset's
   `a:active,a:hover{color:#336}` indigo — but that targets <a>, not our
   <button>, so the ring is the real culprit.) Force white text + no underline
   across every interactive state, kill the blue outline/box-shadow, and swap in
   an intentional green keyboard-focus ring for accessibility. */
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn:hover,
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn:focus,
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn:active {
	color: #ffffff !important;
	background-color: var(--wsh-color-green-dark, #5e6f53) !important;
	border-color: var(--wsh-color-green-dark, #5e6f53) !important;
	text-decoration: none !important;
}
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn:focus {
	/* Remove the leaked blue UA focus ring / any focus box-shadow. */
	outline: none !important;
	box-shadow: none !important;
}
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn:focus-visible {
	/* Intentional accessible focus indicator (keyboard) — green, not blue.
	   Wins over the :focus outline:none above on source order at equal
	   specificity, and only matches keyboard focus. */
	outline: 2px solid var(--wsh-color-green-dark, #5e6f53) !important;
	outline-offset: 2px;
}
.wsh-matrix .wsh-matrix__scroll-nav .wsh-matrix__scroll-btn:disabled {
	/* Muted/greyed so the disabled-at-extremes state stays clearly distinct
	   from the green active buttons. Last in source order so it wins over the
	   hover/focus/active rule if a browser matches :hover on a disabled button. */
	color: var(--wsh-color-grey, #aaa) !important;
	background-color: rgba(0, 0, 0, 0.06) !important;
	border-color: transparent !important;
	cursor: not-allowed;
}

/* ============================================================
   Date range label — Pass 2.5h, sits between the nav bar and the
   matrix header row. Shows the viewport-accurate range (e.g.
   "May 20 – June 18, 2026"). Server emits a placeholder using the
   full rendered window; JS overwrites with the visible-count range
   on load and on resize, UNLESS the page is in selection mode (Pass
   2.5k committed picker range), in which case PHP owns the label
   text and JS leaves it alone.

   Centered above the grid per the matrix-chrome style principle
   (DECISIONS.md 2026-05-20 post-Pass-2.5h Decision 1 — all matrix
   chrome elements center above the grid; differentiation between
   chrome elements is by size/weight, not alignment).
   ============================================================ */
.wsh-matrix__date-range-label {
	padding: 10px 16px;
	font-family: var(--wsh-font-body, 'Poppins', sans-serif);
	font-size: 14px;
	font-weight: 500;
	color: var(--wsh-color-dark);
	background: var(--wsh-matrix-color-sticky-bg);
	border-bottom: 1px solid var(--wsh-matrix-color-cat-border);
	letter-spacing: 0.01em;
	text-align: center;  /* Pass 2.5d-bundle micro-patch — DECISIONS.md 2026-05-20 post-Pass-2.5h Decision 1 (matrix chrome elements center above the grid) */
}

/* ============================================================
   Pass 2.5k — Date range picker.
   Sits between the nav bar and the .wsh-matrix__date-range-label;
   centered above the grid per the matrix-chrome style principle.
   Native HTML5 date inputs — no JS date library. Apply submits the
   form (GET) routing to /availability/?start_date=X&range_end=Y.
   Clear is a regular <a> link to /availability/ (no params), so it
   works without JS.
   ============================================================ */
.wsh-matrix__date-picker {
	display: flex;
	flex-wrap: wrap;
	align-items: end;
	justify-content: center;
	gap: 12px;
	padding: 14px 16px;
	background: var(--wsh-matrix-color-sticky-bg);
	border-bottom: 1px solid var(--wsh-matrix-color-cat-border);
}
.wsh-matrix__picker-field {
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.wsh-matrix__picker-label {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--wsh-color-grey, #656565);
}
.wsh-matrix__picker-input {
	font-family: var(--wsh-font-body, 'Poppins', sans-serif);
	font-size: 14px;
	color: var(--wsh-color-dark);
	background: #fff;
	padding: 8px 10px;
	border: 1px solid var(--wsh-matrix-color-cat-border);
	border-radius: 4px;
	min-width: 160px;
	line-height: 1.2;
}
.wsh-matrix__picker-input:focus {
	outline: 2px solid var(--wsh-color-green-dark, #5e6f53);
	outline-offset: 1px;
	border-color: transparent;
}
/* 2026-06-01 — self-contained picker buttons, same hardening as the scroll
   buttons: every appearance property set explicitly + text-shadow / filter /
   tap-highlight killed so a leaked Hello Elementor / Elementor text-shadow (the
   soft blur), focus ring, or button reset can't touch the Apply / Clear
   controls. Brand tokens only, no hardcoded brand hex. */
.wsh-matrix .wsh-matrix__picker-btn {
	/* 2026-06-01 — match the matrix header/body font (see scroll-btn note);
	   --wsh-font-button's unloaded 600 weight rendered blurry. */
	font-family: var(--wsh-font-body, 'Poppins', sans-serif);
	font-size: 13px;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: 0.02em;
	padding: 9px 18px;
	border-radius: 4px;
	/* Default (Clear / secondary) = outline style. */
	color: var(--wsh-color-green-dark, #5e6f53);
	background: transparent;
	border: 1px solid var(--wsh-color-green-dark, #5e6f53);
	cursor: pointer;
	text-decoration: none !important;
	text-shadow: none !important;
	filter: none !important;
	-webkit-tap-highlight-color: transparent;
}
/* ITEM 2 — Apply is the primary FILLED button. Previously the base rule
   (.wsh-matrix .wsh-matrix__picker-btn, 0,2,0) out-specified the single-class
   .wsh-matrix__picker-btn--apply (0,1,0), so Apply rendered hollow. Scope it to
   2 classes (0,2,0) AND place it after the base + !important on color/background
   so its green fill + white text win decisively. */
.wsh-matrix .wsh-matrix__picker-btn--apply {
	background: var(--wsh-color-green, #7b8e6e) !important;
	border-color: var(--wsh-color-green, #7b8e6e);
	color: #ffffff !important;
}
.wsh-matrix .wsh-matrix__picker-btn--apply:hover,
.wsh-matrix .wsh-matrix__picker-btn--apply:focus {
	background: var(--wsh-color-green-dark, #5e6f53) !important;
	border-color: var(--wsh-color-green-dark, #5e6f53);
	color: #ffffff !important;
}
.wsh-matrix .wsh-matrix__picker-btn--clear:hover,
.wsh-matrix .wsh-matrix__picker-btn--clear:focus {
	background: rgba(var(--wsh-color-green-rgb, 123, 142, 110), 0.08);
	color: var(--wsh-color-green-dark, #5e6f53);
}
/* Kill the leaked blue UA focus ring on picker buttons; green keyboard ring. */
.wsh-matrix .wsh-matrix__picker-btn:focus {
	outline: none !important;
	box-shadow: none !important;
}
.wsh-matrix .wsh-matrix__picker-btn:focus-visible {
	outline: 2px solid var(--wsh-color-green-dark, #5e6f53) !important;
	outline-offset: 2px;
}

/* ============================================================
   Pass 2.5k — Clamp notice.
   Server-emitted when the picked range was clamped to RENDER_CELLS
   or to the today + 365 forward cap. Dismissible via the × button
   (JS handles dismissal — no server roundtrip, no persistence;
   fresh page load shows the notice again if range still clamped).
   role="status" because it's informational, not blocking.
   ============================================================ */
.wsh-matrix__clamp-notice {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	padding: 10px 16px;
	font-size: 13px;
	color: var(--wsh-color-dark);
	background: rgba(255, 184, 119, 0.18);   /* light amber tint of changeover color */
	border-bottom: 1px solid var(--wsh-matrix-color-cat-border);
	text-align: center;
}
.wsh-matrix__clamp-notice--hidden {
	display: none;
}
.wsh-matrix__clamp-notice-text {
	flex: 0 1 auto;
}
.wsh-matrix__clamp-notice-dismiss {
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	padding: 0;
	border: none;
	background: transparent;
	font-size: 18px;
	line-height: 1;
	color: var(--wsh-color-dark);
	cursor: pointer;
	border-radius: 3px;
}
.wsh-matrix__clamp-notice-dismiss:hover,
.wsh-matrix__clamp-notice-dismiss:focus {
	background: rgba(0, 0, 0, 0.06);
}

/* ============================================================
   Pass 2.5g — DEMO badge.
   Top-right corner of the matrix wrapper, only visible when
   WSH_MATRIX_DEMO_MODE === true (PHP emits the element + adds
   .wsh-matrix--demo-mode wrapper class). Amber pill — distinct
   from the sage .wsh-matrix__min-stay-badge so users can tell at
   a glance "this is mock data" vs "this unit has a 30-night min."
   ============================================================ */
.wsh-matrix__demo-badge {
	position: absolute;
	top: 8px;
	right: 8px;
	z-index: 5;
	padding: 3px 10px;
	font-family: var(--wsh-font-button, 'Montserrat', sans-serif);
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #ffffff;
	background: var(--wsh-matrix-color-range-accent, #EF9F27);
	border-radius: 999px;
	line-height: 1.4;
	pointer-events: none;   /* visual marker only */
}

/* Pass 3 — Pass 2.5g client-side pick-rejected inline notice + cell-
   flash animation REMOVED. The cell-click state machine they served
   was retired in Pass 3 in favor of cell-click-routes-to-detail.
   Affected identifiers (now absent from active code):
     .wsh-matrix__pick-rejected-notice + --hidden modifier
     .wsh-matrix__cell--pick-rejected
     @keyframes wsh-matrix-pick-reject-flash
   See DECISIONS.md 2026-05-20 Pass 3 entry. */

/* ============================================================
   Outer container — 2026-06-01: native horizontal scroll.
   PHP now renders the FULL forward span (RENDER_CELLS = 366 — a
   year ahead) into the shared grid tracks; the date columns scroll
   horizontally here instead of being clipped. This replaces the
   Pass 2.5h model (clip a wide block with overflow:hidden + slide a
   60-cell window via prev/next page navigation). The viewport-measure
   + href-rewrite JS that drove that windowing is retired; the only JS
   left on this container is the passive date-range-label sync and the
   booking-surface click listener.

   overflow-y stays `visible`: the box keeps auto height (it grows to
   fit all unit rows), so no internal vertical scrollbar appears and
   the page continues to drive vertical scroll. Only the horizontal
   axis scrolls. The sticky left column (.wsh-matrix__unit-col),
   sticky header corner, and sticky band labels pin against this
   container's left edge as the dates scroll.
   ============================================================ */
/* 2026-06-01 (Item 4) — mirrored top scrollbar. A thin strip above the grid
   with its own horizontal scrollbar; JS sets the inner spacer's width to the
   grid's true content width (scrollContainer.scrollWidth) so the thumb
   proportion matches the bottom scroll, and keeps the two scrollLeft values in
   sync (re-entrancy-guarded). Display/nav only — never touches booking. */
.wsh-matrix__top-scroll {
	overflow-x: auto;
	overflow-y: hidden;
	width: 100%;
}
.wsh-matrix__top-scroll-spacer {
	height: 1px;
}
.wsh-matrix__scroll {
	position: relative;
	overflow-x: auto;
	overflow-y: visible;
	width: 100%;
}

/* Pass 2.5k.1 — internal scroll subsystem REMOVED (wholesale).
   The Pass 2.5k cluster (.wsh-matrix--range-overflow conditional rules,
   sticky-positioned .wsh-matrix__scroll-affordance buttons, the
   .wsh-matrix--dragging cursor states, and the .wsh-matrix--at-scroll-end
   modifier) was built to handle the case where a committed picker range
   exceeded the viewport. The Pass 2.5k.1 picker-as-visual-checker model
   no longer crops the rendered window on picker commit — the matrix
   always renders the viewport-driven 60-cell window and clips with the
   Pass 2.5h `overflow: hidden` default. The whole conditional-scroll
   subsystem became dead code and is removed here.
   Matrix navigation is now Prev/Next only. DECISIONS.md 2026-05-20
   Pass 2.5k.1 entry "Matrix loses internal-scroll capability" documents
   the rationale so a future pass doesn't re-add drag-to-scroll without
   understanding why it was stripped. */

.wsh-matrix__grid {
	/* 2026-06-01 (Item 1 fix) — shrink-wrap to the FULL 366-column content
	   width, not the scroll container's visible width. A block-level width:auto
	   would only fill the visible viewport while the date-cell grid overflowed
	   it, which capped the sticky-left column's containing block at ~one
	   viewport (~2 weeks) before it detached. max-content makes the grid (and
	   the flex rows that fill it) span all 366 columns, so position:sticky;left:0
	   on .wsh-matrix__unit-col / __header-corner / __cat-label holds across the
	   entire year. */
	display: block;
	width: max-content;
}

/* ============================================================
   Sticky top header row (day-of-week + day-of-month).
   ============================================================ */
.wsh-matrix__header-row {
	display: flex;
	/* Item 1 fix backstop — span full content width so the sticky header
	   corner stays pinned across all 366 columns (see .wsh-matrix__grid). */
	min-width: max-content;
	position: sticky;
	top: 0;
	z-index: 3;
	background: var(--wsh-matrix-color-sticky-bg);
	border-bottom: 1px solid var(--wsh-matrix-color-cat-border);
	min-height: var(--wsh-matrix-header-h);
}
.wsh-matrix__header-corner {
	flex: 0 0 var(--wsh-matrix-unit-col-w);
	position: sticky;
	left: 0;
	z-index: 4;
	background: var(--wsh-matrix-color-sticky-bg);
	border-right: 1px solid var(--wsh-matrix-color-cat-border);
}
.wsh-matrix__header-cells {
	display: grid;
	grid-template-columns: repeat(var(--wsh-matrix-cols), var(--wsh-matrix-cell-w));
}
.wsh-matrix__header-cell {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	font-size: 11px;
	color: var(--wsh-matrix-color-header-text);
	border-left: 1px solid var(--wsh-matrix-color-cell-border);
	padding: 4px 0;
	line-height: 1.2;
}
.wsh-matrix__header-cell--weekend {
	background: rgba(0, 0, 0, 0.015);
}
.wsh-matrix__header-cell--today {
	color: var(--wsh-matrix-color-today-outline);
	font-weight: 700;
}
.wsh-matrix__header-month {
	/* Item 2 — top line of the 3-line header ("Jun"). Mirrors the DOW line's
	   small-caps treatment, slightly bolder to read as the group label. */
	text-transform: uppercase;
	letter-spacing: 0.04em;
	font-size: 10px;
	font-weight: 600;
	color: var(--wsh-matrix-color-header-text);
}
.wsh-matrix__header-dow {
	text-transform: uppercase;
	letter-spacing: 0.04em;
	font-size: 10px;
}
.wsh-matrix__header-dom {
	font-size: 14px;
	font-weight: 600;
	color: var(--wsh-color-dark);
}
.wsh-matrix__header-cell--today .wsh-matrix__header-dom {
	color: var(--wsh-matrix-color-today-outline);
}

/* ============================================================
   Category band header (separator between bedroom groups).
   Sticky-left so the label stays visible on horizontal scroll.
   ============================================================ */
.wsh-matrix__cat-header {
	/* Immune to inherited Elementor `text-align:center` (post wrapper): seeds the
	   inline-block label at the LEFT edge of the full-grid-width band so
	   position:sticky;left:0 on .wsh-matrix__cat-label engages. Deliberate
	   defense — do not strip (DECISIONS.md 2026-06-01). */
	text-align: left;
	background: var(--wsh-matrix-color-cat-bg);
	color: var(--wsh-matrix-color-cat-text);
	border-top: 1px solid var(--wsh-matrix-color-cat-border);
	border-bottom: 1px solid var(--wsh-matrix-color-cat-border);
}
.wsh-matrix__cat-label {
	display: inline-block;
	/* Defensive: keep the label's own text + count left-aligned regardless of
	   inherited alignment. Header rule above is the effective un-fling fix. */
	text-align: left;
	position: sticky;
	left: 0;
	padding: 8px 16px;
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}
.wsh-matrix__cat-count {
	color: var(--wsh-color-grey);
	font-weight: 500;
	font-size: 12px;
	margin-left: 4px;
}

/* ============================================================
   Unit row — sticky left column + N cells.
   ============================================================ */
.wsh-matrix__row {
	display: flex;
	/* Item 1 fix backstop — span full content width so the sticky-left unit
	   column's containing block is the whole row, not just the viewport. */
	min-width: max-content;
	min-height: var(--wsh-matrix-cell-h);
	border-bottom: 1px solid var(--wsh-matrix-color-row-border);
}

.wsh-matrix__unit-col {
	flex: 0 0 var(--wsh-matrix-unit-col-w);
	/* min-width:0 overrides the flex-default min-width:auto so a long unit name
	   can't override flex-basis and balloon the column past --wsh-matrix-unit-col-w
	   (which misaligns that row's date cells against the header). overflow:hidden
	   + the name link's existing ellipsis hold every row to one column width.
	   text-align:left counters the inherited Elementor text-align:center that the
	   wrapper cascades into the matrix. */
	min-width: 0;
	overflow: hidden;
	text-align: left;
	position: sticky;
	left: 0;
	/* 2026-06-01 — raised from z-index:2 to 3 so the frozen left column
	   always paints above date cells as they scroll under it. The range-
	   select endpoint cells (.wsh-matrix__cell--selected-start/-end) carry
	   z-index:2; at the old equal z-index a selected cell (later in DOM)
	   could bleed over the sticky column during horizontal scroll. */
	z-index: 3;
	background: var(--wsh-matrix-color-sticky-bg);
	border-right: 1px solid var(--wsh-matrix-color-cat-border);
	padding: var(--wsh-matrix-row-padding) 10px;
	display: flex;
	align-items: center;
	gap: 10px;
}

.wsh-matrix__unit-thumb {
	flex: 0 0 var(--wsh-matrix-thumb-px);
	width: var(--wsh-matrix-thumb-px);
	height: var(--wsh-matrix-thumb-px);
	border-radius: 4px;
	overflow: hidden;
	background: #eee;
	display: block;
}
.wsh-matrix__unit-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.wsh-matrix__unit-meta {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	align-items: flex-start;   /* name / stats / badge flush left under each other */
	text-align: left;          /* immune to inherited Elementor center */
	min-width: 0;
	line-height: 1.3;
}

/* Pass 2.5d — selector specificity bumped from single-class (0,1,0) to
   compound (0,2,0) so the matrix's unit-name link rules beat common
   WordPress theme overrides like `.entry-content a` (0,1,1) without
   needing !important. Defensive against theme overrides reported in
   Pass 2 live-render review; no declaration changes from Pass 2.
   See DECISIONS.md 2026-05-20 Pass 2.5d entry. */
.wsh-matrix .wsh-matrix__unit-name-link {
	color: var(--wsh-matrix-color-link);
	text-decoration: none;
	font-weight: 600;
	font-size: 13px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: 100%;
	border: none;
}
.wsh-matrix .wsh-matrix__unit-name-link:hover,
.wsh-matrix .wsh-matrix__unit-name-link:focus {
	text-decoration: underline;
	color: var(--wsh-matrix-color-link-hover);
}

.wsh-matrix__unit-stats {
	font-size: 11px;
	color: var(--wsh-color-grey);
	letter-spacing: 0.01em;
}

.wsh-matrix__min-stay-badge {
	display: inline-block;
	margin-top: 4px;
	padding: 2px 8px;
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--wsh-matrix-color-badge-text);
	background: var(--wsh-matrix-color-badge-bg);
	border-radius: 999px;
	align-self: flex-start;
	line-height: 1.4;
}

/* ============================================================
   Cells container + individual cells.
   ============================================================ */
.wsh-matrix__cells {
	display: grid;
	grid-template-columns: repeat(var(--wsh-matrix-cols), var(--wsh-matrix-cell-w));
	flex: 1 1 auto;
}

.wsh-matrix__cell {
	position: relative;
	/* Pass 3 — flex centering so the always-visible price text
	   sits vertically + horizontally centered in the 40px cell.
	   Absolutely-positioned descendants (.wsh-matrix__span-label
	   for multi-day booked spans) are unaffected — they pin via
	   their own left/top transform math. */
	display: flex;
	align-items: center;
	justify-content: center;
	height: var(--wsh-matrix-cell-h);
	border-left: 1px solid var(--wsh-matrix-color-cell-border);
	box-sizing: border-box;
	cursor: pointer;
	background: var(--wsh-matrix-color-avail);
}

/* Pass 3 — Always-visible nightly-rate price on every bookable cell.
   Booked cells stay priceless (their booked-span treatment is the story
   — price is irrelevant when the cell is unbookable).
   The em-dash variant reads as "no rate data available" rather than
   "free" — critical for real-mode rendering of the 6 monthly-rental
   units where Escapia returns min_rate = 0. */
.wsh-matrix__cell-price {
	font-family: var(--wsh-font-body, 'Poppins', sans-serif);
	font-size: 13px;
	font-weight: 500;
	color: var(--wsh-color-dark);
	line-height: 1.2;
	letter-spacing: 0.01em;
	pointer-events: none;   /* clicks pass through to the .wsh-matrix__cell parent */
}
.wsh-matrix__cell-price--unknown {
	color: var(--wsh-color-grey, #999);
	font-weight: 400;
}

/* Pass 3 — hover affordance polish. Bookable cells (avail + both
   changeover variants) lift slightly on hover; booked cells signal
   "not clickable" via cursor change. The click routing in JS also
   no-ops on booked cells. */
.wsh-matrix__cell--avail:hover,
.wsh-matrix__cell--changeover-am:hover,
.wsh-matrix__cell--changeover-pm:hover {
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.10);
	filter: brightness(0.97);
}
.wsh-matrix__cell--booked {
	cursor: not-allowed;
}
/* Lead-time grey (v3.5.13) — non-booked cells before the earliest valid
   check-in (Honolulu today + min_lead_days) dimmed as not a valid check-in. */
.wsh-matrix__cell--lead {
	opacity: 0.45;
}

.wsh-matrix__cell--avail {
	background: var(--wsh-matrix-color-avail);
}
.wsh-matrix__cell--booked {
	background: var(--wsh-matrix-color-booked);
}
/* Diagonal: morning is orange (checkout/booked), afternoon is cyan (avail). */
.wsh-matrix__cell--changeover-am {
	background: linear-gradient(
		to bottom right,
		var(--wsh-matrix-color-changeover) 0%,
		var(--wsh-matrix-color-changeover) 49%,
		var(--wsh-matrix-color-avail) 51%,
		var(--wsh-matrix-color-avail) 100%
	);
}
/* Mirrored: morning is cyan (avail), afternoon is orange (check-in). */
.wsh-matrix__cell--changeover-pm {
	background: linear-gradient(
		to bottom right,
		var(--wsh-matrix-color-avail) 0%,
		var(--wsh-matrix-color-avail) 49%,
		var(--wsh-matrix-color-changeover) 51%,
		var(--wsh-matrix-color-changeover) 100%
	);
}
/* Pass 2.5k-correction — today body-cell outline REMOVED.
   The 2px amber outline used to mark every body cell in today's column
   (Pass 2 spec). Pass 2.5k-correction repurposed amber as the SELECTED
   check-in / check-out marker, so body cells in today's column must be
   visually unaffected by default (to avoid confusion with selection
   markers). The today marker is now header-only — see
   .wsh-matrix__header-cell--today below, which colors the day-of-week
   abbreviation and day-of-month numeral in amber (#BA7517).
   The .wsh-matrix__cell--today class is still applied by render_cell()
   to body cells in today's column (for future JS targeting if needed),
   but no longer carries visual styling at rest. */
.wsh-matrix__cell--today {
	/* intentionally empty — class marker only */
}

/* ============================================================
   Pass 2.5k — Selection range visualization (committed picker range).
   --in-range fills with a light sage tint as background-image so the
   underlying availability color (avail / booked / changeover) still
   reads through. --selected-start and --selected-end add an inset
   accent outline on the leading and trailing edges respectively.
   Single-day picked range: cell gets BOTH classes — leading + trailing
   outlines combine to a full outline.

   DECISIONS.md 2026-05-20 post-Pass-2.5h Decision 4 formally promoted
   these three classes from Pass 2.5g demo-only to production targets.
   Pass 2.5k is the first pass to ship the rule blocks. Pass 3's two-
   click gesture will reuse the same classes for the in-progress
   selection visualization — visual language is shared, plumbing
   differs.
   ============================================================ */
.wsh-matrix__cell--in-range {
	background-image: linear-gradient(
		var(--wsh-matrix-color-range-fill),
		var(--wsh-matrix-color-range-fill)
	);
}
.wsh-matrix__cell--selected-start {
	box-shadow: inset 3px 0 0 0 var(--wsh-matrix-color-range-accent),
	            inset 0 2px 0 0 var(--wsh-matrix-color-range-accent),
	            inset 0 -2px 0 0 var(--wsh-matrix-color-range-accent);
	z-index: 2;
}
.wsh-matrix__cell--selected-end {
	box-shadow: inset -3px 0 0 0 var(--wsh-matrix-color-range-accent),
	            inset 0 2px 0 0 var(--wsh-matrix-color-range-accent),
	            inset 0 -2px 0 0 var(--wsh-matrix-color-range-accent);
	z-index: 2;
}
/* Single-day picked range — leading + trailing combine to a full outline. */
.wsh-matrix__cell--selected-start.wsh-matrix__cell--selected-end {
	box-shadow: inset 0 0 0 3px var(--wsh-matrix-color-range-accent);
	z-index: 2;
}
/* Pass 2.5k-correction — today-and-picked composite outline REMOVED.
   The pre-correction rule combined today's amber outline with the
   selection accent. Today body cells no longer outline by default, so
   there's no composite to manage — selection classes on today's column
   simply use their own outline rules unchanged. */

/* ============================================================
   Matrix-is-a-booking-surface (2026-05-29) — two-click range select.
   Invalid check-out pick → brief red inset flash on the rejected cell;
   the check-in selection is preserved so the guest can try a closer
   check-out. (Re-adds the Pass-2.5g pick-reject flash retired in Pass 3.)
   While the booking chain is in flight, the matrix shows a progress
   cursor and ignores further cell clicks (JS also guards via rangeBusy).
   ============================================================ */
.wsh-matrix__cell--pick-rejected {
	animation: wsh-matrix-pick-reject-flash 0.6s ease-out;
}
@keyframes wsh-matrix-pick-reject-flash {
	0%, 100% { box-shadow: none; }
	25%, 75% { box-shadow: inset 0 0 0 3px var(--wsh-matrix-color-reject, #d64545); }
}
.wsh-matrix--booking { cursor: progress; }
.wsh-matrix--booking .wsh-matrix__cell { pointer-events: none; }

/* ============================================================
   Span label — "Booked" centered over a multi-day booked range.
   Pass 2 places the label in the START cell of each span ≥ 2 days.
   The label overflows out of the start cell into adjacent (same-state)
   cells via overflow: visible + absolute positioning.
   ============================================================ */
.wsh-matrix__span-label {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(calc((var(--span-len, 1) - 1) * var(--wsh-matrix-cell-w) / 2 - 50%), -50%);
	white-space: nowrap;
	font-size: 11px;
	font-weight: 600;
	color: var(--wsh-color-dark);
	pointer-events: none;
	z-index: 1;
}

/* ============================================================
   Hover quote tooltip — repositioned by Pass 3 JS. Hidden in Pass 2.
   ============================================================ */
.wsh-matrix__hover-quote {
	position: absolute;
	padding: 4px 10px;
	background: var(--wsh-matrix-color-quote-bg);
	color: var(--wsh-matrix-color-quote-text);
	font-size: 11px;
	border-radius: 3px;
	pointer-events: none;
	white-space: nowrap;
	z-index: 5;
	display: none; /* Pass 3 flips to display: block when wired up */
}
.wsh-matrix__hover-quote[hidden] {
	display: none;
}

/* ============================================================
   Admin diagnostic line at bottom (manage_options only).
   ============================================================ */
.wsh-matrix__admin-diag {
	padding: 6px 12px;
	font-size: 11px;
	color: var(--wsh-color-grey);
	border-top: 1px dashed var(--wsh-matrix-color-cat-border);
	font-family: 'Courier New', monospace;
	margin: 0;
}

/* ============================================================
   Responsive — desktop-first. Mobile (< 800px) is best-effort for v1.
   Pass 2.5h removed the 1199px max-height rule: there is no internal
   scrolling at any viewport width; narrower viewports just clip more
   date cells off the right edge (and JS adjusts the nav slide-distance
   accordingly).
   ============================================================ */
@media (max-width: 799px) {
	.wsh-matrix {
		--wsh-matrix-unit-col-w: 200px;
		--wsh-matrix-cell-w: 36px;
		--wsh-matrix-thumb-px: 40px;
	}
	.wsh-matrix .wsh-matrix__unit-name-link {
		font-size: 12px;
	}
	.wsh-matrix__date-range-label {
		font-size: 13px;
		padding: 8px 12px;
	}
}
