/* client-overrides.css — Alibaba Market & Grille (alibaba)
 *
 * Per-client CSS only. `static-overrides.css` is a verbatim copy of the shared
 * fleet template and is re-synced on every adoption refresh — anything written
 * there is destroyed. This file is auto-linked by `wp-build-page.py` (it emits the
 * <link> only when this file exists) and loads AFTER static-overrides.css, so it
 * wins on source order at equal specificity.
 *
 * ---------------------------------------------------------------------------
 * 1. Flag carousel — restore the live slide geometry (gap-aware slide width)
 * ---------------------------------------------------------------------------
 * Measured at the home gate (probes/alibaba-carousel.mjs), 1440px viewport:
 *
 *                     live      rebuild   delta
 *   widget            114px     168px     +54
 *   slide (first)     115px     158px     +37   <- the cause
 *
 * Every element below the carousel was shifted down by exactly +54px, and nothing
 * else on the page differed. Two rules combine to produce it:
 *
 *   (a) Elementor's OWN stylesheet caps an un-initialised carousel's slides at
 *         .elementor-image-carousel-wrapper:not(.swiper-initialized) .swiper-slide
 *           { max-width: calc(100% / var(--e-image-carousel-slides-to-show, 3)) }
 *       That is 1267/8 = 158.4px here. It divides by the slide COUNT but never
 *       subtracts the gutters, because live it is a placeholder — Swiper is about
 *       to overwrite it with explicit pixel widths that do account for
 *       `spaceBetween`. On a static rebuild Swiper never runs, so the placeholder
 *       IS the final answer. And because it is a `max-width`, it silently beats the
 *       shared template's `width: 240px !important` — `!important` does not help a
 *       `width` that a `max-width` is clamping.
 *
 *   (b) The shared strip then adds its own `gap` on top of slides already sized to
 *       fill 100%, so the row overflows by (N-1) x gap and each slide is too wide
 *       for the space it actually gets.
 *
 * The source configures `slides_to_show: 8` with `image_spacing_custom: 50px`
 * (tablet 5 / 25px, mobile 3). Subtracting the gutters reproduces live exactly:
 *   (1267 - 7x50) / 8 = 114.6px  ->  live measures 115px  ✓
 *   ( 343 - 2x25) / 3 =  97.7px  ->  live measures  97px  ✓
 *
 * Written against `--e-image-carousel-slides-to-show` (Elementor already sets it
 * per breakpoint: 8 / 5 / 3) rather than hard-coded counts, so only the gutter
 * value is client-specific. The general form of this belongs in the shared
 * template — logged to process-learning/INBOX.md 2026-08-26 as a PREVENT, since
 * ANY carousel with a configured image spacing is over-wide by (N-1)xgap today.
 */
.elementor-widget-image-carousel {
  --ym-carousel-gap: 50px;
  /* Operator call at the home gate: advance every 2s. The source stores 1500ms;
   * read against the rendered strip that felt fast, and the flags are the kind of
   * detail a visitor reads rather than glances at. The shared template falls back
   * to the source value when this var is unset, so this is the only place the
   * client's pace is recorded. */
  --ym-carousel-autoplay-ms: 2000;
}

.elementor-widget-image-carousel .swiper,
.elementor-widget-image-carousel .swiper-container,
.elementor-widget-image-carousel .swiper-wrapper {
  gap: var(--ym-carousel-gap) !important;
  /* The shared template reserves 8px under the track for scrollbar clearance.
   * Live has no such gutter, so it reads as pure extra height on the widget.
   * Measured: 8px -> widget 168px, 0 -> 114px, which is live exactly. */
  padding-bottom: 0 !important;
}

