PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents / 4.6.0
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents v4.6.0
4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.14 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.10 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.4.0 4.4.1 4.4.10 4.4.11 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1
embedpress / assets / css / google-reviews.css
embedpress / assets / css Last commit date
fonts 9 months ago vendor 9 months ago admin-notices.css 2 months ago admin.build.css 2 months ago admin.css 8 months ago analytics.build.css 2 months ago blocks.build.css 3 days ago carousel.min.css 2 years ago custom-player.build.css 2 months ago el-icon.css 3 months ago embedpress-elementor.css 2 years ago embedpress.css 3 days ago ep-gr-elementor-picker.css 3 days ago ep-pdf-lightbox.css 3 months ago feature-notices.css 8 months ago feature-preview-modal.css 3 days ago font.css 7 years ago glider.min.css 2 years ago google-reviews.build.css 3 days ago google-reviews.css 3 days ago index.html 7 years ago instagram-shortcode-generator.css 1 month ago lazy-load.css 6 months ago meetup-events.css 8 months ago modal.css 9 months ago onboarding.build.css 2 months ago pdf-gallery.css 3 months ago plyr.css 9 months ago preview.css 6 years ago settings-icons.css 9 months ago settings.css 3 days ago
google-reviews.css
732 lines
1 /* EmbedPress — Google Reviews
2 *
3 * Google-authentic UI. NO cards: reviews are a clean vertical list separated by
4 * hairline dividers (matches Google's own review panel). Class names are a
5 * stable contract shared with the Pro stylesheet/JS — only add, never rename.
6 * Layout variants: .ep-google-reviews--{list|grid|carousel} (free) and Pro's
7 * .ep-gr--preset-{masonry|slider|badge|spotlight|knowledge} / .ep-gr--dark.
8 */
9
10 .ep-google-reviews {
11 --ep-gr-text: #202124;
12 --ep-gr-heading: #202124;
13 --ep-gr-muted: #5f6368;
14 --ep-gr-divider: #e8eaed;
15 --ep-gr-card-border: #eef1f6;
16 --ep-gr-card-fill: #f7f9fc;
17 --ep-gr-card-fill-hover: #eef2f8;
18 --ep-gr-star: #fbbc04;
19 --ep-gr-star-empty: #dadce0;
20 --ep-gr-link: #1a73e8;
21 --ep-gr-bg: #ffffff;
22 --ep-gr-accent: #1a73e8;
23 --ep-gr-gap: 0px;
24 --ep-gr-clamp: 5;
25 /* Structural controls (set inline by the renderer from the columns/gap/
26 max-width settings). Fallbacks here keep standalone CSS sane. */
27 --ep-gr-columns: 3;
28 --ep-gr-max-width: none;
29
30 color: var(--ep-gr-text);
31 font-family: "Google Sans", Roboto, -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
32 font-size: 14px;
33 line-height: 1.5;
34 box-sizing: border-box;
35 max-width: var(--ep-gr-max-width);
36 margin-inline: auto; /* center when capped via max-width */
37 }
38 .ep-google-reviews *,
39 .ep-google-reviews *::before,
40 .ep-google-reviews *::after { box-sizing: border-box; }
41
42 /* ── Style isolation (CSS cascade layer) ──────────────────────────────────
43 * The widget must look identical on EVERY theme/builder. We put a neutralizing
44 * reset for the tags we render INSIDE a named @layer. Layered styles always
45 * lose to unlayered styles in the cascade — but crucially, ALL of our widget
46 * CSS that follows is UNLAYERED, so it always beats both this reset AND any
47 * theme rule that is itself layered. For unlayered theme rules, the reset's
48 * own specificity (a real `.ep-google-reviews tag` selector) plus our class
49 * rules below handle the realistic cases (themes styling generic tags in
50 * post content). Scoped to elements WE emit — never users' embedded content.
51 */
52 @layer ep-gr-reset {
53 .ep-google-reviews :is(div, span, p, a, img, time, button, article, header, h1, h2, h3, h4, ul, ol, li) {
54 margin: 0;
55 padding: 0;
56 border: 0;
57 background: none;
58 box-shadow: none;
59 outline: none;
60 text-decoration: none;
61 list-style: none;
62 float: none;
63 max-width: none;
64 text-transform: none;
65 letter-spacing: normal;
66 text-shadow: none;
67 font-family: inherit;
68 color: inherit;
69 }
70 .ep-google-reviews button { -webkit-appearance: none; appearance: none; cursor: pointer; font: inherit; }
71 .ep-google-reviews img { max-width: 100%; height: auto; vertical-align: middle; }
72 .ep-google-reviews a { color: var(--ep-gr-link); }
73 }
74
75 /* ── Summary header ──────────────────────────────────────────────────────── */
76 .ep-gr-summary { margin-bottom: 8px; }
77 .ep-gr-summary-head {
78 display: flex;
79 align-items: flex-start;
80 justify-content: space-between;
81 gap: 16px;
82 }
83 /* Header alignment (the "Header alignment" control). */
84 .ep-gr-summary--align-center .ep-gr-summary-head,
85 .ep-gr-summary--align-right .ep-gr-summary-head { flex-wrap: wrap; }
86 .ep-gr-summary--align-center .ep-gr-summary-place { text-align: center; flex: 1 1 100%; }
87 .ep-gr-summary--align-right .ep-gr-summary-place { text-align: right; flex: 1 1 100%; }
88 .ep-gr-summary--align-center .ep-gr-summary-rating { justify-content: center; }
89 .ep-gr-summary--align-right .ep-gr-summary-rating { justify-content: flex-end; }
90 .ep-gr-summary--align-center .ep-gr-summary-head { justify-content: center; }
91 .ep-gr-summary--align-right .ep-gr-summary-head { justify-content: flex-end; }
92 .ep-gr-summary-name {
93 font-size: 24px;
94 font-weight: 400;
95 line-height: 1.25;
96 color: var(--ep-gr-heading);
97 }
98 .ep-gr-summary-address {
99 font-size: 14px;
100 color: var(--ep-gr-muted);
101 margin-top: 4px;
102 }
103 .ep-gr-write-review {
104 flex: 0 0 auto;
105 border: 1px solid var(--ep-gr-divider);
106 background: none;
107 color: var(--ep-gr-link);
108 font-size: 14px;
109 font-weight: 500;
110 text-decoration: none;
111 padding: 9px 16px;
112 border-radius: 999px;
113 white-space: nowrap;
114 transition: background 0.15s ease;
115 }
116 .ep-gr-write-review:hover { background: rgba(26, 115, 232, 0.06); text-decoration: none; }
117 .ep-gr-summary-rating {
118 display: flex;
119 align-items: center;
120 gap: 12px;
121 margin-top: 16px;
122 }
123 .ep-gr-summary-score {
124 font-size: 44px;
125 font-weight: 400;
126 line-height: 1;
127 color: var(--ep-gr-heading);
128 }
129 .ep-gr-summary-count { font-size: 15px; color: var(--ep-gr-text); }
130
131 /* ── Star rows (half-star fill overlay) ──────────────────────────────────── */
132 .ep-gr-stars,
133 .ep-gr-starrow {
134 position: relative;
135 display: inline-block;
136 line-height: 1;
137 font-size: 15px;
138 letter-spacing: 1px;
139 white-space: nowrap;
140 }
141 .ep-gr-stars--lg .ep-gr-starrow,
142 .ep-gr-stars.ep-gr-stars--lg { font-size: 24px; letter-spacing: 2px; }
143 .ep-gr-starrow-track { color: var(--ep-gr-star-empty); }
144 .ep-gr-starrow-fill {
145 position: absolute;
146 inset-block-start: 0;
147 inset-inline-start: 0;
148 overflow: hidden;
149 color: var(--ep-gr-star);
150 white-space: nowrap;
151 }
152 /* SVG star glyphs inherit the row's color (track = empty, fill = gold) via
153 currentColor, and size to the row's font-size via em so --lg still scales. */
154 .ep-gr-star-svg {
155 width: 1em;
156 height: 1em;
157 fill: currentColor;
158 vertical-align: -0.12em;
159 }
160 .ep-gr-starrow-track .ep-gr-star-svg { color: var(--ep-gr-star-empty); }
161 .ep-gr-starrow-fill .ep-gr-star-svg { color: var(--ep-gr-star); }
162
163 /* Legacy discrete stars (back-compat) */
164 .ep-gr-star { font-size: 15px; color: var(--ep-gr-star-empty); }
165 .ep-gr-star.is-filled { color: var(--ep-gr-star); }
166
167 /* ── Review list (NO cards — hairline dividers) ──────────────────────────── */
168 .ep-google-reviews--list .ep-gr-items { display: block; }
169 .ep-gr-review {
170 padding: 22px 0;
171 margin: 0;
172 background: none;
173 border: 0;
174 box-shadow: none;
175 }
176 .ep-google-reviews--list .ep-gr-review + .ep-gr-review {
177 border-top: 1px solid var(--ep-gr-divider);
178 }
179
180 .ep-gr-review-head {
181 display: flex;
182 align-items: flex-start;
183 gap: 12px;
184 }
185 .ep-gr-avatar {
186 position: relative;
187 flex: 0 0 40px;
188 width: 40px;
189 height: 40px;
190 border-radius: 50%;
191 background: #f1f3f4;
192 display: inline-flex;
193 align-items: center;
194 justify-content: center;
195 font-weight: 500;
196 font-size: 15px;
197 color: #fff;
198 overflow: hidden;
199 }
200 .ep-gr-avatar--placeholder { background: linear-gradient(135deg, #4285f4, #1a73e8); }
201 .ep-gr-avatar-img {
202 position: absolute;
203 inset: 0;
204 width: 100%;
205 height: 100%;
206 object-fit: cover;
207 border-radius: 50%;
208 }
209 .ep-gr-meta { flex: 1; min-width: 0; }
210 .ep-gr-author {
211 font-size: 14px;
212 font-weight: 600;
213 color: var(--ep-gr-heading);
214 overflow: hidden;
215 text-overflow: ellipsis;
216 white-space: nowrap;
217 }
218 .ep-gr-reviewer-meta {
219 display: flex;
220 align-items: center;
221 gap: 5px;
222 font-size: 13px;
223 color: var(--ep-gr-muted);
224 margin-top: 1px;
225 overflow: hidden;
226 text-overflow: ellipsis;
227 white-space: nowrap;
228 }
229 .ep-gr-dot { opacity: 0.7; }
230 /* Google "G" source badge, top-right of each review card. */
231 .ep-gr-source {
232 flex: 0 0 auto;
233 display: inline-flex;
234 align-items: center;
235 line-height: 0;
236 }
237 .ep-gr-source svg { display: block; }
238
239 .ep-gr-stars-line {
240 display: flex;
241 align-items: center;
242 gap: 8px;
243 margin: 12px 0 8px;
244 }
245 .ep-gr-date { font-size: 13px; color: var(--ep-gr-muted); }
246
247 /* ── Review text + read-more clamp ───────────────────────────────────────── */
248 .ep-gr-body { margin: 0; }
249 .ep-gr-text {
250 color: var(--ep-gr-text);
251 font-size: 14px;
252 line-height: 1.55;
253 white-space: pre-line;
254 display: -webkit-box;
255 -webkit-line-clamp: var(--ep-gr-clamp);
256 -webkit-box-orient: vertical;
257 overflow: hidden;
258 }
259 .ep-gr-body.is-expanded .ep-gr-text {
260 -webkit-line-clamp: unset;
261 display: block;
262 overflow: visible;
263 }
264 .ep-gr-readmore {
265 margin-top: 2px;
266 padding: 0;
267 background: none;
268 border: 0;
269 cursor: pointer;
270 font: inherit;
271 font-size: 14px;
272 font-weight: 500;
273 color: var(--ep-gr-link);
274 }
275 .ep-gr-readmore:hover { text-decoration: underline; }
276 .ep-gr-readmore .ep-gr-readmore-less { display: none; }
277 .ep-gr-body.is-expanded .ep-gr-readmore .ep-gr-readmore-more { display: none; }
278 .ep-gr-body.is-expanded .ep-gr-readmore .ep-gr-readmore-less { display: inline; }
279
280 /* ── Photo strip (horizontal thumbnails, like Google) ────────────────────── */
281 .ep-gr-photos {
282 display: flex;
283 gap: 8px;
284 margin-top: 14px;
285 overflow: hidden;
286 flex-wrap: wrap;
287 }
288 .ep-gr-photo {
289 position: relative;
290 flex: 0 0 auto;
291 width: 104px;
292 height: 104px;
293 border-radius: 10px;
294 overflow: hidden;
295 background: #e8eaed;
296 }
297 .ep-gr-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
298 .ep-gr-photo--more::after {
299 content: attr(data-more);
300 position: absolute;
301 inset: 0;
302 display: flex;
303 align-items: center;
304 justify-content: center;
305 background: rgba(0, 0, 0, 0.55);
306 color: #fff;
307 font-size: 18px;
308 font-weight: 600;
309 }
310
311 /* ── Owner response ──────────────────────────────────────────────────────── */
312 .ep-gr-owner {
313 margin-top: 12px;
314 padding: 10px 14px;
315 background: #f8f9fa;
316 border-radius: 8px;
317 }
318 .ep-gr-owner-head { font-size: 12px; font-weight: 600; color: var(--ep-gr-heading); margin-bottom: 3px; }
319 .ep-gr-owner-text { font-size: 13px; line-height: 1.5; color: var(--ep-gr-muted); }
320
321 /* ── Like / thanks action row ────────────────────────────────────────────── */
322 .ep-gr-rev-actions {
323 display: flex;
324 align-items: center;
325 gap: 18px;
326 margin-top: 14px;
327 color: var(--ep-gr-muted);
328 }
329 .ep-gr-rev-action {
330 display: inline-flex;
331 align-items: center;
332 gap: 6px;
333 font-size: 13px;
334 }
335 .ep-gr-rev-like svg { display: block; }
336 .ep-gr-thanks-icon { font-size: 14px; }
337
338 /* ── Footer (View on Google) ─────────────────────────────────────────────── */
339 .ep-gr-footer { margin-top: 18px; }
340 .ep-gr-view-on-google {
341 display: inline-block;
342 color: var(--ep-gr-link);
343 text-decoration: none;
344 font-weight: 500;
345 font-size: 14px;
346 }
347 .ep-gr-view-on-google:hover { text-decoration: underline; }
348
349 /* ── Grid layout (FLAT bordered boxes, EQUAL height) ─────────────────────── */
350 /* Real CSS grid with stretch rows so every box in a row matches the tallest —
351 uniform, tidy. The read-more clamp keeps that tallest box bounded. Flat look:
352 a hairline border, no shadow (that's what sets it apart from Card). */
353 .ep-google-reviews--grid .ep-gr-items {
354 display: grid;
355 grid-template-columns: repeat(var(--ep-gr-columns, 3), minmax(0, 1fr));
356 gap: var(--ep-gr-gap, 20px);
357 align-items: stretch;
358 }
359 .ep-google-reviews--grid .ep-gr-review {
360 display: flex;
361 flex-direction: column;
362 height: 100%;
363 box-sizing: border-box;
364 background: var(--ep-gr-bg, #fff);
365 border: 1px solid var(--ep-gr-divider);
366 border-radius: 12px;
367 padding: 20px;
368 transition: border-color 0.18s ease;
369 }
370 .ep-google-reviews--grid .ep-gr-review:hover { border-color: #c6ccd8; }
371 /* Push the actions/footer to the card bottom so equal-height cards align. */
372 .ep-google-reviews--grid .ep-gr-rev-actions,
373 .ep-google-reviews--card .ep-gr-rev-actions { margin-top: auto; }
374
375 /* ── Card layout (FILLED boxes, EQUAL height — Essential Addons style) ───── */
376 /* Same equal-height grid. Distinct from the flat Grid layout via a soft FILLED
377 surface + rounder corners (no shadow), with a subtle lift on hover. */
378 .ep-google-reviews--card .ep-gr-items {
379 display: grid;
380 grid-template-columns: repeat(var(--ep-gr-columns, 3), minmax(0, 1fr));
381 gap: var(--ep-gr-gap, 24px);
382 align-items: stretch;
383 }
384 .ep-google-reviews--card .ep-gr-review {
385 display: flex;
386 flex-direction: column;
387 height: 100%;
388 box-sizing: border-box;
389 background: var(--ep-gr-card-fill, #f7f9fc);
390 border: 1px solid transparent;
391 border-radius: 16px;
392 padding: 22px;
393 transition: background 0.18s ease, transform 0.18s ease;
394 }
395 .ep-google-reviews--card .ep-gr-review:hover {
396 background: var(--ep-gr-card-fill-hover, #eef2f8);
397 transform: translateY(-3px);
398 }
399
400 /* ── Carousel (real slider; controls added by JS) ────────────────────────── */
401 .ep-google-reviews--carousel {
402 position: relative;
403 /* Reserve a side gutter so the arrows sit clear of the cards instead of
404 overlapping the review content. The .ep-gr-viewport lives inside this
405 padding; the arrows are placed in the gutter (see .ep-gr-carousel-prev/next).
406 Dots now sit in normal flow under the viewport (no bottom padding needed). */
407 padding-inline: 48px;
408 }
409 /* The stationary .ep-gr-viewport (inserted by google-reviews.js) clips; the
410 .ep-gr-items track inside it is what JS translates. overflow:hidden MUST live
411 on the viewport, NOT the moving track — otherwise the clip box travels with
412 the translate and the next page renders blank. */
413 .ep-google-reviews--carousel .ep-gr-viewport {
414 overflow: hidden;
415 width: 100%;
416 }
417 .ep-google-reviews--carousel .ep-gr-items {
418 display: flex;
419 align-items: flex-start; /* don't stretch short slides to the tallest one */
420 width: 100%;
421 will-change: transform;
422 }
423 /* Per-view = the "Columns" control. Each slide is 100%/columns of the viewport
424 (the JS perView() measures the same ratio to compute pages). On phones we
425 force a single slide regardless of the column setting. */
426 .ep-google-reviews--carousel .ep-gr-review {
427 flex: 0 0 100%;
428 max-width: 100%;
429 /* Gap between carousel slides is applied as horizontal padding INSIDE each
430 slide (half the gap per side → a full gap between adjacent cards). The
431 slide's outer box stays flex-basis:100%/perView, so the JS percentage
432 translate + perView ratio are unaffected. The visible card is .ep-gr-review
433 content; box-sizing keeps padding inside the basis. Default 20px to match
434 the grid/card layouts when no Gap is set. */
435 padding: 22px calc(var(--ep-gr-gap, 20px) / 2);
436 border: 0;
437 }
438 /* Tighter, CONSISTENT text clamp across the card layouts (carousel/grid/card +
439 the Pro masonry/bubble presets) so a verbose review never towers over the
440 short ones — every card starts the same height and "Read more" reveals the
441 rest on click. Photo strips are height-limited for the same reason. */
442 .ep-google-reviews--carousel .ep-gr-text,
443 .ep-google-reviews--grid .ep-gr-text,
444 .ep-google-reviews--card .ep-gr-text,
445 .ep-gr--preset-masonry .ep-gr-text,
446 .ep-gr--preset-bubble .ep-gr-text { -webkit-line-clamp: 4; }
447 .ep-google-reviews--carousel .ep-gr-text { -webkit-line-clamp: 3; }
448 .ep-google-reviews--carousel .ep-gr-photos { max-height: 84px; overflow: hidden; }
449 @media (min-width: 700px) {
450 .ep-google-reviews--carousel .ep-gr-review {
451 flex-basis: calc(100% / var(--ep-gr-columns, 2));
452 max-width: calc(100% / var(--ep-gr-columns, 2));
453 padding-inline: 16px;
454 }
455 }
456 .ep-gr-carousel-arrow {
457 position: absolute;
458 /* Center on the viewport. Dots occupy ~30px at the bottom (now in flow), so
459 the viewport's vertical middle is a touch above the root's middle. */
460 top: calc(50% - 16px);
461 transform: translateY(-50%);
462 z-index: 2;
463 width: 36px;
464 height: 36px;
465 border-radius: 50%;
466 border: 1px solid var(--ep-gr-divider);
467 background: #fff;
468 color: var(--ep-gr-heading);
469 font-size: 22px;
470 line-height: 1;
471 cursor: pointer;
472 display: flex;
473 align-items: center;
474 justify-content: center;
475 transition: background 0.15s ease;
476 }
477 .ep-gr-carousel-arrow:hover { background: #f8f9fa; }
478 /* Centered within the carousel's 48px side gutter, clear of the cards. */
479 .ep-gr-carousel-prev { inset-inline-start: 6px; }
480 .ep-gr-carousel-next { inset-inline-end: 6px; }
481 /* In normal flow directly under the viewport so the dots follow the per-page
482 height (the viewport flexes per page) instead of being pinned to a growing
483 root bottom and leaving a gap. */
484 .ep-gr-carousel-dots {
485 display: flex;
486 justify-content: center;
487 gap: 7px;
488 margin-top: 14px;
489 }
490 .ep-gr-carousel-dot {
491 width: 8px;
492 height: 8px;
493 padding: 0;
494 border: 0;
495 border-radius: 50%;
496 background: var(--ep-gr-star-empty);
497 cursor: pointer;
498 transition: background 0.15s ease, transform 0.15s ease;
499 }
500 .ep-gr-carousel-dot.is-active { background: var(--ep-gr-accent); transform: scale(1.2); }
501
502 /* ── States ──────────────────────────────────────────────────────────────── */
503 .ep-google-reviews--empty,
504 .ep-google-reviews--error {
505 padding: 16px;
506 border: 1px dashed var(--ep-gr-divider);
507 border-radius: 10px;
508 color: var(--ep-gr-muted);
509 text-align: center;
510 }
511 .ep-google-reviews--error { border-color: #fad2cf; color: #c5221f; background: #fce8e6; }
512
513 /* "No place chosen yet" — a calm editor-only prompt, not an error. */
514 .ep-google-reviews--placeholder {
515 display: flex;
516 flex-direction: column;
517 align-items: center;
518 gap: 6px;
519 padding: 28px 20px;
520 border: 1px dashed var(--ep-gr-divider, #dcdfe6);
521 border-radius: 12px;
522 background: #f7f8fb;
523 color: var(--ep-gr-muted, #6b7280);
524 text-align: center;
525 }
526 .ep-google-reviews--placeholder .ep-gr-placeholder-icon { color: var(--ep-gr-accent, #5b4e96); }
527 .ep-google-reviews--placeholder strong { color: var(--ep-gr-heading, #25396f); font-size: 14px; }
528 .ep-google-reviews--placeholder span { font-size: 13px; max-width: 360px; }
529
530 /* Tablet: cap a high column count at 2 so cards stay readable. These are CSS
531 Grid containers, so the responsive override MUST use grid-template-columns —
532 `column-count` is a multi-column (columns) property and is a no-op on a grid,
533 which is why the grid/card/bubble layouts previously never collapsed and cards
534 got cut off in narrow containers. */
535 @media (max-width: 900px) and (min-width: 601px) {
536 .ep-google-reviews--grid .ep-gr-items,
537 .ep-google-reviews--card .ep-gr-items {
538 grid-template-columns: repeat(min(2, var(--ep-gr-columns, 3)), minmax(0, 1fr));
539 }
540 }
541 @media (max-width: 600px) {
542 .ep-google-reviews--grid .ep-gr-items,
543 .ep-google-reviews--card .ep-gr-items {
544 grid-template-columns: 1fr;
545 }
546 /* Tighter gutter on mobile so the single card keeps usable width. */
547 .ep-google-reviews--carousel { padding-inline: 38px; }
548 .ep-gr-carousel-prev { inset-inline-start: 2px; }
549 .ep-gr-carousel-next { inset-inline-end: 2px; }
550 }
551
552 /* --- "Load more" button (FREE, AJAX pagination) --- */
553 .ep-gr-loadmore-wrap { text-align: center; margin-top: 18px; }
554 .ep-gr-loadmore {
555 display: inline-block;
556 padding: 9px 22px;
557 font-size: 14px;
558 font-weight: 600;
559 color: var(--ep-gr-accent, #5b4e96);
560 background: transparent;
561 border: 1.5px solid var(--ep-gr-accent, #5b4e96);
562 border-radius: 999px;
563 cursor: pointer;
564 transition: background .15s, color .15s, opacity .15s;
565 }
566 .ep-gr-loadmore:hover { background: var(--ep-gr-accent, #5b4e96); color: #fff; }
567 .ep-gr-loadmore.is-loading { opacity: .6; cursor: default; }
568 .ep-gr-loadmore:disabled { cursor: default; }
569 .ep-gr--dark .ep-gr-loadmore { color: #e6e8eb; border-color: #3a4150; }
570 .ep-gr--dark .ep-gr-loadmore:hover { background: var(--ep-gr-accent, #5b4e96); border-color: var(--ep-gr-accent, #5b4e96); }
571
572 /* --- Pro-layout upsell — rendered INLINE in the content (not a modal) when an
573 editor picks a Pro layout without Pro. Reuses EmbedPress's pro__alert card
574 design tokens (#131F4D / #7C8DB5 / #5B4E96, 20px radius) but is self-contained
575 here so it styles correctly in every GR context (frontend, Gutenberg SSR
576 preview, AND the Elementor editor, where settings.css isn't loaded). --- */
577 .ep-gr-pro-upsell { display: block; }
578 .ep-gr-pro-upsell .ep-gr-pro-upsell__card {
579 width: 100%;
580 max-width: 500px;
581 margin: 0 auto;
582 background: #fff;
583 border: 1px solid #e6e8f0;
584 border-radius: 20px;
585 padding: 32px 30px;
586 display: flex;
587 flex-direction: column;
588 align-items: center;
589 text-align: center;
590 box-sizing: border-box;
591 }
592 .ep-gr-pro-upsell__icon {
593 width: 64px;
594 height: 64px;
595 display: flex;
596 align-items: center;
597 justify-content: center;
598 background: #f1eefb;
599 border-radius: 50%;
600 margin-bottom: 18px;
601 }
602 .ep-gr-pro-upsell .ep-gr-pro-upsell__card h2 {
603 font-size: 22px;
604 font-weight: 600;
605 color: #131F4D;
606 margin: 0 0 10px;
607 padding: 0;
608 }
609 .ep-gr-pro-upsell .ep-gr-pro-upsell__card p {
610 font-size: 14px;
611 font-weight: 400;
612 color: #7C8DB5;
613 line-height: 1.55;
614 margin: 0 0 18px;
615 max-width: 380px;
616 }
617 .ep-gr-pro-upsell .ep-gr-pro-upsell__btn {
618 display: inline-block;
619 font-size: 14px;
620 font-weight: 600;
621 color: #fff !important;
622 background: #5B4E96;
623 padding: 11px 28px;
624 border-radius: 8px;
625 text-decoration: none;
626 transition: background .15s ease;
627 }
628 .ep-gr-pro-upsell .ep-gr-pro-upsell__btn:hover { background: #4a3f7d; }
629 .ep-gr-pro-upsell .ep-gr-pro-upsell__note {
630 font-size: 12px;
631 color: #9aa3bd;
632 margin: 14px 0 0 !important;
633 }
634
635 /* ── Loading state (place added, reviews still being fetched in the background)
636 The frontend poller (google-reviews.js initPoller) self-refreshes the block
637 when the job finishes — see GoogleReviewsRenderer::render_loading. ─────────── */
638 .ep-google-reviews--loading {
639 border: 1px solid var(--ep-gr-card-border);
640 border-radius: 12px;
641 padding: 18px;
642 background: #fff;
643 }
644 .ep-gr-loading-head {
645 display: flex;
646 align-items: flex-start;
647 gap: 12px;
648 margin-bottom: 18px;
649 }
650 .ep-gr-loading-text { display: flex; flex-direction: column; gap: 3px; }
651 .ep-gr-loading-text strong { font-size: 14px; color: var(--ep-gr-heading); font-weight: 600; }
652 .ep-gr-loading-text span { font-size: 12.5px; color: var(--ep-gr-muted); line-height: 1.5; max-width: 560px; }
653
654 .ep-gr-spinner {
655 flex: 0 0 auto;
656 width: 18px;
657 height: 18px;
658 margin-top: 1px;
659 border: 2px solid var(--ep-gr-divider);
660 border-top-color: var(--ep-gr-link);
661 border-radius: 50%;
662 animation: ep-gr-spin 0.7s linear infinite;
663 }
664 @keyframes ep-gr-spin { to { transform: rotate(360deg); } }
665
666 .ep-gr-skeletons { display: flex; flex-direction: column; gap: 14px; }
667 .ep-gr-skel-card {
668 border: 1px solid var(--ep-gr-card-border);
669 border-radius: 10px;
670 padding: 14px;
671 display: flex;
672 flex-direction: column;
673 gap: 10px;
674 }
675 .ep-gr-skel-row { display: flex; align-items: center; gap: 10px; }
676 .ep-gr-skel-lines { display: flex; flex-direction: column; gap: 6px; flex: 1; }
677 .ep-gr-skel {
678 display: block;
679 background: linear-gradient(90deg, #eef1f6 25%, #f6f8fb 37%, #eef1f6 63%);
680 background-size: 400% 100%;
681 animation: ep-gr-shimmer 1.4s ease infinite;
682 border-radius: 6px;
683 }
684 .ep-gr-skel-avatar { width: 40px; height: 40px; border-radius: 50%; flex: 0 0 auto; }
685 .ep-gr-skel-line { height: 11px; width: 100%; }
686 .ep-gr-skel-line--xs { width: 30%; }
687 .ep-gr-skel-line--sm { width: 45%; }
688 .ep-gr-skel-line--md { width: 70%; }
689 @keyframes ep-gr-shimmer { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }
690
691 /* Admin-only fetch-failed notice (visitors get nothing server-side). */
692 .ep-google-reviews--fetch-failed { text-align: left; }
693 .ep-google-reviews--fetch-failed p { margin: 0 0 8px; }
694 .ep-google-reviews--fetch-failed a { color: var(--ep-gr-link); }
695 .ep-google-reviews--fetch-failed .ep-gr-admin-only-note { color: var(--ep-gr-muted); font-size: 12px; }
696
697 /* ── Dark theme + accent (FREE — mirrors Essential Addons' free Business
698 Reviews). The theme/accent controls are free, so the full dark-mode token
699 set lives here, not only in the Pro stylesheet. Pro's google-reviews-pro.css
700 keeps the PREMIUM-LAYOUT (masonry/badge/etc.) dark variants. ─────────────── */
701 .ep-google-reviews[data-ep-gr-accent] .ep-gr-starrow-fill,
702 .ep-google-reviews[data-ep-gr-accent] .ep-gr-star.is-filled {
703 color: var(--ep-gr-accent);
704 }
705 .ep-google-reviews.ep-gr--dark {
706 --ep-gr-text: #e8eaed;
707 --ep-gr-heading: #ffffff;
708 --ep-gr-muted: #9aa0a6;
709 --ep-gr-divider: #3c4043;
710 --ep-gr-card-border: #34373c;
711 --ep-gr-card-bg: #26282c;
712 --ep-gr-card-fill: #26282c;
713 --ep-gr-card-fill-hover: #2d3035;
714 --ep-gr-star-empty: #5f6368;
715 --ep-gr-link: #8ab4f8;
716 --ep-gr-bg: #202124;
717 background: #202124;
718 padding: 20px;
719 border-radius: 12px;
720 }
721 .ep-gr--dark.ep-google-reviews--card .ep-gr-review,
722 .ep-gr--dark.ep-google-reviews--grid .ep-gr-review {
723 background: var(--ep-gr-card-bg, #26282c);
724 border-color: var(--ep-gr-card-border, #34373c);
725 }
726 .ep-gr--dark .ep-gr-write-review { border-color: #5f6368; }
727 .ep-gr--dark .ep-gr-owner { background: #2a2f37; }
728 .ep-gr--dark .ep-gr-photo { background: #2a2f37; }
729 .ep-gr--dark .ep-gr-avatar--placeholder { background: linear-gradient(135deg, #4285f4, #1a73e8); }
730 .ep-gr--dark .ep-gr-carousel-arrow { background: #2a2f37; border-color: #3c4043; color: #e8eaed; }
731 .ep-gr--dark .ep-gr-carousel-arrow:hover { background: #353b45; }
732