/* DESIGN.md, implemented. Tokens first, then .kg-* components.
   Light mode only: no prefers-color-scheme: dark block belongs in this file. */

:root {
  color-scheme: light;

  --kg-bg: #ffffff;
  --kg-card: #f7f7f4;
  --kg-ink: #232020;
  --kg-muted: #6e6a66;
  --kg-line: #ece7df;
  /* Marigold is the primary accent (Toni, 2026-08-16). Its fills carry ink at
     9.0:1; white on marigold is 1.8:1 and unreadable. Where the accent is the
     mark itself on white — the wordmark, the saved heart — marigold is 1.8:1
     too, so those take `--kg-primary-strong`, the darker marigold already in the
     palette as the warning token, at 2.6:1. */
  --kg-primary: #f4b740;
  --kg-primary-ink: #232020;
  --kg-primary-strong: #e0902e;

  --kg-success: #3fa66a;
  --kg-warning: #e0902e;
  --kg-error: #d9534f;
  --kg-info: #4c9be0;

  /* Default accent pair; every card and chip overrides these inline. */
  --kg-accent: #f76c5e;
  --kg-accent-soft: #fde7e3;

  /* Marigold's accent-soft fill from DESIGN.md § Color, as a token because the
     landing picker's panel is painted with it and no card owns it. */
  --kg-soft-marigold: #fcf1d8;

  /* 8px scale with 4px half-steps. */
  --kg-2xs: 4px;
  --kg-xs: 8px;
  --kg-sm: 12px;
  --kg-md: 16px;
  --kg-lg: 24px;
  --kg-xl: 32px;
  --kg-2xl: 48px;
  --kg-3xl: 64px;

  --kg-radius-sm: 8px;
  --kg-radius-md: 14px;
  --kg-radius-lg: 20px;
  --kg-radius-full: 9999px;

  --kg-text-xs: 0.8rem;
  --kg-text-sm: 0.875rem;
  --kg-text-base: 1rem;
  --kg-text-lg: 1.125rem;
  --kg-text-xl: 1.25rem;
  --kg-text-2xl: 1.5rem;
  --kg-text-3xl: 1.875rem;

  --kg-display-font: "Cabinet Grotesk", "DM Sans", sans-serif;
  --kg-body-font: "DM Sans", sans-serif;

  --kg-tap: 44px;
  --kg-ease-out: cubic-bezier(0.2, 0.8, 0.3, 1);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--kg-bg);
  color: var(--kg-ink);
  font-family: var(--kg-body-font);
  font-size: var(--kg-text-base);
  line-height: 1.55;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
}

:focus-visible {
  outline: 3px solid var(--kg-info);
  outline-offset: 2px;
  border-radius: var(--kg-radius-sm);
}

/* ── Layout ─────────────────────────────────────────────────────────────── */

.kg-frame {
  width: 100%;
  max-width: 480px;
  margin: 0 auto;
  padding: 0 var(--kg-md) var(--kg-3xl);
  background: var(--kg-bg);
}

@media (min-width: 600px) {
  body {
    /* The tinted page gutter, so the column reads as an app and not a strip. */
    background: #faf8f5;
  }

  .kg-frame {
    max-width: 760px;
    margin: var(--kg-lg) auto;
    padding: 0 var(--kg-xl) var(--kg-3xl);
    border: 1px solid var(--kg-line);
    border-radius: var(--kg-radius-lg);
    box-shadow: 0 1px 2px rgba(35, 32, 32, 0.04);
  }
}

/* Every page gets the same air under the header. The hero used to carry it and
   the pages with no hero — the results list, favourites — started against the
   rule; the hero's own top padding drops by the same amount, so the landing is
   where it was. */
.kg-main {
  display: block;
  padding-top: var(--kg-lg);
}

/* The three layout wrappers are inert until the desktop tier: `display: contents`
   means the phone and the framed tablet column lay out exactly as they did
   before the wrappers existed, and only the ≥960px block below gives them a box.
   `.kg-narrow` is the exception — a form column is centred from the tablet tier. */
.kg-landing,
.kg-layout,
.kg-sidebar,
.kg-detail-main,
.kg-detail-rail {
  display: contents;
}

.kg-narrow {
  display: contents;
}

/* ── Header and footer ──────────────────────────────────────────────────── */

