/**
 * REI Frontend Styles
 * φ-based design system using Golden Ratio proportions.
 *
 * @package Real_Estate_Individual
 */

/* ─── CSS Custom Properties (override with REI_Golden.applyPhiCSS in JS) ─── */
:root {
    --rei-base: 16px;
    --rei-phi: 1.618;
    --rei-text-xs: calc(var(--rei-base) / var(--rei-phi) / var(--rei-phi));
    --rei-text-sm: calc(var(--rei-base) / var(--rei-phi));
    --rei-text-md: var(--rei-base);
    --rei-text-lg: calc(var(--rei-base) * var(--rei-phi));
    --rei-text-xl: calc(var(--rei-base) * var(--rei-phi) * var(--rei-phi));
    --rei-text-2xl: calc(var(--rei-base) * var(--rei-phi) * var(--rei-phi) * var(--rei-phi));
    --rei-radius-sm: 8px;
    --rei-radius-md: 13px;
    --rei-radius-lg: 21px;
    --rei-radius-xl: 34px;
    --rei-spacing-xs: calc(var(--rei-base) / var(--rei-phi) / var(--rei-phi));
    --rei-spacing-sm: calc(var(--rei-base) / var(--rei-phi));
    --rei-spacing-md: var(--rei-base);
    --rei-spacing-lg: calc(var(--rei-base) * var(--rei-phi));
    --rei-spacing-xl: calc(var(--rei-base) * var(--rei-phi) * var(--rei-phi));
    --rei-transition: 0.618s cubic-bezier(0.618, 0, 0.382, 1);
    --rei-hover-scale: 1.0618;
    --rei-personal-color: #D4AF37;
    --rei-golden: #D4AF37;
    --rei-golden-light: #F0E6C8;
    --rei-bg-light: #fafaf8;
    --rei-bg-dark: #1a1a1a;
    --rei-text-primary: #2c2c2c;
    --rei-text-secondary: #666;
    --rei-text-muted: #999;
    --rei-shadow: 0 2px 8px rgba(0,0,0,0.08);
    --rei-shadow-hover: 0 8px 21px rgba(0,0,0,0.13);
}

/* ─── Section Base ─── */
.rei-section {
    padding: var(--rei-spacing-xl) 0;
    position: relative;
}

.rei-section-primary {
    min-height: 61.8vh;
    display: flex;
    align-items: center;
}

.rei-section-secondary {
    min-height: 38.2vh;
}

.rei-section-title {
    font-size: var(--rei-text-xl);
    font-weight: 700;
    margin-bottom: var(--rei-spacing-lg);
    color: var(--rei-text-primary);
    position: relative;
    display: inline-block;
}

.rei-section-title::after {
    content: '';
    display: block;
    width: 61.8%;
    height: 3px;
    background: var(--rei-personal-color);
    margin-top: var(--rei-spacing-xs);
    border-radius: 2px;
}

.rei-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 var(--rei-spacing-md);
}

/* ─── Card Grid (ERE columns system, 30px gap) ─── */
/*
 * The tracks are `minmax(0, 1fr)`, never a bare `1fr`, and that is what makes
 * a row of cards a row. `1fr` is `minmax(auto, 1fr)`: its minimum is the
 * item's min-content, so one long title — the whole line of it back when the
 * title was `white-space: nowrap`, its longest word today, see
 * .rei-card-title below — pulled its whole track wider than the others and the
 * grid outgrew its container. With a 0 minimum every track is the same 1/N of
 * the container and the title ellipsizes into it, which is what the ellipsis is
 * there for.
 */
.rei-card-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 30px;
}

/*
 * ERE columns system:
 * columns-*     >= 1200px   the count the settings screen or the block states
 * columns-md-*  992-1199px  the same count
 * columns-sm-*  768-991px   always 1 — a tablet, since the owner's decision
 *                           of 2026-09-28
 * columns-xs-*  481-767px   always 1 — a phone
 * columns-mb-*  <= 480px    always 1
 *
 * The sm, xs and mb steps are printed as the literal 1 by
 * REI_Card_Layout::grid_classes() and have no rule of their own on purpose:
 * they land on the base declaration above, which is already one track. The
 * 2-4 rules those steps still carry are the stylesheet's full copy of the
 * ERE scheme and no grid REI builds resolves to them.
 */