/* Restore live's box model inside the slide.
 *
 * With the track padding gone the widget came out 6px SHORT of live at every
 * viewport (-6px at 1440 and at 390 alike) — a constant, which is the tell that it
 * is a font-derived inline-baseline gap rather than a layout error. Live's slide is
 * `display:block` holding a `display:inline` <img>, so each slide is 121px around a
 * 115px flag: the 6px is the descender space under an inline replaced element.
 *
 * The shared template makes the slide `display:flex` and the image `display:block`,
 * which removes it. Reverting BOTH is what matters and the order is not optional —
 * a flex container blockifies its children, so `display:inline` on the image is
 * silently computed back to `block` unless the slide stops being a flex container
 * first. Reproducing live's own two declarations gets the gap back at any font
 * size, which hard-coding `padding-bottom: 6px` would not. */
.elementor-widget-image-carousel .swiper-slide {
  display: block !important;
}
.elementor-widget-image-carousel .swiper-slide img {
  display: inline !important;
}

.elementor-widget-image-carousel .swiper-slide {
  --ym-n: var(--e-image-carousel-slides-to-show, 3);
  flex: 0 0 calc((100% - (var(--ym-n) - 1) * var(--ym-carousel-gap)) / var(--ym-n)) !important;
  width: calc((100% - (var(--ym-n) - 1) * var(--ym-carousel-gap)) / var(--ym-n)) !important;
  /* Defeat Elementor's gap-blind clamp described above. Without this the
   * flex-basis is honoured and then immediately clamped back to 100%/N. */
  max-width: none !important;
}

/* The shared template pins images to a 240px swatch box. These are 193x193 flags
 * shown 8-up, so they must fill their (much smaller) slot instead. `contain` is
 * kept from the shared rule — it is the non-destructive default and these are
 * square, so contain and cover render identically here. */
.elementor-widget-image-carousel .swiper-slide img {
  width: 100% !important;
  max-height: none !important;
  height: auto !important;
}

@media (max-width: 1024px) {
  .elementor-widget-image-carousel { --ym-carousel-gap: 25px; }
}

/* ============================================================================
 * Alibaba Grille menu — client change request, 2026-08-26
 * ============================================================================
 * Lives HERE, not in static-overrides.css: that file is the shared template and
 * the adoption refresh overwrites it wholesale.
 *
 * Self-contained `.ym-menu` namespace rather than cloned Elementor widget markup.
 * Three reasons, all previously paid for on this fleet:
 *   - Elementor styles per WIDGET ID, so a copied widget inherits nothing from
 *     the row it is dropped into;
 *   - a hand-added `.e-con` whose `--display` is unset computes to `inline` and
 *     silently stops being a flex box;
 *   - anything depending on captured per-widget CSS breaks on the next rebuild.
 * Colours and fonts are read from the Elementor kit vars so the section tracks
 * the site's global styles, with literal fallbacks if the kit is ever dropped.
 *
 * Brand yellow (#FCEF33) is used as a RULE/FILL only, never as text — as text on
 * white it is ~1.2:1 and effectively invisible. Text is the kit's dark blue and
 * body ink, both well clear of AA on white.
 */