.kg-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kg-sm);
  padding: var(--kg-md) 0;
  border-bottom: 1px solid var(--kg-line);
  flex-wrap: wrap;
}

.kg-brand {
  display: flex;
  align-items: baseline;
  gap: var(--kg-xs);
  flex-wrap: wrap;
}

.kg-tagline {
  margin: 0;
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
}

/* Beside the wordmark where there is room; under it on a phone, where the two
   side by side fill the row and push the nav onto a line of its own. */
@media (max-width: 599px) {
  .kg-brand {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--kg-2xs);
  }

  .kg-tagline {
    font-size: var(--kg-text-xs);
  }
}

.kg-wordmark {
  font-family: var(--kg-display-font);
  font-weight: 800;
  font-size: var(--kg-text-xl);
  text-decoration: none;
  letter-spacing: -0.02em;
}

/* a·som·brar·se·.com — leaf, teal, grape, coral, then marigold last (Toni,
   2026-08-17). Category accents from DESIGN.md § Color; marigold is the darker
   `--kg-primary-strong` because the mark sits on white (see the token note). */
.kg-wordmark-1 { color: #5bb98c; }
.kg-wordmark-2 { color: #3fb6c2; }
.kg-wordmark-3 { color: #9b6dd6; }
.kg-wordmark-4 { color: #f76c5e; }
.kg-wordmark-5 { color: var(--kg-primary-strong); }

.kg-nav {
  display: flex;
  align-items: center;
  gap: var(--kg-xs);
}

.kg-nav-link {
  display: inline-flex;
  align-items: center;
  min-height: var(--kg-tap);
  padding: 0 var(--kg-sm);
  border-radius: var(--kg-radius-md);
  font-size: var(--kg-text-base);
  font-weight: 500;
  text-decoration: none;
  color: var(--kg-ink);
}

.kg-nav-link:hover {
  background: var(--kg-card);
}

.kg-nav-button {
  border: 0;
  background: transparent;
  font-family: inherit;
  cursor: pointer;
}

.kg-nav-email {
  max-width: 12ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
}

.kg-inline-form {
  margin: 0;
}

.kg-footer {
  margin-top: var(--kg-2xl);
  padding-top: var(--kg-md);
  border-top: 1px solid var(--kg-line);
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
}

.kg-footer p {
  margin: 0 0 var(--kg-xs);
}

.kg-footer-link {
  text-decoration: underline;
}

/* ── Hero ───────────────────────────────────────────────────────────────── */

.kg-hero {
  padding: var(--kg-lg) 0 var(--kg-lg);
}

.kg-hero-compact {
  padding: var(--kg-xl) 0 var(--kg-md);
}

.kg-display {
  margin: 0 0 var(--kg-sm);
  font-family: var(--kg-display-font);
  font-weight: 800;
  font-size: clamp(2.25rem, 8vw, 3.75rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
}

/* One word of the landing headline sits on a marigold band, drawn as a gradient
   stop rather than a border so it hugs the text at every clamp size. The band is
   behind the word, not around it: the ink stays ink and the 9:1 it has on
   marigold is the same it has on white. */
.kg-display-mark {
  background: linear-gradient(
    transparent 56%,
    var(--kg-primary) 56%,
    var(--kg-primary) 81%,
    transparent 81%
  );
  padding: 0 0.08em;
  /* The marked phrase holds one line: a band split across a wrap draws twice,
     and the two fragments do not line up under a display line-height below 1. */
  white-space: nowrap;
}


/* The lede is muted; what it emphasises goes to ink, not to a heavier muted. */
.kg-lede strong {
  font-weight: 600;
  color: var(--kg-ink);
}

.kg-lede {
  margin: 0;
  font-size: var(--kg-text-lg);
  color: var(--kg-muted);
  max-width: 46ch;
}

.kg-section-title {
  margin: 0 0 var(--kg-sm);
  font-family: var(--kg-display-font);
  font-weight: 700;
  font-size: var(--kg-text-2xl);
  letter-spacing: -0.02em;
}

.kg-muted {
  color: var(--kg-muted);
}

/* ── City ───────────────────────────────────────────────────────────────── */

.kg-city {
  padding: var(--kg-sm) 0 0;
}

/* The label sits on its own line above the select, and carries
   `.kg-section-title`, so «Ciudad» reads exactly like «Edad» in both places the
   two appear together: the landing panel and the sidebar. */
.kg-city-field {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  margin: 0;
  font-size: var(--kg-text-sm);
}

.kg-select {
  min-height: var(--kg-tap);
  padding: 0 var(--kg-sm);
  border: 1px solid var(--kg-line);
  border-radius: var(--kg-radius-md);
  background: #ffffff;
  color: var(--kg-ink);
  font-family: var(--kg-body-font);
  font-size: var(--kg-text-base);
}

.kg-select:focus-visible {
  outline: 3px solid var(--kg-info);
  outline-offset: 2px;
}

/* The count and the order, on one line above the grid. They wrap to two lines
   on a narrow phone rather than squeezing the select under 44px. */
.kg-results-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--kg-sm);
  margin-bottom: var(--kg-md);
}

.kg-results-head .kg-section-title {
  margin: 0;
}

.kg-sort {
  display: flex;
  align-items: center;
  gap: var(--kg-xs);
}

.kg-sort-label {
  font-size: var(--kg-text-sm);
  color: var(--kg-muted);
}

/* Hidden once kg.js submits on change; visible whenever it does not run, which
   is the only way a no-JavaScript reader can apply the order at all. */
.kg-sort-go[hidden] {
  display: none;
}

.kg-city-form {
  display: flex;
  align-items: flex-end;
  gap: var(--kg-xs);
  flex-wrap: wrap;
}

/* ── Age selector ───────────────────────────────────────────────────────── */

.kg-age {
  padding: var(--kg-md) 0 var(--kg-lg);
}

.kg-age-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--kg-xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

.kg-age-option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--kg-tap);
  min-height: var(--kg-tap);
  padding: 0 var(--kg-sm);
  border: 1px solid var(--kg-line);
  border-radius: var(--kg-radius-md);
  background: var(--kg-card);
  font-size: var(--kg-text-lg);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  transition: transform 200ms var(--kg-ease-out), background 150ms var(--kg-ease-out);
}

.kg-age-option:active {
  transform: scale(0.96);
}

.kg-age-option.is-selected {
  background: var(--kg-primary);
  border-color: var(--kg-primary);
  color: var(--kg-primary-ink);
}

/* The landing picker is one panel on soft marigold — the accent's own tint in
   place of the neutral card grey — holding the city above the keypad, separated
   by a rule: two choices in one block, read top to bottom. The cells go white on
   it, so the keypad reads as a control on a coloured ground and not as a grid of
   tinted buttons. Unlike the other layout wrappers this one is a box at every
   width; the desktop block only widens its padding. */
.kg-landing-picker {
  display: grid;
  gap: var(--kg-md);
  padding: var(--kg-md);
  background: var(--kg-soft-marigold);
  border-radius: var(--kg-radius-lg);
}

.kg-landing-picker .kg-city {
  padding: 0 0 var(--kg-md);
  border-bottom: 1px solid var(--kg-line);
}

.kg-landing-picker .kg-city-form {
  padding-bottom: var(--kg-md);
  border-bottom: 1px solid var(--kg-line);
}

.kg-landing-picker .kg-city-form .kg-city {
  padding: 0;
  border-bottom: 0;
}

.kg-landing-picker .kg-age {
  padding: 0;
}

/* A grid, not a wrapping row: fourteen ages in seven equal columns read as a
   keypad — two rows of seven, 0–6 above 7–13 — where flex-wrap gives six to a
   row on a phone and leaves the last two hanging under a ragged edge. The cell
   takes its width from the column, so `min-width` has to go: the 44px tap target
   is held by `min-height` and by the panel going full-bleed below 600px, which
   is what buys seven columns their width on a 375px screen. */
.kg-landing-picker .kg-age-list {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--kg-2xs);
}

