/* edge-vision.css — Edge Vision catalog components
   Layered on top of styles.css + program.css. Reuses their tokens
   (--prog-ink / --prog-accent / --prog-line / --prog-muted / --prog-card-shadow)
   and only adds what the catalog needs: platform accents, the filter bar,
   day-by-day course cards, learning paths and level cards.
   The two original stylesheets stay untouched. */

:root {
  --ev-mpc: #0066B3;        /* MiniPC — TESA blue */
  --ev-mpc-bg: #E8F1FA;
  --ev-fpg: #6B3FA0;        /* FPGA · KV260 */
  --ev-fpg-bg: #F3ECF9;
  --ev-pse: #0B6B63;        /* PSoC Edge E84 */
  --ev-pse-bg: #E5F1EF;
  --ev-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}

/* ---- hero tweak: the catalog headline is short enough to breathe ---- */
.hero--ev .hero__title { max-width: 26ch; }

/* ---- stat strip ---- */
.ev-stats { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); margin-top: 2rem; }
.ev-stat {
  background: #fff; border: 1px solid var(--prog-line); border-top: 4px solid var(--prog-accent);
  border-radius: 14px; padding: 1.4rem 1.5rem; box-shadow: var(--prog-card-shadow);
}
.ev-stat b { display: block; font-size: 2rem; font-weight: 800; letter-spacing: -.02em; line-height: 1.1; color: var(--prog-ink); }
.ev-stat span { display: block; margin-top: .3rem; font-size: .9rem; color: var(--prog-muted); }
.ev-stat--mpc { border-top-color: var(--ev-mpc); }
.ev-stat--fpg { border-top-color: var(--ev-fpg); }
.ev-stat--pse { border-top-color: var(--ev-pse); }