@media (min-width: 1200px) {
    .rei-card-grid.columns-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .rei-card-grid.columns-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .rei-card-grid.columns-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 992px) and (max-width: 1199px) {
    .rei-card-grid.columns-md-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .rei-card-grid.columns-md-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .rei-card-grid.columns-md-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 768px) and (max-width: 991px) {
    .rei-card-grid.columns-sm-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .rei-card-grid.columns-sm-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .rei-card-grid.columns-sm-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (min-width: 481px) and (max-width: 767px) {
    .rei-card-grid.columns-xs-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .rei-card-grid.columns-xs-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .rei-card-grid.columns-xs-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
    .rei-card-grid.columns-mb-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .rei-card-grid.columns-mb-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .rei-card-grid.columns-mb-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/*
 * ─── Card (matches ERE property-grid card) ───
 *
 * How big a card is drawn is the owner's setting (REI_Card_Layout): the width
 * comes from the grid — the card fills the track it was placed in — and the
 * height follows from the aspect ratio. Every card grid emits
 * --rei-card-ratio and --rei-card-max-width (see css_vars()), the cards
 * inherit them, and both defaults below are the site-wide defaults of the
 * settings screen — so a grid that carries no variables (markup built by a
 * script, a template of the owner's own) still looks the way the site is
 * configured to look.
 */
.rei-card {
    background: #f8f8f8;
    padding: 15px 15px 0;
    cursor: pointer;
    opacity: 0;
    /* 100% of the track, and the padding inside it: the card is exactly as
       wide as its column, which is the width REI_Card_Layout::image_width()
       measures the picture at. `box-sizing` is stated rather than inherited
       because a card that added its own 30px of padding on top of the column
       would overflow it on any theme that does not use border-box — and the
       stylesheet is loaded on every theme. `min-width: 0` is the item's half
       of the same rule the tracks follow above: without it a title holding one
       word longer than the column keeps the item at its min-content width and
       the card grows out of that column. */
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    /* A ceiling, not a width: with no number stated (the shipped default, and
       what `none` says) the card fills its column. With one, the card stops
       there and the auto margins centre it in a wider column. */
    max-width: var(--rei-card-max-width, none);
    margin-inline: auto;
}

.rei-card-link,
.rei-card > a {
    display: block;
    color: inherit;
    text-decoration: none;
}

.rei-card-image {
    position: relative;
    overflow: hidden;
    /* Golden by default, read as width ÷ height: 1.618 wide for every 1 high,
       so the picture is a landscape rectangle (~216px high on the picture of
       the shipped three-column card, which is 350px). A single number, not
       "1.618 / 1", so no browser has to parse the slash; object-fit crops the
       picture. */
    aspect-ratio: var(--rei-card-ratio, 1.618);
    background: #f0f0f0;
}

/* The extra `.rei-card` is load-bearing, not decoration: Elementor ships
   `.elementor img { height: auto }` in frontend.min.css, which is the same
   specificity as `.rei-card-image img` and loads later, so it won the height
   and the picture kept its own aspect ratio — `object-fit: cover` did nothing
   and the golden box cropped from the top instead of centring. One class more
   (0,2,1) beats it wherever the page is an Elementor page. */
.rei-card .rei-card-image img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ERE hover effect: dark overlay over the image */
.rei-card-image::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(34, 34, 34, 0.6);
    opacity: 0;
    transition: opacity 0.3s;
    pointer-events: none;
}

.rei-card:hover .rei-card-image::after {
    opacity: 1;
}

/*
 * The exceptions to the card size above, and the reason they exist.
 *
 * The dynamic page's own layout variants are not card grids: layout B draws
 * comparison rows, layout D an editorial row and a narrow inline strip. All
 * three fill the line they sit on by design, so reshaping them into a
 * 380px-wide golden rectangle would break the layout, not follow the setting.
 * They keep the geometry their own stylesheet gives them; the card size
 * settings apply everywhere else, layout A's masonry and layout C included.
 */
.rei-dyn-page[data-rei-layout="B"] .rei-card,
.rei-dyn-page[data-rei-layout="D"] .rei-dyn-editorial .rei-card,
.rei-dyn-page[data-rei-layout="D"] .rei-dyn-inline-strip .rei-card {
    max-width: none;
    margin-inline: 0;
}

.rei-dyn-page[data-rei-layout="B"] .rei-card-image,
.rei-dyn-page[data-rei-layout="D"] .rei-dyn-editorial .rei-card-image,
.rei-dyn-page[data-rei-layout="D"] .rei-dyn-inline-strip .rei-card-image {
    aspect-ratio: 11 / 6; /* the shape these rows had before the setting */
}

.rei-card-badge {
    position: absolute;
    top: 15px;
    left: 0;
    background: var(--rei-personal-color);
    color: #fff;
    padding: 0 5px 0 10px;
    border-radius: 0;
    font-size: 12px;
    font-weight: 600;
    line-height: 20px;
    z-index: 2;
}

.rei-card-badge-new {
    background: #4CAF50;
}

.rei-card-badge-featured {
    background: var(--rei-golden);
    color: #1a1a1a;
}

.rei-card-body {
    padding: 17px 0 0;
}

/* Cards without the ERE-style meta bar keep a bottom padding */
.rei-card-body:not(:has(.rei-card-meta)) {
    padding-bottom: 15px;
}

/*
 * Facts-led card — Phase 2 (§2.3), arm B of the personalization experiment.
 *
 * A visitor whose trait reading is on the verbal side gets the facts first:
 * the body above the picture, which is what "водещи факти" means. The class is
 * emitted only while that experiment's arm is running (see
 * REI_Renderer::card_lead_class()) and it is the only thing that changes — no
 * node is added, moved or renamed, so the card keeps the structure the ERE
 * design parity work reads.
 *
 * The photo-led reading needs no class: a card already leads with its picture.
 * Reverse order is used rather than `order`, because the two children are the
 * only ones the link has and their order is the whole change.
 */
.rei-card.rei-card-lead-facts .rei-card-link,
.rei-card.rei-card-lead-facts > a {
    display: flex;
    flex-direction: column-reverse;
}

/* The body's top padding belonged to a body that stood under a picture. */
.rei-card.rei-card-lead-facts .rei-card-body {
    padding: 0 0 17px;
}

/*
 * ─── The card title: two lines, then an ellipsis ───
 *
 * The owner's decision of 2026-09-28, and it replaces one line. One line was
 * `white-space: nowrap` with `text-overflow: ellipsis` — which is still what
 * ERE itself ships for its own .property-title — and it was affordable while
 * the grids were 4 columns wide. In the three columns the owner settled on,
 * the title has ~158px of the card: the picture is a golden rectangle and the
 * Elementor container of the live page is 625px, so a nowrap line cut a
 * Bulgarian title after about a dozen characters. `-webkit-line-clamp` is the
 * two-line form of the same idea and needs no wrapper around the heading:
 * `display: -webkit-box` with the vertical orientation makes it a stack of
 * line boxes, the clamp counts them, and the browser paints the ellipsis on
 * the last one — so `text-overflow` is gone with it. `white-space` is gone
 * too, or the text would never reach the second line the clamp exists to
 * allow; both are meant to be absent, not forgotten.
 *
 * `min-height` is the other half of the pair, and the reason it is a pair. A
 * card grid row is as tall as its tallest card, so a one-line title left its
 * own card 25px short of the row: the meta bar hovered above the card's bottom
 * edge and the coloured bars of one row did not line up. Two lines is now the
 * height of every title box and a one-line title has the second line empty.
 * Measured in Chrome on the live 625px container, three columns: cards 278.2px
 * with one-line titles and with two-line ones alike, every meta bar flush with
 * the bottom edge.
 *
 * `overflow-wrap` is for the title that is one long word. A word wider than
 * the card is the one thing the clamp cannot ellipsize — there is no line box
 * for it to end — so the word would simply be cropped by the overflow below.
 * Breaking it keeps the guarantee the nowrap rule used to give: nothing of the
 * title is ever cut off sideways.
 */
.rei-card-title {
    font-size: 18px;
    font-weight: 600;
    margin: 0 0 10px;
    color: var(--rei-text-primary);
    line-height: 1.4;
    min-height: 2.8em; /* the two lines the clamp allows, at a 1.4 leading */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow-wrap: break-word;
    overflow: hidden;
}

.rei-card-title a {
    color: inherit;
    text-decoration: none;
}

.rei-card-title a:hover {
    color: var(--rei-personal-color);
}

.rei-card-location {
    font-size: 12px;
    font-weight: 400;
    color: var(--rei-text-secondary);
    margin: 0 0 15px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.rei-card-price {
    display: block;
    font-size: 16px;
    font-weight: 600;
    color: var(--rei-text-primary);
    margin-bottom: 11px;
}

.rei-price-prefix,
.rei-price-postfix {
    font-size: 12px;
    color: var(--rei-personal-color);
}

.rei-card-price-old {
    text-decoration: line-through;
    color: #c0392b;
    font-size: var(--rei-text-sm);
    margin-right: 0.618rem;
}

.rei-card-price-new {
    color: #27ae60;
    font-weight: 700;
}

.rei-card-price-saving {
    font-size: var(--rei-text-xs);
    color: #27ae60;
}

/* ERE-style meta bar: accent background, flush to card edges */
.rei-card-meta {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: center;
    margin: 0 -15px 0 -15px;
    padding: 5px 15px;
    line-height: 20px;
    background: var(--rei-personal-color);
    color: #fff;
    font-size: 12px;
    transition: background-color 0.3s;
}

.rei-card:hover .rei-card-meta {
    background: var(--rei-text-primary);
}

.rei-card-meta span {
    display: flex;
    align-items: center;
    gap: 4px;
}

.rei-card-meta i {
    font-size: var(--rei-text-sm);
}

.rei-card-excerpt {
    line-height: 1.6;
    margin: 0 0 15px;
    color: var(--rei-text-secondary);
}

/*
 * "Не ми показвай повече такива" — the rejection control under a card.
 *
 * Quiet by design: no fill, no accent background, small type and a muted
 * color, so it reads as a footnote and never competes with the card's own
 * link. It gains contrast (and an underline) only on hover or focus.
 * Rendered by templates/card-property.php, and only for a visitor who has
 * consented — see REI_Renderer::render_property_card().
 */
.rei-card-dismiss {
    display: block;
    width: 100%;
    margin: 0;
    padding: 8px 0 13px;
    border: 0;
    background: none;
    color: var(--rei-text-muted);
    font-size: var(--rei-text-sm);
    line-height: 1.4;
    text-align: left;
    cursor: pointer;
    transition: color 0.3s;
}

.rei-card-dismiss:hover,
.rei-card-dismiss:focus-visible {
    color: var(--rei-text-secondary);
    text-decoration: underline;
}

.rei-card-dismiss:focus-visible {
    outline: 2px solid var(--rei-personal-color);
    outline-offset: 2px;
}

/*
 * ─── Zone display modes (a profile zone's `display`) ──────────────────
 *
 * `display` in a profile zone config becomes a class on the block wrapper —
 * `rei-dyn-display-{value}` (class-rei-dynamic-renderer.php:238) — and
 * every value here is one REI_Dynamic_Renderer actually emits today. The
 * class only exists on a dynamic page's block, so these rules cost nothing
 * anywhere else.
 *
 * Two modes are defined, the two the zone configs still ask for: `compact`
 * and `images_only`. The other four the configs used to carry are gone from
 * them instead of guessed at here (F-30, test.md):
 *   - `editorial` and `full` were redundant — the articles section renders
 *     its own editorial reading and variant D picks the look, while "a bigger
 *     card" is what `columns` already does;
 *   - `table` and `carousel` were intended and never built.
 *
 * Layout-independent by design: `display` says how a block reads, not how one
 * of the four variants draws it. `[data-rei-layout]` is in the selector for
 * weight, not as a filter: a layout sheet scopes its own card rules as
 * `.rei-dyn-page[data-rei-layout="X"] .rei-card ...`, so a mode has to
 * outrank that to mean anything, and the attribute is on every dynamic page.
 *
 * Every value below is a layout token (--rei-gap, --rei-section-padding,
 * --rei-text-*, 1rem) or a φ step on one, so a mode moves with the tokens
 * instead of freezing today's numbers.
 */

/*
 * Компактен — същата карта с по-малко въздух.
 *
 * The block re-declares --rei-gap one φ step down (1rem · 0.618 → 1rem ·
 * 0.382). Every layout sheet reads that token for its own paddings, gaps,
 * card margins and grid gaps, so this one declaration tightens the whole
 * block in all four variants at once — and the layout keeps deciding the
 * shape, which is why no per-layout rule is needed here. --rei-gap is
 * declared only on `.rei-dyn-page[data-rei-layout=...]`, so nothing outside
 * the block is touched.
 */
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-compact {
    --rei-gap: calc(1rem * 0.618 * 0.618);
    /* One φ step below --rei-section-padding (1.618rem). */
    padding: calc(var(--rei-section-padding) * 0.618);
}

/* Layout B's block is already the tightest of the four — 1rem · 0.618 of
   vertical padding where A, C and D have 1rem · 1.618 — so a uniform step down
   would be a step *up* for it. It keeps its own token, one step down. */
.rei-dyn-page[data-rei-layout="B"] .rei-dyn-block.rei-dyn-display-compact {
    padding: var(--rei-gap) calc(var(--rei-section-padding) * 0.618);
}

/* The heading follows the block: one φ step down from 1.618rem, which is what
   layout B already draws it at — so the roomier variants come down to it. */
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-compact .rei-dyn-block-title {
    font-size: calc(1rem * 1.618 / 1.618);
}

/* Card title: held at the size the layouts already give it (--rei-text-md =
   1rem) rather than one φ step below, which would be 16px / 1.618 = 9.9px —
   under the legibility floor. The leading is the one layout A gives the same
   title, and the margins tighten with --rei-gap. The base card's 18px comes
   down here too. */
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-compact .rei-card-title {
    font-size: var(--rei-text-md);
    line-height: 1.382;
}

/* The price in layouts A and C is 1.618rem — one φ step down is 1rem, the
   size layouts B and D already use. */
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-compact .rei-card-price {
    font-size: calc(1rem * 1.618 / 1.618);
}

/* Fact rows: the size the layouts already give the address and the meta bar
   (16px / 1.618). The base card draws them at 12px, so this is their step
   down too. */
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-compact .rei-card-location,
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-compact .rei-card-meta,
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-compact .rei-card-meta span {
    font-size: var(--rei-text-sm);
}

/*
 * Само снимки — снимката води.
 *
 * The picture, the name and the price; the address line and the facts bar go.
 * Keeping those two is a decision, not an oversight: both live *inside*
 * .rei-card-body (templates/card-property.php:73-105), so hiding the body
 * would leave a photograph with no name and no figure — and two of the four
 * zones that ask for this mode are titled "Горещи оферти" and "Топ оферти за
 * вас", which an offer without a price cannot be. What the mode drops is what
 * repeats the picture anyway: where the property is, how many rooms it has.
 *
 * The rejection control under the card is deliberately left alone: it is a
 * control, not content, and a visitor must not lose it by a display mode.
 */
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-images_only .rei-card-location,
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-images_only .rei-card-meta {
    display: none;
}

/* The accent bar was what closed the bottom of the card — .rei-card has no
   bottom padding of its own and .rei-card-body:not(:has(.rei-card-meta))
   still matches a bar that is hidden but present — so the body closes it. */
.rei-dyn-page[data-rei-layout] .rei-dyn-block.rei-dyn-display-images_only .rei-card-body {
    padding-bottom: var(--rei-gap);
}

/*
 * "Следващото действие" — the verified next step in the dynamic page's Z4
 * slot (Phase 4 / Next Best Action).
 *
 * Quiet for the same reason the rejection control above is: it is a step, not
 * a banner. Small type, muted color, no fill, no accent background — it reads
 * as a footnote next to the content and gains contrast only on hover or focus.
 * Rendered by REI_Dynamic_Renderer::render_nudge() when the Orchestrator
 * offered a step and its claim was verified (apply_next_action()).
 */
.rei-dyn-nudge-action .rei-dyn-nudge-cta {
    display: inline-block;
    padding-bottom: 2px;
    color: var(--rei-text-muted);
    font-size: var(--rei-text-sm);
    line-height: 1.618;
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, currentColor 38.2%, transparent);
    text-underline-offset: 3px;
    transition: color 0.3s, text-decoration-color 0.3s;
}

.rei-dyn-nudge-action .rei-dyn-nudge-cta:hover,
.rei-dyn-nudge-action .rei-dyn-nudge-cta:focus-visible {
    color: var(--rei-text-secondary);
    text-decoration-color: currentColor;
}

.rei-dyn-nudge-action .rei-dyn-nudge-cta:focus-visible {
    outline: 2px solid var(--rei-personal-color);
    outline-offset: 2px;
}

/* ─── Resonance Badge ─── */
.rei-resonance {
    position: absolute;
    top: var(--rei-spacing-sm);
    right: var(--rei-spacing-sm);
    width: 42px;
    height: 42px;
    z-index: 2;
}

.rei-resonance canvas {
    width: 100%;
    height: 100%;
}

.rei-resonance-value {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: var(--rei-text-xs);
    font-weight: 700;
    color: var(--rei-personal-color);
}

/* ─── Hero Section ─── */
.rei-hero {
    min-height: 45vh;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 60px 20px;
    position: relative;
    overflow: hidden;
}

.rei-hero-bg {
    display: none;
}

.rei-hero-content {
    max-width: 900px;
    padding: 20px;
    position: relative;
    z-index: 1;
}

.rei-hero-title {
    font-size: clamp(1.6rem, 4vw, 2.8rem);
    font-weight: 700;
    color: var(--rei-hero-text-color, var(--rei-personal-color));
    margin-bottom: 16px;
    line-height: 1.2;
}

.rei-hero-subtitle {
    font-size: clamp(1.05rem, 2.5vw, 1.3rem);
    font-weight: 400;
    color: var(--rei-hero-text-color, var(--rei-personal-color));
    opacity: 0.95;
    margin: 0 0 20px 0;
}

.rei-hero-register-link {
    display: inline-block;
    padding: 10px 24px;
    background: var(--rei-personal-color, #D4AF37);
    color: var(--rei-hero-text-color, #fff);
    border-radius: 8px;
    text-decoration: none;
    font-weight: 600;
    transition: all 0.3s ease;
    border: 2px solid transparent;
}

.rei-hero-register-link:hover {
    transform: scale(1.03);
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
    border-color: var(--rei-hero-text-color);
}

/* ─── Hero responsive ─── */
@media (max-width: 768px) {
    .rei-hero {
        min-height: 35vh;
        padding: 40px 15px;
    }
    .rei-hero-register-link {
        padding: 8px 20px;
        font-size: 0.95rem;
    }
}

@media (max-width: 480px) {
    .rei-hero {
        min-height: 30vh;
        padding: 30px 12px;
    }
    .rei-hero-register-link {
        padding: 8px 16px;
        font-size: 0.9rem;
    }
}

/* ─── Profile Spiral Widget ─── */
.rei-widget-spiral {
    position: fixed;
    bottom: var(--rei-spacing-lg);
    right: var(--rei-spacing-lg);
    width: 55px;
    height: 55px;
    z-index: 9999;
    cursor: pointer;
    transition: transform var(--rei-transition);
}

.rei-widget-spiral:hover {
    transform: scale(1.1618);
}

.rei-widget-spiral canvas {
    width: 100%;
    height: 100%;
}

.rei-widget-spiral-tooltip {
    position: absolute;
    bottom: calc(100% + 13px);
    right: 0;
    background: #fff;
    color: var(--rei-text-primary);
    padding: 8px 13px;
    border-radius: var(--rei-radius-sm);
    font-size: var(--rei-text-xs);
    white-space: nowrap;
    box-shadow: var(--rei-shadow);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.382s ease;
}

.rei-widget-spiral:hover .rei-widget-spiral-tooltip {
    opacity: 1;
}

/* ─── Empty State ─── */
.rei-empty {
    text-align: center;
    padding: var(--rei-spacing-xl);
    color: var(--rei-text-muted);
}

/* ─── Cookie Consent ─── */
.rei-cookie-consent {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    background: #fff;
    border-top: 2px solid var(--rei-personal-color);
    box-shadow: 0 -5px 21px rgba(0,0,0,0.08);
    z-index: 99999;
    padding: var(--rei-spacing-md);
}

.rei-cookie-content {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--rei-spacing-md);
    flex-wrap: wrap;
}

.rei-cookie-content p {
    margin: 0;
    flex: 1;
    font-size: var(--rei-text-sm);
}

.rei-cookie-actions {
    display: flex;
    gap: var(--rei-spacing-sm);
    align-items: center;
    flex-wrap: wrap;
}

/* ─── Cookie Settings Panel ─── */
.rei-cookie-settings {
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--rei-transition), opacity var(--rei-transition), padding var(--rei-transition);
    opacity: 0;
    padding: 0 var(--rei-spacing-sm);
    width: 100%;
    box-sizing: border-box;
}

.rei-cookie-settings.rei-cookie-settings-open {
    max-height: 500px;
    opacity: 1;
    padding: var(--rei-spacing-sm);
}

.rei-cookie-settings h4 {
    font-size: var(--rei-text-sm);
    font-weight: 600;
    margin: 0 0 var(--rei-spacing-sm) 0;
    color: var(--rei-text-primary);
}

.rei-cookie-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--rei-spacing-xs) 0;
    cursor: pointer;
    gap: var(--rei-spacing-sm);
}