.kg-landing-picker .kg-age-option {
  width: 100%;
  min-width: 0;
}

@media (max-width: 599px) {
  .kg-landing-picker {
    margin-inline: calc(-1 * var(--kg-md));
    padding: var(--kg-md) var(--kg-sm);
    border-radius: 0;
  }
}

.kg-landing .kg-age-option:not(.is-selected) {
  background: var(--kg-bg);
  border-color: transparent;
}

/* ── The chosen age and city, collapsed ─────────────────────────────────── */

/* Past the landing these two are answered, so they sit closed as one line that
   states the answer and opens on click. The marker is our own chevron: the
   native triangle is a different shape in every browser. */
.kg-chosen {
  border: 1px solid var(--kg-line);
  border-radius: var(--kg-radius-md);
  background: var(--kg-card);
}

.kg-chosen-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--kg-sm);
  min-height: var(--kg-tap);
  padding: 0 var(--kg-sm);
  cursor: pointer;
  list-style: none;
  font-weight: 600;
}

.kg-chosen-summary::-webkit-details-marker {
  display: none;
}

.kg-chosen-action {
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
  font-weight: 500;
}

.kg-chosen-action::after {
  content: " ▾";
}

.kg-chosen[open] .kg-chosen-action::after {
  content: " ▴";
}