.ym-menu {
  display: block;
  width: 100%;
  box-sizing: border-box;
  background: #fff;
  /* 6% side padding, NOT a max-width clamp — that is the site's gutter. Every
     content container on this page (404956e, 980bec4, 8707e3c, b396d01, fdb43ca…)
     is an `e-con-full` at 100% width with `--padding-left/right: 6%`, so a
     1140px centred inner made the menu visibly narrower than everything around
     it. Operator change 2026-08-27. */
  padding: 64px 6% 72px;
  /* The theme header is sticky at ~100px, so an anchor jump would otherwise
     land with the heading hidden underneath it. */
  scroll-margin-top: 110px;
  /* Kit global TEXT typography, not hand-picked sizes — Roboto 18px / 1.5em /
     400 / #252525. Operator asked for the menu to match body copy exactly, and
     reading it from the vars means a kit change carries here too. */
  font-family: var(--e-global-typography-text-font-family, "Roboto"), sans-serif;
  font-size: var(--e-global-typography-text-font-size, 18px);
  font-weight: var(--e-global-typography-text-font-weight, 400);
  line-height: var(--e-global-typography-text-line-height, 1.5em);
  color: var(--e-global-color-text, #252525);
}
.ym-menu *,
.ym-menu *::before,
.ym-menu *::after { box-sizing: border-box; }

/* No max-width: the 6% padding on `.ym-menu` IS the gutter, so the grid runs
   edge-to-edge with the rest of the page's content. */
.ym-menu__inner { margin: 0; }

.ym-menu__heading {
  font-family: var(--e-global-typography-primary-font-family, "Frank Ruhl Libre"), Georgia, serif;
  color: var(--e-global-color-secondary, #17344F);
  font-size: clamp(28px, 4.2vw, 44px);
  line-height: 1.15;
  margin: 0 0 10px;
  text-align: center;
}
.ym-menu__intro {
  text-align: center;
  margin: 0 auto 44px;
  max-width: 46em;
  color: #4a4a4a;
}
.ym-menu__intro a {
  color: var(--e-global-color-secondary, #17344F);
  font-weight: 700;
  text-decoration: underline;
}

/* Online-ordering hand-off (client request 2026-09-14: Uber Eats + DoorDash are
 * live). Pills matching the site's link-buttons — same spec as .ym-gallery-more
 * (all three captured button widgets are border-radius:99px; only the FORM
 * submit is square). The intro's 44px bottom margin moves to this row. */
.ym-menu__intro { margin-bottom: 18px; }
.ym-menu__order {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  margin: 0 auto 44px;
}
.ym-menu__order-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 16px 30px;
  border-radius: 99px;
  background-color: var(--e-global-color-primary, #000);
  color: var(--e-global-color-54c861b, #fff);
  font-family: var(--e-global-typography-accent-font-family, "Roboto"), sans-serif;
  font-size: var(--e-global-typography-accent-font-size, 18px);
  font-weight: var(--e-global-typography-accent-font-weight, 500);
  text-transform: var(--e-global-typography-accent-text-transform, uppercase);
  line-height: 1.2;
  text-decoration: none;
  transition: background-color 0.2s ease;
}
/* Brand-matched (operator request 2026-09-14). Real brand colors, AA-verified —
 * no invented shades:
 *   Uber Eats  #06C167 (their green) + BLACK ink = 8.83:1 (their own pairing;
 *              white on that green is 2.38:1, unusable);
 *   DoorDash   #EB1700 (their web red) + white = 4.51:1 (the marketing red
 *              #FF3008 is 3.7:1, under AA — #EB1700 is also theirs).
 * Hovers darken within brand and stay AA: #05A356/black = 6.38, #D42802/white
 * = 5.12. Icons are inline simple-icons glyphs on currentColor. */
.ym-menu__order-icon {
  width: 22px;
  height: 22px;
  margin-right: 10px;
  flex: 0 0 auto;
}
.ym-menu__order-btn--ubereats {
  background-color: #06C167;
  color: #000;
}
.ym-menu__order-btn--ubereats:hover {
  background-color: #05A356;
  color: #000;
}
.ym-menu__order-btn--doordash {
  background-color: #EB1700;
  color: #fff;
}
.ym-menu__order-btn--doordash:hover {
  background-color: #D42802;
  color: #fff;
}
/* Both focus states, not just :focus-visible — the Hello Elementor reset trap
 * that left the lightbox close button pink. */
.ym-menu__order-btn:focus,
.ym-menu__order-btn:focus-visible {
  outline: 3px solid var(--e-global-color-secondary, #17344F);
  outline-offset: 3px;
}

.ym-menu__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 44px 64px;
  align-items: start;
}

.ym-menu__group { display: block; min-width: 0; }

.ym-menu__group-title {
  font-family: var(--e-global-typography-primary-font-family, "Frank Ruhl Libre"), Georgia, serif;
  color: var(--e-global-color-secondary, #17344F);
  /* Stepped up from 22px alongside the 16px→18px body bump, so the group still
     out-ranks the dish names it heads. */
  font-size: 26px;
  line-height: 1.25;
  margin: 0 0 4px;
  padding-bottom: 8px;
  /* the brand yellow, as a fill */
  border-bottom: 3px solid var(--e-global-color-accent, #FCEF33);
}
.ym-menu__group-note {
  margin: 8px 0 0;
  font-size: 15px;
  line-height: 1.5;
  font-style: italic;
  color: #5c6b7a;
}

.ym-menu__list { list-style: none; margin: 14px 0 0; padding: 0; }
.ym-menu__item { margin: 0 0 14px; }
.ym-menu__item:last-child { margin-bottom: 0; }

.ym-menu__row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
}
/* Weight 400, matching the kit's global text weight — the operator compared a
   dish name (was 500) against body copy (400) and asked for them to match. The
   price keeps its 700 so the two ends of the row still read apart. */
.ym-menu__name { flex: 0 1 auto; font-weight: 400; }
.ym-menu__name em { font-style: normal; font-weight: 400; color: #6a6a6a; font-size: .92em; }
/* dotted leader between dish and price */
.ym-menu__lead {
  flex: 1 1 auto;
  min-width: 12px;
  border-bottom: 1px dotted #b9c4d0;
  transform: translateY(-4px);
}
.ym-menu__price {
  flex: 0 0 auto;
  font-weight: 700;
  color: var(--e-global-color-secondary, #17344F);
  font-variant-numeric: tabular-nums;
}
.ym-menu__desc {
  display: block;
  margin-top: 3px;
  padding-right: 3.5em;
  font-size: 16px;
  line-height: 1.5;
  color: #5c6b7a;
}

.ym-menu__footnote {
  margin: 44px 0 0;
  text-align: center;
  font-size: 16px;
  color: #6a6a6a;
}

@media (max-width: 1024px) {
  .ym-menu__grid { gap: 38px 44px; }
}
@media (max-width: 767px) {
  .ym-menu { padding: 44px 6% 52px; }
  .ym-menu__grid { grid-template-columns: 1fr; gap: 34px; }
  .ym-menu__intro { margin-bottom: 32px; }
  .ym-menu__desc { padding-right: 0; }
}

/* Submit-button hover contrast — operator decision 2026-08-27.
 *
 * The captured hover state paints white on the kit's green
 * `--e-global-color-316fab7` (#059326) = 4.03:1, just under the 4.50 AA needs for
 * normal text. Darkened 7% in lightness, same hue: #058923 = 4.56:1. That is the
 * MINIMUM change that clears AA, computed rather than picked, so the button still
 * reads as the same green.
 *
 * ⚠ Scoped to the two button-hover selectors ON PURPOSE — do NOT "simplify" this by
 * overriding `--e-global-color-316fab7` itself. That same variable also paints the
 * reviews section background (element 404956e) and a shape fill (086110c), so
 * retargeting the var would repaint two large areas of the page to fix a hover state.
 * Matches the source rule's specificity and loads after it, so no !important. */
.elementor-30 .elementor-element.elementor-element-32b3a46 .elementor-button[type="submit"]:hover,
.elementor-30 .elementor-element.elementor-element-32b3a46 .e-form__buttons__wrapper__button-next:hover {
  background-color: #058923;
  border-color: #058923;
}

/* ============================================================================
 * Wave divider + reviews width — operator change request, 2026-08-27
 * ============================================================================
 *
 * (1) The `wave-brush` divider at the bottom of container 086110c paints
 *     `--e-global-color-316fab7` (#059326). That was CORRECT before the menu
 *     existed: 086110c used to sit directly on top of the green reviews section
 *     (404956e), so the green wave read as that section bleeding upward.
 *     Inserting `.ym-menu` between them orphaned it — a green wave now breaks
 *     against a white section. Repainted white to match `.ym-menu`'s background.
 *
 *     ⚠ Do NOT "fix" this by retargeting `--e-global-color-316fab7`. That same
 *     variable still paints the reviews section background and the submit-button
 *     hover; changing it would repaint the page to correct one SVG fill. Same
 *     reasoning as the hover rule above.
 *
 *     ⚠ If the menu is ever moved or removed, re-check this — the right colour
 *     for a shape divider is whatever section lands BELOW it, so this is only
 *     white for as long as the white menu follows.
 *
 * Selector mirrors the captured rule exactly (both the `> .elementor-shape-*`
 * and `> .e-con-inner >` forms Elementor emits) and this file loads last, so
 * equal specificity wins on order — no !important needed.
 */
.elementor-30 .elementor-element.elementor-element-086110c > .elementor-shape-bottom .elementor-shape-fill,
.elementor-30 .elementor-element.elementor-element-086110c > .e-con-inner > .elementor-shape-bottom .elementor-shape-fill {
  fill: #fff;
}

/*
 * (2) The Trustindex reviews widget sat in container 6e7ec96 at `--width: 65%`,
 *     which is 65% of its parent's already-gutter-inset content box — ~865px
 *     inside a ~1330px content area at a 1512px viewport, so it read as a narrow
 *     island against every other section. 100% takes it out to the same 6%
 *     gutters as the rest of the page.
 *
 *     The captured CSS already sets `--width: 100%` at the tablet and mobile
 *     breakpoints, so this only changes desktop; declaring it unscoped is safe
 *     and keeps all three breakpoints agreeing.
 */
.elementor-30 .elementor-element.elementor-element-6e7ec96 {
  --width: 100%;
}

/* ============================================================================
 * Gallery "Load more" — operator change request, 2026-08-27
 * ============================================================================
 * Behaviour lives in `client-overrides.js`; this is only its skin. Deliberately
 * built from the SAME kit vars the page's real buttons use (element 2089c22:
 * --e-global-color-primary on --e-global-color-54c861b, accent typography,
 * 16px/30px padding) rather than invented, so it reads as a native control.
 * Black on the section's #DFE6ED is ~18:1 and white on black is 21:1 — both
 * far clear of AA, which matters because this is UPPERCASE at 18px.
 *
 * Not an `.elementor-button`: reusing that class would drag in per-widget-ID
 * rules that were never written for it, and on this codebase a widget's styles
 * are keyed to its ID, so it would inherit nothing predictable anyway.
 */
.ym-gallery-more-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  /* Matches the gallery's own 15px grid gap so the control sits on the same
     rhythm as the tile rows above it. */
  margin-top: 15px;
}

.ym-gallery-status {
  margin: 0;
  font-family: var(--e-global-typography-text-font-family, "Roboto"), sans-serif;
  font-size: 16px;
  line-height: 1.5;
  /* #4a4a4a on #DFE6ED = 7.4:1. The kit's #252525 is heavier than this line
     needs — it is a status, not content. */
  color: #4a4a4a;
}

.ym-gallery-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 16px 30px;
  border: none;
  /* Pill, matching the site's other link-buttons. All three captured button
   * widgets (4336661, 2089c22 "View Menu", a7644da "Call to Order") are
   * `border-radius: 99px`; only the FORM submit (32b3a46) is square, and this
   * is a link-style control, not a submit. Operator call 2026-08-27. */
  border-radius: 99px;
  cursor: pointer;
  background-color: var(--e-global-color-primary, #000);
  color: var(--e-global-color-54c861b, #fff);
  font-family: var(--e-global-typography-accent-font-family, "Roboto"), sans-serif;
  font-size: var(--e-global-typography-accent-font-size, 18px);
  font-weight: var(--e-global-typography-accent-font-weight, 500);
  text-transform: var(--e-global-typography-accent-text-transform, uppercase);
  line-height: 1.2;
  transition: background-color 0.2s ease;
}
.ym-gallery-more:hover {
  /* The kit green, which is what the site's other buttons move to on hover. */
  background-color: var(--e-global-color-316fab7, #059326);
}
/* Both states, not just :focus-visible. Hello Elementor's reset paints
 * `[type="button"]:focus`, and a PROGRAMMATIC .focus() — which the load-more
 * does, to land the user on the first new tile — matches :focus only. Covering
 * one and not the other is exactly what left the lightbox close button pink. */
.ym-gallery-more:focus,
.ym-gallery-more:focus-visible {
  outline: 3px solid var(--e-global-color-secondary, #17344F);
  outline-offset: 3px;
}

/* The newly-revealed tiles take focus programmatically so keyboard users are
 * not dumped back at the top of the document. That focus must be VISIBLE. */
.elementor-widget-gallery .e-gallery-item:focus,
.elementor-widget-gallery .e-gallery-item:focus-visible {
  outline: 3px solid var(--e-global-color-secondary, #17344F);
  outline-offset: 2px;
}

/* ── Trustindex review date: WCAG AA ────────────────────────────────────────
   The widget ships its review dates as #8a8a8a on #ffffff = 3.45:1, which is
   the ONLY colour-contrast failure Lighthouse finds on the site (a11y 97 on
   both form factors, this one node repeated per review). #6b6b6b on white is
   5.33:1 and is visually the same "quiet metadata" grey.

   Scoped under .ti-widget so it can only ever touch vendor markup, and it is
   here rather than in static-overrides.css because that file is overwritten by
   the adoption refresh. The vendor renders this client-side, so nothing in our
   static build could have caught it — it took a real browser run.
   (2026-08-28) */
.ti-widget .ti-review-header .ti-date,
.ti-widget .ti-review-header .ti-date * {
  color: #6b6b6b !important;
}

/* ── Gallery paging: hide the un-paged tiles in CSS, not in JS ──────────────
   ⚠ The `19` below is PAGE_SIZE + 1 from client-overrides.js. Two files, one
   number — change both together.

   Why this cannot be left to the JS. Elementor's e-gallery sets an inline
   background-image on EVERY tile at init, and it does that before our paging
   script gets to hide anything. `display:none` applied afterwards does not
   cancel a fetch that is already away, so a grid showing 18 photos was
   downloading all 54: 6.6 MB of thumbnails on a mobile load, measured
   2026-08-28. A browser does not fetch a background-image for an element that
   is `display:none` at style-resolution time — so the hide has to exist in the
   stylesheet, where it applies before Elementor's JS ever runs.

   Trade-off, stated rather than hidden: with JS disabled the gallery now shows
   18 photos instead of 54 and no Load-more control. That is acceptable here
   only because the lightbox, the carousel and the mobile nav are all already
   JS-dependent on this build — the gallery is not the page's last working
   feature without JS, it is one of several that already are not. */
.elementor-widget-gallery .elementor-gallery__container > .e-gallery-item:nth-child(n+19) {
  display: none;
}

/* ==========================================================================
   /blog + /blog/<slug> (client request 2026-09-14; shim-rendered, see
   08-blog/build-blog-page.py). Same self-contained-namespace philosophy as
   .ym-menu: Elementor styles per widget ID, so hand-added markup inherits
   nothing. Site conventions honoured: 6% side gutter (never a max-width
   clamp), kit heading/text vars, pill buttons elsewhere.
   ========================================================================== */
.ym-blog, .ym-post {
  padding: 56px 6% 72px;
  font-family: var(--e-global-typography-text-font-family, "Roboto"), sans-serif;
  font-size: var(--e-global-typography-text-font-size, 18px);
  font-weight: var(--e-global-typography-text-font-weight, 400);
  line-height: var(--e-global-typography-text-line-height, 1.5em);
  color: var(--e-global-color-text, #252525);
}
.ym-blog *, .ym-blog *::before, .ym-blog *::after,
.ym-post *, .ym-post *::before, .ym-post *::after { box-sizing: border-box; }

.ym-blog__heading, .ym-post__title {
  font-family: var(--e-global-typography-primary-font-family, "Frank Ruhl Libre"), Georgia, serif;
  color: var(--e-global-color-secondary, #17344F);
  font-size: clamp(28px, 4.2vw, 44px);
  line-height: 1.15;
  margin: 0 0 10px;
}
.ym-blog__heading { text-align: center; }
.ym-blog__intro {
  text-align: center;
  margin: 0 auto 44px;
  max-width: 46em;
  color: #4a4a4a;
}
.ym-blog__list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 44px 40px;
  align-items: start;
}
.ym-blog__empty { grid-column: 1 / -1; text-align: center; color: #4a4a4a; margin: 24px 0; }
.ym-blog__card { min-width: 0; }
.ym-blog__card-imglink { display: block; }
.ym-blog__card-img {
  width: 100%;
  aspect-ratio: 4 / 3;   /* the gallery's tile ratio */
  object-fit: cover;
  border-radius: 6px;
  margin-bottom: 14px;
}
.ym-blog__card-date {
  margin: 0 0 6px;
  font-size: .84em;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #6a6a6a;
}
.ym-blog__card-title {
  font-family: var(--e-global-typography-primary-font-family, "Frank Ruhl Libre"), Georgia, serif;
  font-size: 24px;
  line-height: 1.25;
  margin: 0 0 8px;
}
.ym-blog__card-title a { color: var(--e-global-color-secondary, #17344F); text-decoration: none; }
.ym-blog__card-title a:hover { text-decoration: underline; }
.ym-blog__card-excerpt { margin: 0 0 10px; }
.ym-blog__card-more a {
  color: var(--e-global-color-secondary, #17344F);
  font-weight: 700;
  text-decoration: underline;
}
@media (max-width: 1024px) { .ym-blog__list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .ym-blog__list { grid-template-columns: 1fr; } }

.ym-post__inner { max-width: 46em; margin: 0 auto; }
.ym-post__back { margin: 0 0 28px; }
.ym-post__back a, .ym-post__body a {
  color: var(--e-global-color-secondary, #17344F);
  font-weight: 700;
  text-decoration: underline;
}
.ym-post__date { margin: 0 0 20px; font-size: .9em; color: #6a6a6a; }
.ym-post__img { width: 100%; height: auto; border-radius: 6px; margin: 0 0 24px; }
.ym-post__body p { margin: 0 0 1em; }
.ym-post__body h2, .ym-post__body h3 {
  font-family: var(--e-global-typography-primary-font-family, "Frank Ruhl Libre"), Georgia, serif;
  color: var(--e-global-color-secondary, #17344F);
  line-height: 1.2;
  margin: 1.4em 0 .5em;
}
.ym-post__body img { max-width: 100%; height: auto; border-radius: 6px; }
.ym-post__body ul, .ym-post__body ol { margin: 0 0 1em; padding-left: 1.4em; }
.ym-post__body blockquote {
  margin: 0 0 1em;
  padding: 8px 0 8px 20px;
  border-left: 4px solid var(--e-global-color-316fab7, #059326);
  color: #4a4a4a;
}

.ym-visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Socket legal links (operator 2026-09-14: "utility page links in the socket,
 * other side of the FB icon"). Replaces the detached ym-legal-links strip that
 * rendered as a white band UNDER the socket with default pink link styling.
 * Sits inside the socket's own e-con, so it inherits the row layout; typography
 * mirrors the copyright widget beside it. White on the navy socket — AA is not
 * in question at any size. Underlined always: color alone can't mark a link on
 * a single-color bar. */
.ym-socket-links {
  /* Beats the shared [data-ym-legal-links]{display:block;margin-top:.4em} at
   * equal specificity by source order (this file loads after static-overrides).
   * That shared rule exists for the OLD own-line placement; in the socket row
   * this is a flex sibling of the copyright + icon. */
  display: inline-flex;
  margin-top: 0;
  align-items: center;
  gap: 10px;
  font-family: var(--e-global-typography-text-font-family, "Roboto"), sans-serif;
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: .02em;
  color: #fff;
}
.ym-socket-links a {
  color: #fff;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.ym-socket-links a:hover { text-decoration-thickness: 2px; }