.rei-cookie-toggle input[type="checkbox"] {
    appearance: none;
    -webkit-appearance: none;
    width: 42px;
    height: 24px;
    background: #ddd;
    border-radius: 12px;
    position: relative;
    cursor: pointer;
    transition: background var(--rei-transition);
    flex-shrink: 0;
}

.rei-cookie-toggle input[type="checkbox"]::after {
    content: '';
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    background: #fff;
    border-radius: 50%;
    transition: transform var(--rei-transition);
}

.rei-cookie-toggle input[type="checkbox"]:checked {
    background: var(--rei-personal-color);
}

.rei-cookie-toggle input[type="checkbox"]:checked::after {
    transform: translateX(18px);
}

.rei-cookie-toggle input[type="checkbox"]:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.rei-cookie-toggle .rei-toggle-label {
    font-size: var(--rei-text-sm);
    color: var(--rei-text-primary);
}

.rei-cookie-save {
    margin-top: var(--rei-spacing-sm);
}

/* ─── Cookie settings trigger ([rei_cookie_settings]) ───
   The way back to the bar after the first choice. It sits in the flow, where
   the owner placed it (a footer widget, the end of a menu) — never fixed over
   the content, and never hidden: it is the only door to a choice that was
   already made, so it must always be drawn. Quiet by design: it borrows the
   type of its surroundings and stays a little faded until it is pointed at,
   which keeps it discreet without making it unreadable. */