.kg-chosen-body {
  display: grid;
  gap: var(--kg-sm);
  padding: 0 var(--kg-sm) var(--kg-sm);
}

.kg-chosen-body .kg-age {
  padding: 0;
}

.kg-chosen-body .kg-city {
  padding: 0;
}

/* ── Filters ────────────────────────────────────────────────────────────── */

/* A summary line is one nowrap row, and a grid item's automatic minimum is its
   content — so without these the sidebar grows past its 280px track and slides
   under the results. The value is what gives way, by ellipsis. */
.kg-sidebar,
.kg-filters,
.kg-filter-details,
.kg-filter-summary {
  min-width: 0;
}

/* A collapsed group's summary reads exactly like the legend it stands in for,
   so the closed sidebar is a list of the same words the open one shows. */
.kg-filter-summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--kg-tap);
  padding: var(--kg-xs) 0;
  cursor: pointer;
  list-style: none;
  flex-wrap: wrap;
  gap: var(--kg-2xs) var(--kg-xs);
}

.kg-filter-summary-label {
  font-size: var(--kg-text-sm);
  font-weight: 600;
  color: var(--kg-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  flex: none;
}

/* What the closed group holds, on its own line under the label and in full:
   the choice is the thing the reader came back for, so it is the bold half of
   the row and it wraps rather than being cut. It goes when the group opens —
   the controls themselves say it better than a summary of them can. */
.kg-filter-summary-value {
  order: 1;
  flex: 1 0 100%;
  font-size: var(--kg-text-base);
  font-weight: 600;
  color: var(--kg-ink);
}

.kg-filter-details[open] > .kg-filter-summary .kg-filter-summary-value {
  display: none;
}

.kg-filter-summary::-webkit-details-marker {
  display: none;
}

/* The chevron stays on the label's line, hard right, and the value wraps under
   both — hence `order` rather than source order. */
.kg-filter-summary::after {
  content: "▾";
  order: 0;
  margin-left: auto;
  letter-spacing: 0;
  color: var(--kg-muted);
}

.kg-filter-details[open] > .kg-filter-summary::after {
  content: "▴";
}

.kg-filter-details + .kg-filter-details {
  border-top: 1px solid var(--kg-line);
}


/* The gaps are the grid's, not the fieldsets'. A margin on the fieldset plus a
   :last-of-type reset gets it wrong here: the Categorías fieldset is the form's
   only fieldset child, so it matched the reset and its legend collided with the
   row above. */
.kg-filters {
  display: grid;
  gap: var(--kg-lg);
  padding: var(--kg-md);
  margin-bottom: var(--kg-lg);
  background: var(--kg-card);
  border-radius: var(--kg-radius-lg);
}

/* The form reads as four groups under the age panel — where, when, what,
   everything else — separated by hairlines, in that order, with no group
   titles of their own (Toni, 2026-08-15). */
.kg-filter-group {
  display: grid;
  gap: var(--kg-lg);
}

.kg-filters > .kg-filter-group + .kg-filter-group {
  border-top: 1px solid var(--kg-line);
  padding-top: var(--kg-lg);
}

.kg-fieldset {
  border: 0;
  margin: 0;
  padding: 0;
}

.kg-legend {
  padding: 0 0 var(--kg-xs);
  font-size: var(--kg-text-sm);
  font-weight: 600;
  color: var(--kg-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.kg-filter-grid {
  display: grid;
  gap: var(--kg-lg);
}

@media (min-width: 600px) {
  .kg-filter-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.kg-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--kg-xs);
}

.kg-filter-chip {
  display: inline-flex;
  align-items: center;
  min-height: var(--kg-tap);
  padding: 0 var(--kg-md);
  border: 1px solid var(--kg-line);
  border-radius: var(--kg-radius-full);
  background: #ffffff;
  font-size: var(--kg-text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: transform 200ms var(--kg-ease-out);
}

.kg-filter-chip:active {
  transform: scale(0.97);
}

.kg-filter-chip input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.kg-filter-chip:has(input:checked) {
  background: var(--kg-accent-soft);
  border-color: var(--kg-accent);
  color: var(--kg-ink);
}

.kg-filter-chip-plain:has(input:checked) {
  background: var(--kg-primary);
  border-color: var(--kg-primary);
  color: var(--kg-primary-ink);
}

.kg-filter-chip:has(input:focus-visible) {
  outline: 3px solid var(--kg-info);
  outline-offset: 2px;
}

/* Seven chips on the 44px target need 344px and the sidebar is 280px wide, so
   they are laid out four and three rather than left to wrap five and two. The
   letter is decorative; the accessible name is the full day, on the input. */
.kg-chip-row-days {
  display: grid;
  grid-template-columns: repeat(4, minmax(var(--kg-tap), 1fr));
  gap: 6px;
}

.kg-filter-chip-day {
  justify-content: center;
  padding: 0;
}

/* ── The date window ────────────────────────────────────────────────────── */

/* `auto-fit` and not two fixed columns: a native date input needs about 150px
   for its text and its picker button, and half of the 280px sidebar is less
   than that — the calendar icon was being clipped off the first field. Where
   two do not fit, they stack. */
.kg-date-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--kg-xs);
}

.kg-date-field {
  display: grid;
  gap: 4px;
  font-size: var(--kg-text-sm);
}

.kg-date-label {
  color: var(--kg-muted);
  font-weight: 500;
}

.kg-date-field input {
  width: 100%;
  min-height: var(--kg-tap);
  padding: 0 var(--kg-sm);
  border: 1px solid var(--kg-line);
  border-radius: var(--kg-radius-md);
  background: #ffffff;
  color: var(--kg-ink);
  font-family: var(--kg-body-font);
  font-size: var(--kg-text-sm);
}

.kg-date-field input:focus-visible {
  outline: 3px solid var(--kg-info);
  outline-offset: 2px;
}

.kg-field-hint,
.kg-field-note {
  margin: var(--kg-xs) 0 0;
  font-size: var(--kg-text-sm);
  color: var(--kg-muted);
}

.kg-field-note {
  color: var(--kg-ink);
}

.kg-filter-actions {
  display: flex;
  gap: var(--kg-xs);
  align-items: center;
  flex-wrap: wrap;
}

/* ── Buttons ────────────────────────────────────────────────────────────── */

.kg-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--kg-tap);
  padding: 0 var(--kg-lg);
  border: 1px solid transparent;
  border-radius: var(--kg-radius-md);
  font-family: inherit;
  font-size: var(--kg-text-base);
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: transform 200ms var(--kg-ease-out), background 150ms var(--kg-ease-out);
}