/* ---- gold callout (reuses the "certified" accent) ---- */
.ev-note {
  background: #FBF6EC; border: 1px solid #EBDCC0; border-left: 4px solid var(--prog-gold);
  border-radius: 12px; padding: 1.2rem 1.4rem; margin-top: 1.8rem;
  font-size: .95rem; color: var(--prog-muted); line-height: 1.7;
}
.ev-note strong { color: #8A5A12; }
.ev-note code { font-family: var(--ev-mono); font-size: .85em; color: var(--prog-ink); }
.section--dark .ev-note { background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.14); color: rgba(255,255,255,.82); }
.section--dark .ev-note strong { color: #E5C07B; }
.section--dark .ev-note code { color: #cfe0f2; }

/* ---- platform tracks (3-up version of .track) ---- */
.track--mpc { background: linear-gradient(135deg, #0066B3, #00355F); }
.track--fpg { background: linear-gradient(135deg, #6B3FA0, #3C2160); }
.track--pse { background: linear-gradient(135deg, #0B6B63, #063B36); }
.track__code { font-family: var(--ev-mono); font-size: .82rem; opacity: .8; margin-top: .9rem; display: block; }

/* ---- filter bar ----
   The filter is pure CSS: five visually-hidden radios sit before .ev-filter and
   #coursesGroups, and :checked ~ rules do the showing/hiding. No JavaScript is
   involved, so filtering works on file://, in print, and with JS disabled.
   Keyboard users get real radio-group semantics (arrow keys) for free. */
.ev-radio { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* Not sticky: three stacked rows are ~230px tall, which would pin a third of the
   viewport under the 64px nav. It scrolls with the page instead. */
.ev-filter {
  margin: 1.6rem 0 .4rem; padding: .9rem 1.2rem 1rem;
  background: #fff; border: 1px solid var(--prog-line); border-radius: 14px;
  box-shadow: var(--prog-card-shadow);
}
.ev-filter__row { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; padding: .32rem 0; }
.ev-filter__row + .ev-filter__row { border-top: 1px solid var(--prog-line); padding-top: .55rem; margin-top: .2rem; }
.ev-filter__lbl {
  flex: 0 0 6.2rem; font-size: .72rem; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--prog-muted);
}
.ev-chip {
  display: inline-block;
  border: 1.5px solid var(--prog-line); background: #fff; color: var(--prog-ink);
  border-radius: 999px; padding: .34rem .85rem; font: inherit; font-size: .85rem; font-weight: 600;
  cursor: pointer; user-select: none; transition: border-color .15s, background .15s, color .15s;
}
.ev-chip:hover { border-color: var(--prog-accent); color: var(--prog-accent); }
.ev-filter__count {
  display: block; margin-top: .7rem; padding-top: .6rem; border-top: 1px solid var(--prog-line);
  font-size: .88rem; font-weight: 700; color: var(--prog-ink);
}
/* which count span shows is decided in the generated edge-vision-filter.css */
.ev-filter__count > span { display: none; }

/* no-results notice — shown by the generated CSS for empty combinations */
.ev-empty {
  display: none; padding: 3rem 1rem; text-align: center;
  color: var(--prog-muted); font-size: .98rem;
}

/* All :checked state rules (active chip, card/group hiding, count line) live in
   the generated css/edge-vision-filter.css so they can never drift from the data.
   Chip rules there target a class, not [for="…"]: Chromium does not reliably
   re-run style invalidation for an attribute selector on a <label> when the
   associated radio changes, so the highlight would stick on the first chip. */

/* ---- course group ---- */
.ev-grp { margin-top: 2.6rem; }
.ev-grp__h { display: flex; align-items: baseline; gap: .8rem; flex-wrap: wrap; padding-bottom: .7rem; border-bottom: 1px solid var(--prog-line); }
.ev-grp__h h3 { font-size: 1.3rem; font-weight: 800; color: var(--prog-ink); margin: 0; }
.ev-grp__h span { font-size: .9rem; color: var(--prog-muted); }
.ev-grp .course-grid { margin-top: 1.4rem; }

/* ---- platform badges ---- */
.badge--mpc { background: var(--ev-mpc-bg); color: var(--ev-mpc); border: 1px solid #BCD6EE; text-transform: none; }
.badge--fpg { background: var(--ev-fpg-bg); color: var(--ev-fpg); border: 1px solid #DCC9EC; text-transform: none; }
.badge--pse { background: var(--ev-pse-bg); color: var(--ev-pse); border: 1px solid #B9D8D3; text-transform: none; }
.badge--lv { background: var(--prog-ink); color: #fff; font-family: var(--ev-mono); letter-spacing: .06em; }

/* ---- course card ---- */
/* Cover art is 1672×941 (16:9). aspect-ratio + explicit width/height on the img
   reserve the space before it loads, so lazy-loading causes no layout shift. */
.ev-cover {
  aspect-ratio: 16 / 9; background: var(--prog-accent-soft);
  border-bottom: 1px solid var(--prog-line); overflow: hidden;
}
.ev-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

.course-card--ev .course-card__body { gap: .5rem; }
.ev-card__top { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.ev-card__code { font-family: var(--ev-mono); font-size: .8rem; font-weight: 700; color: var(--prog-muted); letter-spacing: .02em; }
.ev-card__plats { display: flex; gap: .35rem; flex-wrap: wrap; margin-left: auto; }
.course-card--ev h3 { font-size: 1.14rem; margin-top: .15rem; }
.ev-card__th { font-size: .92rem; color: var(--prog-muted); }

.ev-day { margin-top: .7rem; }
.ev-day__h { font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--prog-accent); margin-bottom: .3rem; }
.ev-day ul { list-style: none; margin: 0; padding: 0; }
.ev-day li { position: relative; padding: .18rem 0 .18rem 1rem; font-size: .9rem; line-height: 1.55; color: var(--prog-muted); }
.ev-day li::before { content: ""; position: absolute; left: 0; top: .72rem; width: 4px; height: 4px; border-radius: 50%; background: #C2CBD6; }

.ev-pre {
  margin-top: auto; padding-top: .8rem; border-top: 1px dashed var(--prog-line);
  font-size: .85rem; color: var(--prog-muted);
}
.ev-pre b { color: var(--prog-ink); font-weight: 700; }
.ev-pre code { font-family: var(--ev-mono); font-size: .92em; color: var(--prog-accent); font-weight: 600; }

/* ---- card footer: book + share ---- */
.ev-card__foot { margin-top: .8rem; display: flex; align-items: center; gap: .5rem; }
.ev-card__foot .ev-book { flex: 1; }

/* Share and the details popup both need JavaScript, so they stay hidden until
   course-actions.js marks the document — no dead buttons when scripts are off.
   Nothing is lost: the card already shows every detail the popup does, and
   "เลือกคอสนี้" is a plain mailto: link that always works. */
.course-card__sharewrap, .ev-detail { display: none; }
.has-js .course-card__sharewrap { display: inline-block; }
.has-js .ev-detail { display: inline-block; }
.has-js .course-card--ev .ev-cover { cursor: zoom-in; }

.ev-detail {
  background: none; border: 1px solid var(--prog-line); color: var(--prog-ink);
  border-radius: 8px; padding: .35rem .7rem;
  font: inherit; font-size: .8rem; font-weight: 600; cursor: pointer;
}
.ev-detail:hover { border-color: var(--prog-accent); color: var(--prog-accent); }
.course-card__sharemenu a {
  display: block; padding: .5rem .6rem; border-radius: 7px;
  font-size: .85rem; color: var(--prog-ink); white-space: nowrap; text-decoration: none;
}
.course-card__sharemenu a:hover { background: var(--prog-accent-soft); }

/* A deep-linked card (#c-VIS-F01) flashes a ring — the .is-shared styling it
   uses already exists in program.css, so nothing is redefined here. */

/* ---- booking dialog ---- */
.ev-dialog {
  border: none; border-radius: 18px; padding: 0; width: min(540px, calc(100vw - 2rem));
  color: var(--prog-ink); background: #fff;
  box-shadow: 0 24px 70px rgba(10,22,40,.32);
  /* The `* { margin: 0 }` reset in styles.css also hits <dialog>, killing the UA's
     `margin: auto` that centres a modal inside its `inset: 0` box. Put it back. */
  margin: auto;
  max-height: min(86vh, 760px);
}
/* Only while open — a bare `display: flex` would override the UA's
   `dialog { display: none }` and leave the dialog on screen when closed. */
.ev-dialog[open] { display: flex; flex-direction: column; }
/* head and foot stay put, the fields scroll on short screens */
.ev-dialog__head, .ev-dialog__foot { flex: none; }
.ev-dialog::backdrop { background: rgba(8,12,24,.62); }
.ev-dialog__x { position: absolute; top: .5rem; right: .6rem; }
.ev-dialog__x button {
  width: 36px; height: 36px; border: none; border-radius: 50%; background: none;
  font-size: 1.5rem; line-height: 1; color: var(--prog-muted); cursor: pointer;
}
.ev-dialog__x button:hover { background: var(--prog-line); color: var(--prog-ink); }
.ev-dialog__head { padding: 1.4rem 1.5rem 1rem; border-bottom: 1px solid var(--prog-line); }
.ev-dialog__eyebrow {
  font-size: .7rem; font-weight: 800; letter-spacing: .14em; text-transform: uppercase;
  color: var(--prog-accent); margin-bottom: .35rem;
}
.ev-dialog__head h3 { font-size: 1.15rem; font-weight: 800; line-height: 1.3; margin: 0 2rem .35rem 0; }
.ev-dialog__meta { font-size: .84rem; color: var(--prog-muted); line-height: 1.55; }
.ev-dialog__meta code { font-family: var(--ev-mono); font-weight: 700; color: var(--prog-accent); }

.ev-dialog__body { padding: 1.1rem 1.5rem; display: flex; flex-direction: column; gap: .7rem; overflow-y: auto; }
.ev-dialog__row { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }
.ev-dialog label {
  display: flex; flex-direction: column; gap: .25rem;
  font-size: .8rem; font-weight: 700; color: var(--prog-ink);
}
.ev-dialog input, .ev-dialog textarea {
  font: inherit; font-size: .92rem; font-weight: 400; color: var(--prog-ink);
  padding: .5rem .65rem; border: 1.5px solid var(--prog-line); border-radius: 9px;
  background: #fff; width: 100%;
}
.ev-dialog input:focus, .ev-dialog textarea:focus { outline: none; border-color: var(--prog-accent); }
.ev-dialog textarea { resize: vertical; }
.ev-dialog__hint { font-size: .78rem; color: var(--prog-muted); line-height: 1.6; margin-top: .1rem; }

.ev-dialog__foot {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  padding: 1rem 1.5rem 1.3rem; border-top: 1px solid var(--prog-line); background: #FBFCFE;
  border-radius: 0 0 18px 18px;
}
.btn--ghost-outline {
  background: #fff; color: var(--prog-ink); border: 1.5px solid var(--prog-line);
  padding: .65rem 1.2rem; font-size: .9rem;
}
.btn--ghost-outline:hover { border-color: var(--prog-accent); color: var(--prog-accent); background: #fff; transform: none; }
.ev-dialog__cancel {
  background: none; border: none; font: inherit; font-size: .9rem; font-weight: 600;
  color: var(--prog-muted); cursor: pointer; margin-left: auto; padding: .65rem .4rem;
}
.ev-dialog__cancel:hover { color: var(--prog-ink); text-decoration: underline; }

/* ---- detail popup: same dialog shell, wider, cover art on top ---- */
.ev-dialog--detail { width: min(720px, calc(100vw - 2rem)); max-height: min(90vh, 900px); }
.ev-detail__cover { flex: none; border-radius: 18px 18px 0 0; border-bottom: 1px solid var(--prog-line); }
.ev-dialog--detail .ev-dialog__x button {
  background: rgba(255,255,255,.9); color: var(--prog-ink);
  box-shadow: 0 2px 10px rgba(10,22,40,.25);
}
.ev-detail__scroll { overflow-y: auto; padding: 1.3rem 1.5rem 1.1rem; }
.ev-detail__head { margin-bottom: .4rem; }
.ev-detail__top { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .5rem; }
.ev-dialog--detail h3 { font-size: 1.3rem; font-weight: 800; line-height: 1.3; margin-bottom: .3rem; }
.ev-dialog--detail .ev-card__th { font-size: .95rem; margin-bottom: .5rem; }
.ev-detail__days { display: grid; grid-template-columns: 1fr 1fr; gap: .3rem 1.6rem; margin-top: .8rem; }
.ev-dialog--detail .ev-pre { margin-top: 1rem; }

@media (max-width: 620px) {
  .ev-detail__days { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .ev-dialog__row { grid-template-columns: 1fr; }
  .ev-dialog__cancel { margin-left: 0; }
}

/* ---- learning paths ---- */
.ev-path { text-align: left; }
.ev-path ol { margin: .4rem 0 0; padding-left: 1.3rem; display: flex; flex-direction: column; gap: .18rem; }
.ev-path li { font-size: .9rem; color: rgba(255,255,255,.9); line-height: 1.5; }
.ev-path li code { font-family: var(--ev-mono); font-size: .84rem; font-weight: 700; color: #fff; margin-right: .35rem; }
.ev-path__tot {
  margin-top: 1rem; padding-top: .8rem; border-top: 1px solid rgba(255,255,255,.22);
  font-size: .92rem; color: rgba(255,255,255,.9);
}
.ev-path__tot b { color: #fff; font-weight: 800; }
.found-card--mpc { background: linear-gradient(135deg, #0066B3 0%, #00355F 100%); }
.found-card--fpg { background: linear-gradient(135deg, #6B3FA0 0%, #3C2160 100%); }
.found-card--pse { background: linear-gradient(135deg, #0B6B63 0%, #063B36 100%); }

/* ---- level cards (L2–L5) ---- */
.ev-lv-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); margin-top: 2rem; }
.ev-lv-card {
  --lv: var(--prog-accent);
  background: #fff; border: 1px solid var(--prog-line); border-top: 4px solid var(--lv);
  border-radius: 14px; padding: 1.4rem; box-shadow: var(--prog-card-shadow);
  display: flex; flex-direction: column; gap: .45rem;
}
.ev-lv-card__n { font-family: var(--ev-mono); font-size: 1.5rem; font-weight: 800; color: var(--lv); line-height: 1; }
.ev-lv-card h3 { font-size: 1.02rem; font-weight: 700; color: var(--prog-ink); margin: 0; }
.ev-lv-card p { font-size: .89rem; line-height: 1.55; color: var(--prog-muted); margin: 0; }
.ev-lv-card__n small { font-family: var(--font); font-size: .78rem; font-weight: 700; color: var(--prog-muted); margin-left: .5rem; }

@media (max-width: 768px) {
  .ev-filter { padding: .8rem .9rem .9rem; }
  .ev-filter__lbl { flex: 0 0 100%; margin-bottom: .1rem; }
  .ev-chip { font-size: .82rem; padding: .3rem .7rem; }
}

@media print {
  .nav, .mobile-nav, .ev-filter, .hero__ctas, .hero__browse, .apply-band { display: none !important; }
  .section { padding: 1rem 0 !important; }
  .course-card { break-inside: avoid; box-shadow: none; }
  .reveal { opacity: 1 !important; transform: none !important; }
}

/* ============================================================
   PROGRAMMES — scheduled workshops (js/programs.js)
   Separate from the Edge Vision catalog: no platform/level/layer
   tags, so no filter applies. One wide card per programme.
   ============================================================ */
.pg-grid { display: grid; gap: 1.6rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 460px), 1fr)); margin-top: 2rem; }
.pg-card { background: #fff; }
/* Posters range from 3:2 landscape to 1:2.1 portrait, so a fixed box with
   object-fit:contain keeps every card the same height and still shows the whole
   poster. Click opens it full size. */
/* An explicit height, NOT aspect-ratio: a percentage height on the image does not
   resolve against an aspect-ratio-derived box, which left tall posters clipped
   instead of letterboxed. With a definite height the image can be contained. */
.pg-cover {
  display: grid; place-items: center; height: clamp(240px, 24vw, 340px);
  background: var(--prog-accent-soft); border-bottom: 1px solid var(--prog-line);
  overflow: hidden; cursor: zoom-in; padding: .6rem;
}
.pg-cover img { width: 100%; height: 100%; object-fit: contain; display: block; }
.pg-kind {
  align-self: flex-start; text-transform: none; letter-spacing: .02em;
}
.pg-card h3 { font-size: 1.16rem; line-height: 1.3; margin-top: .3rem; }
.pg-sub { font-size: .88rem; font-weight: 600; color: var(--prog-accent); line-height: 1.45; }
.pg-facts { gap: .35rem .9rem; }
.pg-out { margin-top: .8rem; }
.pg-out b { font-size: .68rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase; color: var(--prog-ok); }
.pg-out ul { list-style: none; margin: .3rem 0 0; padding: 0; }
.pg-out li { position: relative; padding: .18rem 0 .18rem 1.2rem; font-size: .9rem; color: var(--prog-muted); line-height: 1.55; }
.pg-out li::before { content: "✓"; position: absolute; left: 0; color: var(--prog-ok); font-weight: 800; }
.pg-partners { margin-top: .5rem; font-size: .82rem; color: var(--prog-muted); line-height: 1.6; }
.pg-partners b { color: var(--prog-ink); font-weight: 700; }
.pg-note {
  margin-top: .6rem; padding: .55rem .75rem; border-radius: 10px;
  background: #FBF6EC; border: 1px solid #EBDCC0;
  font-size: .8rem; color: var(--prog-muted); line-height: 1.6;
}
.pg-docs { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .7rem; }
.pg-doc {
  font-size: .8rem; font-weight: 600; color: var(--prog-accent);
  border: 1px solid var(--prog-line); border-radius: 8px; padding: .3rem .6rem;
}
.pg-doc:hover { border-color: var(--prog-accent); background: var(--prog-accent-soft); }

/* ---- programme details dialog ---- */
.pg-dialog { width: min(760px, calc(100vw - 2rem)); max-height: min(90vh, 900px); }
.pg-dialog__scroll { overflow-y: auto; }
.pg-dlg__cover {
  display: grid; place-items: center; height: clamp(220px, 30vh, 340px);
  background: var(--prog-accent-soft); border-bottom: 1px solid var(--prog-line);
  border-radius: 18px 18px 0 0; overflow: hidden; padding: .7rem;
}
.pg-dlg__cover img { width: 100%; height: 100%; object-fit: contain; display: block; }
.pg-dlg__main { padding: 1.2rem 1.5rem 1.4rem; display: flex; flex-direction: column; gap: .3rem; }
.pg-dlg__main .pg-kind { align-self: flex-start; }
.pg-dlg__main h3 { font-size: 1.25rem; font-weight: 800; line-height: 1.3; margin: .3rem 0 .1rem; }
.pg-dialog .ev-dialog__x button { background: rgba(255,255,255,.9); box-shadow: 0 2px 10px rgba(10,22,40,.25); }

/* the condensed card keeps its footer buttons on one row */
.pg-card .ev-card__foot { margin-top: auto; }
.pg-card .pg-book { flex: 1; }
/* .pg-detail is an <a>, so it needs the button's own line-height reset */
a.ev-detail { text-decoration: none; text-align: center; }

/* ---- condensed course card: cover + actions only ----
   The cover infographic already carries the title, duration and level, so the
   body holds nothing but the three buttons. Everything else is in the dialog. */
.course-card--ev .course-card__body { padding: .8rem; }
.course-card--ev .ev-card__foot { margin-top: 0; }

/* ============================================================
   COURSE SUB-NAV — the filter as one sticky strip
   Used by landing-tesa.html. Keeps the .ev-filter class so the generated
   filter CSS (`:checked ~ .ev-filter .ev-chip--…`) keeps matching.
   ============================================================ */
.ev-filter--subnav {
  position: sticky; top: 64px; z-index: 30;
  /* The count sits on its own line: inline it left only ~868px for the chips,
     which is 110px short of the three groups, so the strip scrolled even on a
     1280 desktop. Wrapped, the chips get the full width and fit. */
  display: flex; flex-wrap: wrap; align-items: center; gap: .1rem .8rem;
  margin: 1.4rem 0 .2rem; padding: .55rem .9rem .45rem;
  border-radius: 12px;
  /* opaque, or the cards scroll through it */
  background: #fff; border: 1px solid var(--prog-line);
  box-shadow: 0 6px 18px rgba(10,22,40,.08);
}
/* the three dimensions share one horizontally scrollable line */
.ev-filter--subnav .ev-filter__scroll {
  display: flex; align-items: center; gap: .55rem;
  overflow-x: auto; overflow-y: hidden; flex: 1; min-width: 0;
  scrollbar-width: thin; padding-bottom: 2px;
}
.ev-filter--subnav .ev-filter__grp { display: flex; align-items: center; gap: .35rem; flex: none; }
.ev-filter--subnav .ev-filter__lbl {
  flex: none; margin-right: .15rem;
  font-size: .68rem; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase; color: var(--prog-muted); white-space: nowrap;
}
.ev-filter--subnav .ev-filter__sep {
  flex: none; width: 1px; align-self: stretch; margin: .1rem .35rem;
  background: var(--prog-line);
}
.ev-filter--subnav .ev-chip { white-space: nowrap; padding: .3rem .7rem; font-size: .82rem; }
.ev-filter--subnav .ev-filter__scroll { flex-basis: 100%; }
.ev-filter--subnav .ev-filter__count {
  flex-basis: 100%; display: block; margin: 0; padding: 0; border: none;
  text-align: right; font-size: .78rem; font-weight: 700;
  color: var(--prog-muted); white-space: nowrap;
}
@media print {
  .ev-filter--subnav { position: static; box-shadow: none; }
}

/* ============================================================
   COURSE CARDS — 3-up gallery layout
   Cover with a level tag over it, title, meta, then one action row.
   ============================================================ */
.ev-grp .course-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 310px), 1fr));
  gap: 1.3rem;
}
.ev-cover { position: relative; }
.ev-cover__tag {
  position: absolute; top: .6rem; left: .6rem;
  background: rgba(255,255,255,.94); color: var(--prog-ink);
  font-family: var(--ev-mono); font-size: .72rem; font-weight: 800; letter-spacing: .04em;
  padding: .25rem .6rem; border-radius: 999px;
  box-shadow: 0 2px 8px rgba(10,22,40,.18);
}
.course-card--ev .course-card__body { padding: .95rem 1rem 1rem; gap: .4rem; }
.course-card--ev h3 {
  font-size: 1rem; font-weight: 700; line-height: 1.35; color: var(--prog-ink); margin: 0;
  /* two lines max, so every card in a row lines up */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; min-height: 2.7em;
}
.course-card--ev .ev-card__meta {
  font-size: .78rem; color: var(--prog-muted); display: flex; flex-wrap: wrap; gap: .3rem;
}
.course-card--ev .ev-card__meta code {
  font-family: var(--ev-mono); font-weight: 700; color: var(--prog-accent);
}
.course-card--ev .ev-card__foot {
  margin-top: .5rem; padding-top: .7rem; border-top: 1px solid var(--prog-line);
  gap: .4rem;
}
.course-card--ev .ev-book { flex: none; padding: .38rem .8rem; font-size: .8rem; }
.course-card--ev .ev-detail { padding: .34rem .65rem; font-size: .78rem; }
.course-card--ev .course-card__share { padding: .3rem .55rem; font-size: .76rem; }

/* The filter strip reads as a centred pill bar.
   `safe center` matters: with plain `center` on an overflowing scroll container
   the leftmost chips are pushed to a negative offset that scrolling cannot
   reach. The flex-start line before it is the fallback for engines without
   `safe`, which stay left-aligned and fully scrollable. */
.ev-filter--subnav .ev-filter__scroll { justify-content: flex-start; }
.ev-filter--subnav .ev-filter__scroll { justify-content: safe center; }
.ev-filter--subnav .ev-filter__count { text-align: center; }

/* ============================================================
   COURSE CARDS — 2-up, inset cover, separated action bar
   (supersedes the 3-up rules above)
   ============================================================ */
.ev-grp .course-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 400px), 1fr));
  gap: 1.4rem;
}
.course-card--ev { display: flex; flex-direction: column; }

/* cover floats inside the card instead of running edge to edge */
.course-card--ev .ev-cover {
  aspect-ratio: auto; padding: .75rem .75rem 0;
  background: transparent; border-bottom: none; overflow: visible;
}
.course-card--ev .ev-cover img {
  aspect-ratio: 16 / 9; width: 100%; height: auto;
  object-fit: cover; border-radius: 10px;
}

.course-card--ev .course-card__body { padding: .9rem 1rem .2rem; gap: .45rem; flex: 1; }
.ev-card__tags { display: flex; flex-wrap: wrap; gap: .3rem; }
.ev-card__tags .badge { font-size: .66rem; padding: .2rem .5rem; }
.course-card--ev h3 {
  font-size: 1.05rem; font-weight: 700; line-height: 1.35; color: var(--prog-ink); margin: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.course-card--ev .ev-card__th {
  font-size: .86rem; line-height: 1.55; color: var(--prog-muted); margin: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  min-height: 2.7em;
}
/* meta splits left / right like the reference's duration + lectures row */
.course-card--ev .ev-card__meta {
  display: flex; justify-content: space-between; align-items: center; gap: .6rem;
  margin-top: auto; padding-top: .7rem;
  font-size: .78rem; color: var(--prog-muted);
}
.course-card--ev .ev-card__meta code {
  font-family: var(--ev-mono); font-weight: 700; color: var(--prog-accent);
}

/* action bar: primary left, secondary actions right */
.course-card--ev .ev-card__foot {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  margin: 0; padding: .75rem 1rem; border-top: 1px solid var(--prog-line);
  background: #FBFCFE; border-radius: 0 0 16px 16px;
}
.ev-card__actions { display: flex; align-items: center; gap: .4rem; }
.course-card--ev .ev-book { flex: none; padding: .42rem .9rem; font-size: .82rem; }
.course-card--ev .ev-detail { padding: .38rem .7rem; font-size: .8rem; }
.course-card--ev .course-card__share { padding: .35rem .6rem; font-size: .82rem; line-height: 1; }

/* ============================================================
   COURSE PAGER — the four layers as pages
   Driven by the same evg-* radios as the sub-nav, so the two controls can
   never disagree. Prev/next exist once per state because CSS has no notion
   of "the next radio"; only the pair for the checked state is displayed.
   ============================================================ */
.ev-pager {
  display: flex; align-items: center; justify-content: center; gap: .8rem;
  margin-top: 2.4rem; padding-top: 1.6rem; border-top: 1px solid var(--prog-line);
  flex-wrap: wrap;
}
.ev-pager__side { display: flex; align-items: center; }
.ev-pager__nums { display: flex; align-items: center; gap: .4rem; }

.ev-pager__btn {
  display: none; align-items: center; gap: .4rem;
  border: 1.5px solid var(--prog-line); border-radius: 999px;
  padding: .5rem 1.1rem; font-size: .85rem; font-weight: 600;
  color: var(--prog-ink); background: #fff; cursor: pointer; white-space: nowrap;
  transition: border-color .15s, color .15s;
}
.ev-pager__btn:hover { border-color: var(--prog-accent); color: var(--prog-accent); }
.ev-pager__btn.is-off { color: #B6BFCA; border-color: var(--prog-line); cursor: default; }
.ev-pager__btn.is-off:hover { border-color: var(--prog-line); color: #B6BFCA; }

.ev-pager__num {
  display: grid; place-items: center; min-width: 38px; height: 38px;
  padding: 0 .7rem; border: 1.5px solid var(--prog-line); border-radius: 999px;
  font-size: .85rem; font-weight: 700; color: var(--prog-ink);
  background: #fff; cursor: pointer; user-select: none;
  transition: background .15s, border-color .15s, color .15s;
}
.ev-pager__num:hover { border-color: var(--prog-accent); color: var(--prog-accent); }

/* current page */
#evg-all:checked ~ #coursesPager .ev-pg-num--all,
#evg-1:checked   ~ #coursesPager .ev-pg-num--1,
#evg-2:checked   ~ #coursesPager .ev-pg-num--2,
#evg-3:checked   ~ #coursesPager .ev-pg-num--3,
#evg-4:checked   ~ #coursesPager .ev-pg-num--4 {
  background: var(--prog-ink); border-color: var(--prog-ink); color: #fff;
}

/* only the current state's prev/next pair is shown */
#evg-all:checked ~ #coursesPager .ev-pg-prev--all,
#evg-all:checked ~ #coursesPager .ev-pg-next--all,
#evg-1:checked   ~ #coursesPager .ev-pg-prev--1,
#evg-1:checked   ~ #coursesPager .ev-pg-next--1,
#evg-2:checked   ~ #coursesPager .ev-pg-prev--2,
#evg-2:checked   ~ #coursesPager .ev-pg-next--2,
#evg-3:checked   ~ #coursesPager .ev-pg-prev--3,
#evg-3:checked   ~ #coursesPager .ev-pg-next--3,
#evg-4:checked   ~ #coursesPager .ev-pg-prev--4,
#evg-4:checked   ~ #coursesPager .ev-pg-next--4 { display: inline-flex; }

@media (max-width: 560px) {
  .ev-pager { gap: .5rem; }
  .ev-pager__btn { padding: .45rem .8rem; font-size: .8rem; }
  .ev-pager__num { min-width: 34px; height: 34px; }
}

/* ============================================================
   DETAIL POPUP — landscape: content left, cover art right
   (supersedes the stacked cover layout above)
   ============================================================ */
.ev-dialog--detail { width: min(940px, calc(100vw - 2rem)); max-height: min(88vh, 780px); }
.ev-detail__grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .82fr);
  flex: 1; min-height: 0;   /* lets the left column scroll instead of the dialog */
}
.ev-dialog--detail .ev-detail__scroll {
  overflow-y: auto; padding: 1.5rem 1.4rem 1.3rem 1.6rem; min-height: 0;
}
.ev-detail__art {
  display: grid; place-items: center; padding: 1.2rem 1.4rem 1.2rem .4rem;
  background: linear-gradient(160deg, var(--prog-accent-soft), #fff 70%);
}
.ev-detail__art img {
  width: 100%; height: auto; max-height: 100%;
  object-fit: contain; border-radius: 12px; display: block;
  box-shadow: 0 10px 30px rgba(10,22,40,.14);
}
/* narrower column, so the two-day schedule reads better in one column */
.ev-dialog--detail .ev-detail__days { grid-template-columns: 1fr; }
.ev-dialog--detail .ev-detail__top { margin-bottom: .6rem; }
.ev-dialog--detail h3 { font-size: 1.35rem; }
.ev-dialog--detail .ev-card__th { font-size: .95rem; margin-bottom: .6rem; }
.ev-dialog--detail .course-card__meta {
  display: flex; justify-content: space-between; gap: .8rem;
  padding-top: .7rem; border-top: 1px solid var(--prog-line);
}

/* action bar: code left, actions right — like the card's footer */
.ev-dialog--detail .ev-dialog__foot { justify-content: space-between; }
.ev-detail__code {
  font-family: var(--ev-mono); font-size: .85rem; font-weight: 700; color: var(--prog-accent);
}
.ev-detail__acts { display: flex; align-items: center; gap: .6rem; }
.ev-dialog--detail .ev-dialog__cancel { margin-left: 0; }
/* close button sits over the art panel */
.ev-dialog--detail .ev-dialog__x button { background: rgba(255,255,255,.92); }

@media (max-width: 720px) {
  /* stack: art first, then the content column */
  .ev-detail__grid { grid-template-columns: 1fr; }
  .ev-detail__art { order: -1; padding: 1rem 1rem .2rem; background: none; }
  .ev-detail__art img { max-height: 30vh; }
  .ev-dialog--detail .ev-detail__scroll { padding: 1.1rem 1.2rem 1.2rem; }
}

/* ============================================================
   PROGRAMME POPUP — same landscape shape as the course popup
   (supersedes the stacked .pg-dialog__scroll layout)
   ============================================================ */
.pg-dialog { width: min(940px, calc(100vw - 2rem)); max-height: min(88vh, 780px); }
.pg-dialog__grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .82fr);
  flex: 1; min-height: 0;
}
.pg-dialog .pg-dlg__main {
  overflow-y: auto; min-height: 0;
  padding: 1.5rem 1.4rem 1.3rem 1.6rem; gap: .35rem;
}
.pg-dialog .pg-dlg__cover {
  height: auto; border-radius: 0; border-bottom: none;
  padding: 1.2rem 1.4rem 1.2rem .4rem;
  background: linear-gradient(160deg, var(--prog-accent-soft), #fff 70%);
  align-self: stretch;
}
.pg-dialog .pg-dlg__cover img {
  width: 100%; height: auto; max-height: 100%;
  object-fit: contain; border-radius: 12px;
  box-shadow: 0 10px 30px rgba(10,22,40,.14);
}
.pg-dialog .pg-facts {
  display: flex; flex-wrap: wrap; gap: .35rem .9rem;
  padding-top: .7rem; border-top: 1px solid var(--prog-line);
}
.pg-dialog .ev-dialog__foot { justify-content: space-between; }
.pg-dialog .ev-dialog__cancel { margin-left: 0; }
.pg-dialog .ev-dialog__x button { background: rgba(255,255,255,.92); }

@media (max-width: 720px) {
  .pg-dialog__grid { grid-template-columns: 1fr; }
  .pg-dialog .pg-dlg__cover { order: -1; padding: 1rem 1rem .2rem; background: none; }
  .pg-dialog .pg-dlg__cover img { max-height: 30vh; }
  .pg-dialog .pg-dlg__main { padding: 1.1rem 1.2rem 1.2rem; }
}

/* Art panels: cap the image with viewport units, not `max-height: 100%`.
   The panel's height comes from its grid row, so a percentage max-height does
   not resolve and behaves as `none` — which let the tall 862×1825 poster
   overflow. vh always resolves, and the dialog itself is capped at 88vh. */
.ev-detail__art img,
.pg-dialog .pg-dlg__cover img { max-height: min(54vh, 470px); }
@media (max-width: 720px) {
  .ev-detail__art img,
  .pg-dialog .pg-dlg__cover img { max-height: 30vh; }
}