.rei-cookie-manage {
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: inherit;
    text-decoration: underline;
    cursor: pointer;
    opacity: 0.7;
}

.rei-cookie-manage:hover,
.rei-cookie-manage:focus {
    opacity: 1;
}

/* The bar is focused by openSettings() when the trigger opens it, so a
   keyboard visitor lands inside the panel it just showed. The bar is a
   container, not a control, so it is not drawn as one. */
.rei-cookie-consent:focus {
    outline: none;
}

/* ─── Buttons ─── */
.rei-btn {
    display: inline-block;
    padding: 8px 21px;
    font-size: var(--rei-text-sm);
    font-weight: 600;
    border: none;
    border-radius: var(--rei-radius-sm);
    cursor: pointer;
    text-decoration: none;
    transition: all var(--rei-transition);
}

.rei-btn-accept {
    background: var(--rei-personal-color);
    color: #fff;
}

.rei-btn-accept:hover {
    background: #fff;
    color: var(--rei-personal-color);
    border: 1px solid var(--rei-personal-color);
}

.rei-btn-reject {
    background: transparent;
    color: var(--rei-text-secondary);
    border: 1px solid #ddd;
}

.rei-btn-reject:hover {
    border-color: #999;
    color: var(--rei-text-primary);
}

.rei-btn-settings {
    background: transparent;
    color: var(--rei-personal-color);
    border: 1px solid var(--rei-personal-color);
}