.kg-button:active {
  transform: scale(0.97);
}

.kg-button-primary {
  background: var(--kg-primary);
  color: var(--kg-primary-ink);
}

.kg-button-ghost {
  background: transparent;
  border-color: var(--kg-line);
  color: var(--kg-ink);
}

.kg-button-block {
  width: 100%;
}

/* ── Cards ──────────────────────────────────────────────────────────────── */

.kg-results {
  padding-top: var(--kg-xs);
}

.kg-card-list {
  display: grid;
  gap: var(--kg-md);
}

@media (min-width: 600px) {
  .kg-card-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.kg-card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--kg-card);
  border-left: 4px solid var(--kg-accent);
  border-radius: var(--kg-radius-md);
  overflow: hidden;
  transition: transform 200ms var(--kg-ease-out);
}

.kg-card:has(.kg-card-link:hover) {
  transform: translateY(-2px);
}

/* flex/min-height: a flex item's automatic minimum size is its content's, and
   the photo's own height wins over aspect-ratio unless both are pinned — which
   is why cards in one row showed images of three different heights. */
.kg-card-media {
  flex: none;
  min-height: 0;
  aspect-ratio: 16 / 9;
  background: var(--kg-accent-soft);
}

.kg-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.kg-card-gradient {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, var(--kg-accent-soft), var(--kg-accent));
}

.kg-card-body {
  padding: var(--kg-md);
  display: flex;
  flex-direction: column;
  gap: var(--kg-xs);
}

.kg-card-title {
  margin: 0;
  font-family: var(--kg-display-font);
  font-weight: 700;
  font-size: var(--kg-text-xl);
  line-height: 1.15;
  letter-spacing: -0.01em;
}

/* The stretched link: the whole card is the target, and the heart sits above
   it — a <form> inside an <a> is not valid HTML. */
.kg-card-link {
  text-decoration: none;
}

.kg-card-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.kg-card-meta {
  margin: 0;
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
}

.kg-card-description {
  margin: 0;
  color: var(--kg-ink);
  font-size: var(--kg-text-base);
  /* Clamped for layout only. The text itself is the row's own, uncut. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  line-clamp: 3;
  overflow: hidden;
}

/* ── Chips ──────────────────────────────────────────────────────────────── */

.kg-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--kg-2xs);
}

.kg-chip {
  display: inline-flex;
  align-items: center;
  padding: var(--kg-2xs) var(--kg-sm);
  border-radius: var(--kg-radius-full);
  background: #ffffff;
  border: 1px solid var(--kg-line);
  font-size: var(--kg-text-xs);
  font-weight: 600;
  white-space: nowrap;
}

.kg-chip-category {
  background: var(--kg-accent-soft);
  border-color: transparent;
}

/* Ink, not white: white on the success green is 3.0:1, and ink is 5.2:1. This
   is the same ink/white choice `factory.social.template.on_accent` measures for
   the Gratis pill on a slide. */
.kg-chip-free {
  background: var(--kg-success);
  border-color: transparent;
  color: var(--kg-ink);
}

.kg-chip-unknown {
  color: var(--kg-muted);
  background: transparent;
}

/* ── Favourite heart ────────────────────────────────────────────────────── */

.kg-fav-form {
  position: absolute;
  top: var(--kg-xs);
  right: var(--kg-xs);
  z-index: 2;
  margin: 0;
}

.kg-fav-form-inline {
  position: static;
  z-index: auto;
}

.kg-fav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--kg-xs);
  min-width: var(--kg-tap);
  min-height: var(--kg-tap);
  padding: 0 var(--kg-sm);
  border: 1px solid var(--kg-line);
  border-radius: var(--kg-radius-full);
  background: rgba(255, 255, 255, 0.92);
  color: var(--kg-muted);
  font-family: inherit;
  font-size: var(--kg-text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: transform 200ms var(--kg-ease-out);
}

.kg-fav:active {
  transform: scale(0.92);
}

.kg-fav svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
}

/* The heart goes marigold; the word next to it stays ink, because accent text at
   14px on white is ruled out by name in DESIGN.md § Color. The heart takes the
   darker marigold: the light one is 1.8:1 on white and the icon disappears. */
.kg-fav.is-saved {
  color: var(--kg-primary-strong);
}

.kg-fav .kg-fav-label {
  color: var(--kg-ink);
}

.kg-fav.is-saved svg {
  fill: var(--kg-primary-strong);
  stroke: var(--kg-primary-strong);
}

/* ── Detail ─────────────────────────────────────────────────────────────── */

.kg-detail {
  padding-top: var(--kg-lg);
  display: flex;
  flex-direction: column;
  gap: var(--kg-md);
}

/* The detail page's blocks are grouped in the markup as they sit on desktop
   (main column, then rail). On the phone the wrappers are `display: contents`,
   so these are flex items of `.kg-detail` again and `order` puts them back into
   the reading order the page has always had: media, chips, title, barrio,
   actions, description, cuándo, dónde, source. */
.kg-detail-desc,
.kg-detail-when {
  order: 1;
}

.kg-detail-where {
  order: 2;
}

.kg-detail-source {
  order: 3;
}

.kg-back {
  color: var(--kg-muted);
  text-decoration: none;
  font-size: var(--kg-text-sm);
  min-height: var(--kg-tap);
  display: inline-flex;
  align-items: center;
}

.kg-detail-media {
  flex: none;
  min-height: 0;
  aspect-ratio: 16 / 9;
  border-radius: var(--kg-radius-lg);
  overflow: hidden;
  background: var(--kg-accent-soft);
}