.rei-btn-settings:hover {
    background: var(--rei-personal-color);
    color: #fff;
}

.rei-btn-secondary {
    background: #f5f5f5;
    color: var(--rei-text-primary);
    border: 1px solid #ddd;
}

.rei-btn-danger {
    background: #e74c3c;
    color: #fff;
}

.rei-btn-danger:hover {
    background: #c0392b;
    color: #fff;
}

.rei-privacy-link {
    font-size: var(--rei-text-xs);
    color: var(--rei-text-muted);
}

/* ─── Fade-in Animation ─── */
.rei-fade-in {
    animation: reiFadeIn 0.618s ease-out forwards;
}

@keyframes reiFadeIn {
    from {
        opacity: 0;
        transform: translateY(13px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* ─── Golden Pulse for 100% maturity ─── */
@keyframes reiGoldenPulse {
    0%, 100% {
        opacity: 1;
        transform: scale(1);
    }
    50% {
        opacity: 0.618;
        transform: scale(1.0618);
    }
}

.rei-pulse {
    animation: reiGoldenPulse 2.618s ease-in-out infinite;
}

/* ─── Price Drop Highlight ─── */
.rei-price-drop-highlight {
    animation: reiPricePulse 2.618s ease-in-out infinite;
}

@keyframes reiPricePulse {
    0%, 100% {
        box-shadow: 0 0 0 0 rgba(39, 174, 96, 0.382);
    }
    50% {
        box-shadow: 0 0 0 8px rgba(39, 174, 96, 0);
    }
}

/* ─── Loading ─── */
.rei-loading {
    position: relative;
    min-height: 100px;
}

.rei-loading::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 34px;
    height: 34px;
    margin: -17px 0 0 -17px;
    border: 3px solid #f0f0f0;
    border-top-color: var(--rei-personal-color);
    border-radius: 50%;
    animation: reiSpin 0.618s linear infinite;
}

@keyframes reiSpin {
    to { transform: rotate(360deg); }
}

/* ─── Responsive ─── */
@media (max-width: 768px) {
    .rei-widget-spiral {
        bottom: var(--rei-spacing-md);
        right: var(--rei-spacing-md);
        width: 42px;
        height: 42px;
    }
}

/* ─── Cookie Consent Mobile ─── */
@media (max-width: 480px) {
    .rei-cookie-actions {
        flex-direction: column;
        width: 100%;
    }
    .rei-cookie-actions .rei-btn,
    .rei-cookie-actions .rei-privacy-link {
        width: 100%;
        text-align: center;
    }
    .rei-cookie-actions .rei-privacy-link {
        font-size: var(--rei-text-sm);
    }
    .rei-cookie-settings.rei-cookie-settings-open {
        padding: var(--rei-spacing-xs);
    }
}

/*
 * The visitor's own interest profile ([rei_profile_interests]).
 *
 * Quiet by design, like the rejection control under a card: the block states
 * stored data, it is not a banner. The plugin styles no heading of its own —
 * every heading here is the owner's text — so what is left is a plain list of
 * names and two muted controls that gain contrast only on hover or focus.
 * Rendered by templates/section-profile-interests.php.
 */
.rei-interests {
    margin: var(--rei-spacing-lg) 0;
}

.rei-interests-heading {
    margin: 0 0 var(--rei-spacing-sm);
    color: var(--rei-text-primary);
    font-size: var(--rei-text-lg);
}

.rei-interests-group + .rei-interests-group {
    margin-top: var(--rei-spacing-md);
}

.rei-interests-label {
    margin: 0 0 var(--rei-spacing-xs);
    color: var(--rei-text-secondary);
    font-size: var(--rei-text-sm);
    font-weight: 600;
}

.rei-interests-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.rei-interests-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--rei-spacing-sm);
    padding: 6px 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.rei-interests-item:last-child {
    border-bottom: 0;
}

.rei-interests-name {
    color: var(--rei-text-primary);
}

.rei-interests-control {
    flex: none;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    color: var(--rei-text-muted);
    font-size: var(--rei-text-sm);
    line-height: 1.4;
    cursor: pointer;
    transition: color 0.3s;
}

.rei-interests-control:hover,
.rei-interests-control:focus-visible {
    color: var(--rei-text-secondary);
    text-decoration: underline;
}

.rei-interests-control:focus-visible {
    outline: 2px solid var(--rei-personal-color);
    outline-offset: 2px;
}

.rei-interests-control:disabled {
    opacity: 0.5;
    cursor: default;
}

/* The reset is not a row's correction, so it stands under the lists. */
.rei-interests-reset {
    margin-top: var(--rei-spacing-md);
}