.kg-detail-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.kg-detail-title {
  margin: 0;
  font-family: var(--kg-display-font);
  font-weight: 800;
  font-size: clamp(1.875rem, 6vw, 2.75rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.kg-detail-meta {
  margin: 0;
  color: var(--kg-muted);
}

.kg-detail-actions {
  display: flex;
  align-items: center;
  gap: var(--kg-xs);
  flex-wrap: wrap;
}

.kg-block {
  padding-top: var(--kg-xs);
}

.kg-prose {
  margin: 0 0 var(--kg-xs);
  font-size: var(--kg-text-base);
  white-space: pre-line;
}

.kg-list,
.kg-venues {
  margin: 0 0 var(--kg-xs);
  padding-left: var(--kg-md);
}

.kg-venues {
  list-style: none;
  padding-left: 0;
  display: grid;
  gap: var(--kg-xs);
}

.kg-venue {
  padding: var(--kg-sm) var(--kg-md);
  background: var(--kg-card);
  border-left: 4px solid var(--kg-accent);
  border-radius: var(--kg-radius-md);
}

.kg-venue p {
  margin: 0;
}

.kg-venue-name {
  font-weight: 600;
}

.kg-venue-address,
.kg-venue-neighborhood {
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
}

/* The card fill, so a map whose tiles never arrive is a quiet placeholder
   rather than a white hole in the page. */
.kg-map {
  height: 260px;
  background: var(--kg-card);
  margin-top: var(--kg-sm);
  border-radius: var(--kg-radius-md);
  overflow: hidden;
  border: 1px solid var(--kg-line);
}

.kg-source {
  margin: 0;
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
}

/* ── Forms ──────────────────────────────────────────────────────────────── */

.kg-form {
  display: grid;
  gap: var(--kg-md);
  max-width: 420px;
  padding: var(--kg-lg) 0;
}

.kg-field {
  display: grid;
  gap: var(--kg-2xs);
}

.kg-label {
  font-size: var(--kg-text-sm);
  font-weight: 600;
}

.kg-input {
  min-height: var(--kg-tap);
  padding: 0 var(--kg-sm);
  border: 1px solid var(--kg-line);
  border-radius: var(--kg-radius-md);
  background: #ffffff;
  font-family: inherit;
  font-size: var(--kg-text-base);
  color: var(--kg-ink);
}

.kg-hint {
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
}

/* The red is the border, not the text: #D9534F on its own soft fill is 3.4:1,
   and this line is the one a parent has to read twice. */
.kg-error {
  margin: 0;
  padding: var(--kg-sm) var(--kg-md);
  border-left: 4px solid var(--kg-error);
  border-radius: var(--kg-radius-md);
  background: #fbe9e8;
  color: var(--kg-ink);
  font-weight: 600;
}

.kg-form-foot {
  margin: 0;
  color: var(--kg-muted);
  font-size: var(--kg-text-sm);
}

/* ── Empty states ───────────────────────────────────────────────────────── */

.kg-empty {
  display: grid;
  gap: var(--kg-sm);
  justify-items: start;
  padding: var(--kg-lg);
  background: var(--kg-card);
  border-radius: var(--kg-radius-lg);
}

.kg-empty-title {
  margin: 0;
  font-family: var(--kg-display-font);
  font-weight: 700;
  font-size: var(--kg-text-xl);
}

.kg-empty-text {
  margin: 0;
  color: var(--kg-muted);
}

/* ── Tablet: the centred form column ────────────────────────────────────── */

@media (min-width: 600px) {
  .kg-narrow {
    display: block;
    max-width: 460px;
    margin: 0 auto;
  }

  /* The column is the measure now; a second max-width inside it only pushes the
     fields off its centre. */
  .kg-narrow .kg-form {
    max-width: none;
  }
}

/* ── Desktop tier (≥960px) ──────────────────────────────────────────────── */

/* No frame and no tinted gutter here: the page is the white ground, 1200px of
   content centred in it. Same tokens throughout — this block only places
   things. */
@media (min-width: 960px) {
  body {
    background: var(--kg-bg);
  }

  .kg-frame {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 var(--kg-xl) var(--kg-3xl);
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .kg-header {
    padding: var(--kg-lg) 0;
  }

  .kg-wordmark {
    font-size: var(--kg-text-2xl);
  }

  .kg-nav {
    gap: var(--kg-sm);
  }

  .kg-narrow {
    padding-bottom: var(--kg-2xl);
  }

  /* Landing: promise left, age picker right. */
  .kg-landing {
    display: grid;
    grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
    gap: var(--kg-3xl);
    align-items: center;
    padding: var(--kg-3xl) 0 var(--kg-2xl);
  }

  .kg-landing .kg-hero {
    padding: 0;
  }

  .kg-landing .kg-display {
    font-size: 3.75rem;
  }

  .kg-landing .kg-lede {
    font-size: var(--kg-text-xl);
    max-width: 30ch;
  }

  .kg-landing-picker {
    padding: var(--kg-xl);
  }

  .kg-landing-picker .kg-city-field {
    font-size: var(--kg-text-base);
  }

  .kg-landing-picker .kg-age-list {
    gap: var(--kg-sm);
  }

  .kg-landing-picker .kg-age-option {
    min-height: 56px;
    font-size: var(--kg-text-xl);
  }

  .kg-landing-picker .kg-age-option.is-selected {
    background: var(--kg-primary);
  }

  /* Results: sticky filter sidebar, cards in the remaining width. */
  .kg-layout {
    display: grid;
    grid-template-columns: 280px minmax(0, 1fr);
    gap: var(--kg-2xl);
    align-items: start;
  }

  .kg-sidebar {
    display: grid;
    gap: var(--kg-md);
    position: sticky;
    top: var(--kg-lg);
    /* Taller than the viewport, a sticky column pins at the top and its tail
       (the submit button included) becomes unreachable. A scroll box keeps
       every control reachable; overflow: auto scrolls, it does not clip. */
    max-height: calc(100vh - 2 * var(--kg-lg));
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: var(--kg-2xs);
    scrollbar-width: thin;
  }

  .kg-sidebar .kg-age {
    padding: var(--kg-md);
    background: var(--kg-card);
    border-radius: var(--kg-radius-lg);
  }

  .kg-sidebar .kg-section-title {
    font-size: var(--kg-text-sm);
    font-weight: 600;
    font-family: var(--kg-body-font);
    color: var(--kg-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }

  .kg-sidebar .kg-age-list {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--kg-xs);
  }

  .kg-sidebar .kg-age-option {
    width: 100%;
    background: var(--kg-bg);
  }

  .kg-sidebar .kg-age-option.is-selected {
    background: var(--kg-primary);
  }

  .kg-sidebar .kg-filters {
    margin-bottom: 0;
  }

  .kg-sidebar .kg-filter-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .kg-sidebar .kg-filter-actions .kg-button {
    flex: 1 1 100%;
  }

  .kg-results {
    padding-top: 0;
  }

  /* Favoritos and 404 have no grid to fill; a 1136px-wide empty box is a
     stretched one. */
  .kg-main > .kg-empty {
    max-width: 720px;
  }

  .kg-hero {
    padding: var(--kg-2xl) 0 var(--kg-lg);
  }

  /* Detail: content left, sticky rail right. */
  .kg-detail {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--kg-2xl);
    row-gap: var(--kg-md);
    align-items: start;
    grid-template-areas:
      "back back"
      "main rail";
  }

  .kg-detail > .kg-back {
    grid-area: back;
  }

  .kg-detail-main {
    grid-area: main;
    display: flex;
    flex-direction: column;
    gap: var(--kg-md);
  }

  .kg-detail-rail {
    grid-area: rail;
    display: flex;
    flex-direction: column;
    gap: var(--kg-md);
    position: sticky;
    top: var(--kg-lg);
  }

  .kg-detail-desc,
  .kg-detail-when,
  .kg-detail-where,
  .kg-detail-source {
    order: 0;
  }

  .kg-detail-title {
    font-size: 2.75rem;
  }

  /* The rail is 5/12 of 1136px; a 260px map in it is a stamp. */
  .kg-map {
    height: 420px;
  }

  .kg-detail-rail .kg-detail-actions .kg-button {
    flex: 1 1 auto;
  }
}

@media (min-width: 1200px) {
  .kg-card-list {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ── Motion ─────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }

  .kg-button:active,
  .kg-fav:active,
  .kg-age-option:active,
  .kg-filter-chip:active,
  .kg-card:has(.kg-card-link:hover) {
    transform: none;
  }
}
