/* Vendored from the GameOn design system by bin/sync-design-system. Do not edit — the next sync overwrites it. */
/*!
 * GameOn Design System v1.0.0
 * Built from src/ by build.py -- do not edit this file directly.
 *
 * Source order matters: tokens define the variables every later file reads,
 * and utilities come last so they can override component defaults.
 */

/* ==== 01-tokens.css ===================================================== */
/* ============================================================================
 * GameOn Design System — Tokens
 * ----------------------------------------------------------------------------
 * The single source of truth. Nothing below this file invents a value: every
 * size, colour, space and duration used by a component comes from here.
 *
 * THE 4px RULE
 * Every dimension that can affect vertical alignment is a multiple of 4px:
 * spacing, line-heights, control heights, icon boxes, radii. That is what makes
 * arbitrary components stack and sit next to each other without drifting.
 *
 * Layers:
 *   1. Primitives  --go-<family>-<step>   raw values, never used in components
 *   2. Semantics   --go-color-<role>      what a thing means, used everywhere
 * Re-theming means overriding layer 2 only.
 * ========================================================================== */

:root {
  /* ==========================================================================
   * 1. SPACE — the 4px grid
   * The number is the multiplier, so --go-space-4 == 4 * 4px == 16px.
   * ====================================================================== */
  --go-unit: 4px;

  --go-space-0: 0px;
  --go-space-1: 4px;
  --go-space-2: 8px;
  --go-space-3: 12px;
  --go-space-4: 16px;
  --go-space-5: 20px;
  --go-space-6: 24px;
  --go-space-7: 28px;
  --go-space-8: 32px;
  --go-space-10: 40px;
  --go-space-12: 48px;
  --go-space-14: 56px;
  --go-space-16: 64px;
  --go-space-20: 80px;
  --go-space-24: 96px;

  /* ==========================================================================
   * 2. COLOUR — primitives
   * ====================================================================== */

  /* Brand yellow, from the GameOn meeple mark (#F9C901). */
  --go-yellow-50:  #FFFBEB;
  --go-yellow-100: #FEF3C7;
  --go-yellow-200: #FDE68A;
  --go-yellow-300: #FCD84D;
  --go-yellow-400: #F9C901;   /* brand */
  --go-yellow-500: #DDB100;
  --go-yellow-600: #A98700;
  --go-yellow-700: #7A6100;

  /* Warm neutral ramp — paper, not grey. */
  --go-sand-50:  #FFFDF5;
  --go-sand-100: #FFFBEF;     /* page background */
  --go-sand-200: #F6F1E2;
  --go-sand-300: #F1ECDC;     /* soft fills, rails */
  --go-sand-400: #E2DAC4;
  --go-sand-500: #B8B09B;
  /* sand-600 is the lightest text colour in the system, so it sets the
   * accessibility floor: darkened until it clears 4.5:1 against the CANVAS
   * (#FFFBEF), which is a harder target than white. */
  --go-sand-600: #767162;     /* muted text — 4.7:1 on canvas, 4.9:1 on white */
  --go-sand-700: #4A463B;     /* secondary text */
  --go-sand-800: #2A2721;
  --go-sand-900: #17150F;     /* ink: text, borders */

  --go-white: #FFFFFF;
  --go-black: #000000;

  /* Category hues. One per content source, used for tile accents and badges.
   * -ink steps are darkened until they pass 4.5:1 on white for label text. */
  --go-teal-400:   #12B3B1;
  --go-teal-500:   #0E9594;
  --go-teal-ink:   #0A6E6D;
  --go-coral-400:  #FF7A5C;
  --go-coral-500:  #FF5C39;
  --go-coral-ink:  #B8330F;
  --go-purple-400: #8B72F0;
  --go-purple-500: #6B4EE6;
  --go-purple-ink: #4B32B8;
  --go-blue-400:   #4B82F0;
  --go-blue-500:   #2563EB;
  --go-blue-ink:   #1A47AD;
  --go-green-400:  #1CC066;
  --go-green-500:  #12A150;
  --go-green-ink:  #0B7239;
  --go-red-400:    #E5533D;
  --go-red-500:    #C4321A;
  --go-red-ink:    #9A2411;

  /* ==========================================================================
   * 3. COLOUR — semantics
   * Components reference ONLY these. Retheming = override this block.
   * ====================================================================== */
  --go-color-canvas:        var(--go-sand-100);
  --go-color-surface:       var(--go-white);
  --go-color-surface-sunk:  var(--go-sand-300);
  --go-color-surface-raised: var(--go-white);

  --go-color-ink:        var(--go-sand-900);  /* 16.1:1 on surface */
  --go-color-ink-muted:  var(--go-sand-700);  /*  8.9:1 on surface */
  --go-color-ink-subtle: var(--go-sand-600);  /*  4.8:1 on surface */
  --go-color-ink-invert: var(--go-white);

  --go-color-line:        var(--go-sand-900); /* the structural 2px border */
  --go-color-line-soft:   var(--go-sand-300); /* internal dividers */
  --go-color-line-medium: var(--go-sand-400);

  --go-color-brand:          var(--go-yellow-400);
  --go-color-brand-hover:    var(--go-yellow-300);
  --go-color-brand-active:   var(--go-yellow-500);
  --go-color-brand-surface:  var(--go-yellow-50);
  --go-color-on-brand:       var(--go-sand-900);

  --go-color-focus: var(--go-blue-500);

  /* Status */
  --go-color-success:         var(--go-green-500);
  --go-color-success-ink:     var(--go-green-ink);
  --go-color-success-surface: #E4F7EC;
  --go-color-warning:         var(--go-yellow-400);
  --go-color-warning-ink:     var(--go-yellow-700);
  --go-color-warning-surface: var(--go-yellow-50);
  --go-color-danger:          var(--go-red-500);
  --go-color-danger-ink:      var(--go-red-ink);
  --go-color-danger-surface:  #FDECE8;
  --go-color-info:            var(--go-blue-500);
  --go-color-info-ink:        var(--go-blue-ink);
  --go-color-info-surface:    #E8F0FE;

  /* Content categories. --go-cat is the per-component hook: a tile or badge
   * sets --go-cat and every accent inside it follows. */
  --go-color-cat-tiendas: var(--go-yellow-400);
  --go-color-cat-video:   var(--go-coral-500);
  --go-color-cat-noticias: var(--go-blue-500);
  --go-color-cat-bga:     var(--go-purple-500);
  --go-color-cat-crowd:   var(--go-green-500);
  --go-color-cat-eventos: var(--go-teal-500);
  --go-cat: var(--go-color-brand);

  /* The ink that sits ON a --go-cat fill, and the second half of the same hook:
   * every filled category component reads it instead of naming a colour, so a
   * subtree that repaints --go-cat can keep the text on it readable by setting
   * one more property beside it.
   *
   * The six palette colours above are light enough that ink is the right
   * answer for all of them, which is why the default is ink and not a
   * computed contrast. It exists for the colours the system does not choose —
   * an operator picking a dark accent has nowhere else to say so. */
  --go-cat-ink: var(--go-color-ink);

  /* ==========================================================================
   * 4. TYPE
   * Sizes are px and every line-height is a multiple of 4px, so a block of
   * text always occupies a whole number of grid rows.
   * ====================================================================== */
  --go-font-sans: Outfit, ui-sans-serif, system-ui, -apple-system, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --go-font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo,
    Consolas, monospace;

  --go-text-2xs: 11px;   --go-leading-2xs: 16px;
  --go-text-xs:  12px;   --go-leading-xs:  16px;
  --go-text-sm:  13px;   --go-leading-sm:  20px;
  --go-text-md:  15px;   --go-leading-md:  24px;   /* body default */
  --go-text-lg:  17px;   --go-leading-lg:  24px;
  --go-text-xl:  20px;   --go-leading-xl:  28px;
  --go-text-2xl: 24px;   --go-leading-2xl: 32px;
  --go-text-3xl: 30px;   --go-leading-3xl: 36px;
  --go-text-4xl: 38px;   --go-leading-4xl: 44px;
  --go-text-5xl: 48px;   --go-leading-5xl: 52px;

  --go-weight-regular: 400;
  --go-weight-medium: 500;
  --go-weight-semibold: 600;
  --go-weight-bold: 700;
  --go-weight-extrabold: 800;
  --go-weight-black: 900;

  /* Optical tracking: large type needs negative, small caps-y type positive. */
  --go-tracking-tight: -0.04em;
  --go-tracking-snug: -0.025em;
  --go-tracking-normal: -0.011em;
  --go-tracking-wide: 0.05em;
  --go-tracking-caps: 0.09em;

  /* ==========================================================================
   * 5. CONTROLS
   * Every interactive control is one of four heights. Heights are explicit and
   * content is centred with flexbox, so a button, an input and a select of the
   * same size are always exactly the same height — padding never decides it.
   * ====================================================================== */
  --go-control-h-xs: 24px;
  --go-control-h-sm: 32px;
  --go-control-h-md: 40px;   /* default */
  --go-control-h-lg: 48px;

  --go-control-px-xs: var(--go-space-2);   /*  8px */
  --go-control-px-sm: var(--go-space-3);   /* 12px */
  --go-control-px-md: var(--go-space-4);   /* 16px */
  --go-control-px-lg: var(--go-space-5);   /* 20px */

  /* Gap between an icon and its label, per size. */
  --go-control-gap-xs: var(--go-space-1);
  --go-control-gap-sm: var(--go-space-2);
  --go-control-gap-md: var(--go-space-2);
  --go-control-gap-lg: var(--go-space-2);

  /* ==========================================================================
   * 6. ICONS
   * Icons are always rendered in a square box from this set, and the box is
   * matched to the line-height of the text beside it so baselines never shift.
   * ====================================================================== */
  --go-icon-xs: 12px;
  --go-icon-sm: 16px;
  --go-icon-md: 20px;   /* default: pairs with 24px line-height */
  --go-icon-lg: 24px;
  --go-icon-xl: 32px;
  --go-icon-stroke: 2;  /* matches the 2px border language */

  /* ==========================================================================
   * 7. BORDERS, RADII, SHADOW
   * The 2px border and the hard offset shadow are the signature of this
   * direction. The shadow is offset-only (no blur) and never affects layout.
   * ====================================================================== */
  --go-border-width: 2px;
  --go-border-width-hair: 1px;
  --go-border: var(--go-border-width) solid var(--go-color-line);
  --go-border-soft: var(--go-border-width) solid var(--go-color-line-soft);

  --go-radius-xs: 6px;
  --go-radius-sm: 8px;
  --go-radius-md: 12px;
  --go-radius-lg: 16px;
  --go-radius-xl: 20px;
  --go-radius-2xl: 24px;
  --go-radius-pill: 999px;
  --go-radius-control: var(--go-radius-pill);  /* override for square controls */

  --go-shadow-xs: 2px 2px 0 var(--go-color-line);
  --go-shadow-sm: 3px 3px 0 var(--go-color-line);
  --go-shadow-md: 4px 4px 0 var(--go-color-line);
  --go-shadow-lg: 6px 6px 0 var(--go-color-line);
  /* Category-tinted variant used by tiles. */
  --go-shadow-cat: 4px 4px 0 var(--go-cat);

  /* ==========================================================================
   * 8. FOCUS
   * One focus treatment everywhere. Drawn outside the box so it never changes
   * layout or nudges neighbours.
   * ====================================================================== */
  --go-focus-width: 3px;
  --go-focus-offset: 2px;
  --go-focus-color: var(--go-color-focus);

  /* ==========================================================================
   * 9. LAYOUT
   * ====================================================================== */
  --go-container-max: 1340px;
  --go-container-pad: var(--go-space-5);       /* 20px desktop */
  --go-container-pad-sm: var(--go-space-4);    /* 16px tablet  */
  --go-container-pad-xs: var(--go-space-3);    /* 12px phone   */

  --go-grid-columns: 12;
  --go-grid-gap: var(--go-space-4);            /* 16px */

  --go-card-pad: var(--go-space-4);            /* 16px — one value, so content
                                                  aligns across every card */
  --go-card-pad-lg: var(--go-space-6);

  /* ==========================================================================
   * 10. MOTION & LAYERS
   * ====================================================================== */
  --go-duration-fast: 120ms;
  --go-duration-base: 180ms;
  --go-duration-slow: 260ms;
  --go-ease: cubic-bezier(0.2, 0, 0.2, 1);

  --go-z-base: 0;
  --go-z-sticky: 100;
  --go-z-header: 200;
  --go-z-dropdown: 300;
  --go-z-overlay: 400;
  --go-z-modal: 500;
  --go-z-toast: 600;
}

/* Responsive container padding. Declared here so layout never re-derives it. */
@media (max-width: 900px) {
  :root { --go-container-pad: var(--go-container-pad-sm); }
}
@media (max-width: 560px) {
  :root { --go-container-pad: var(--go-container-pad-xs); }
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --go-duration-fast: 1ms;
    --go-duration-base: 1ms;
    --go-duration-slow: 1ms;
  }
}

/* ==== 02-reset.css ====================================================== */
/* ============================================================================
 * Reset
 * ----------------------------------------------------------------------------
 * Minimal, and specifically tuned for alignment. The rules that matter for the
 * grid are marked ALIGNMENT — removing them reintroduces sub-pixel drift.
 * ========================================================================== */

*,
*::before,
*::after {
  /* ALIGNMENT: borders and padding must live inside the declared box, or a 2px
   * border makes a 40px control 44px tall and every row it sits in drifts. */
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  tab-size: 4;
  /* This system is light-only for v1 (README, "out of scope"). Saying so out
   * loud is what keeps the browser's OWN surfaces light on a machine set to
   * dark — form controls, scroll bars, the canvas behind a bounce scroll —
   * instead of half the page inverting underneath the tokens. Delete this the
   * day a dark token set exists, not before. */
  color-scheme: light;
}

body {
  margin: 0;
  min-height: 100%;
  background: var(--go-color-canvas);
  color: var(--go-color-ink);
  font-family: var(--go-font-sans);
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
  letter-spacing: var(--go-tracking-normal);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
}

/* ALIGNMENT: headings and paragraphs ship with browser margins that are not on
 * the 4px grid. Spacing is applied deliberately by layout primitives instead. */
h1, h2, h3, h4, h5, h6,
p, figure, blockquote, dl, dd, ol, ul, pre {
  margin: 0;
}

ol, ul {
  padding: 0;
  list-style: none;
}

/* ALIGNMENT: replaced elements are inline by default, which adds a phantom
 * descender gap (typically 3-5px) under every image, svg and video. */
img, svg, video, canvas, audio, iframe, embed, object {
  display: block;
  vertical-align: middle;
}

img, video {
  max-width: 100%;
  height: auto;
}

/* ALIGNMENT: form controls do not inherit type, and their default line-height
 * is not on the grid. Both are forced back to the system. */
button, input, select, optgroup, textarea {
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  margin: 0;
}

button, [role="button"] {
  cursor: pointer;
  background: none;
  border: 0;
  padding: 0;
}

button:disabled,
input:disabled,
select:disabled,
textarea:disabled {
  cursor: not-allowed;
}

textarea {
  resize: vertical;
}

/* Remove the number-input spinners; they break control height on some engines. */
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }

a {
  color: inherit;
  text-decoration: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

hr {
  border: 0;
  border-top: var(--go-border-width-hair) solid var(--go-color-line-soft);
  margin: 0;
}

/* Long words must not blow out a grid column. */
h1, h2, h3, h4, h5, h6, p, li, dd, dt, figcaption {
  overflow-wrap: break-word;
}

:where(strong, b) { font-weight: var(--go-weight-bold); }
:where(small) { font-size: var(--go-text-xs); }

/* One focus ring for the whole system, drawn outside the box so it never
 * changes layout. */
:focus-visible {
  outline: var(--go-focus-width) solid var(--go-focus-color);
  outline-offset: var(--go-focus-offset);
  border-radius: inherit;
}
:focus:not(:focus-visible) { outline: none; }

[hidden] { display: none !important; }

/* ==== 03-typography.css ================================================= */
/* ============================================================================
 * Typography
 * ----------------------------------------------------------------------------
 * One class per role. Every class sets font-size AND line-height together —
 * they are never separable, because the line-height is what keeps the text
 * block on the 4px grid.
 *
 *   .go-display   48/52   page hero
 *   .go-h1        38/44   page title
 *   .go-h2        30/36   major section
 *   .go-h3        24/32   tile heading
 *   .go-h4        20/28   sub-section
 *   .go-h5        17/24   card title
 *   .go-h6        15/24   dense card title
 *   .go-body      15/24   default copy
 *   .go-body-sm   13/20   secondary copy, table cells
 *   .go-caption   12/16   meta, timestamps
 *   .go-overline  11/16   uppercase label above a heading
 * ========================================================================== */

.go-display,
.go-h1, .go-h2, .go-h3, .go-h4, .go-h5, .go-h6 {
  font-family: var(--go-font-sans);
  color: var(--go-color-ink);
  text-wrap: balance;
}

.go-display {
  font-size: var(--go-text-5xl);
  line-height: var(--go-leading-5xl);
  font-weight: var(--go-weight-black);
  letter-spacing: var(--go-tracking-tight);
}

.go-h1 {
  font-size: var(--go-text-4xl);
  line-height: var(--go-leading-4xl);
  font-weight: var(--go-weight-black);
  letter-spacing: var(--go-tracking-tight);
}

.go-h2 {
  font-size: var(--go-text-3xl);
  line-height: var(--go-leading-3xl);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-tight);
}

.go-h3 {
  font-size: var(--go-text-2xl);
  line-height: var(--go-leading-2xl);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-snug);
}

.go-h4 {
  font-size: var(--go-text-xl);
  line-height: var(--go-leading-xl);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-snug);
}

.go-h5 {
  font-size: var(--go-text-lg);
  line-height: var(--go-leading-lg);
  font-weight: var(--go-weight-bold);
  letter-spacing: var(--go-tracking-snug);
}

.go-h6 {
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
  font-weight: var(--go-weight-bold);
  letter-spacing: var(--go-tracking-normal);
}

.go-body {
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
  font-weight: var(--go-weight-regular);
  letter-spacing: var(--go-tracking-normal);
}

.go-body-sm {
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-medium);
  letter-spacing: var(--go-tracking-normal);
}

.go-caption {
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-medium);
  letter-spacing: 0;
  color: var(--go-color-ink-subtle);
}

.go-overline {
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-caps);
  text-transform: uppercase;
  color: var(--go-color-ink-subtle);
}

/* --- modifiers ----------------------------------------------------------- */

.go-text-muted   { color: var(--go-color-ink-muted); }
.go-text-subtle  { color: var(--go-color-ink-subtle); }
.go-text-brand   { color: var(--go-yellow-700); }  /* readable brand text */
.go-text-cat     { color: var(--go-cat); }
.go-text-success { color: var(--go-color-success-ink); }
.go-text-danger  { color: var(--go-color-danger-ink); }

.go-text-left   { text-align: left; }
.go-text-center { text-align: center; }
.go-text-right  { text-align: right; }

/* Tabular figures. Mandatory for any column of numbers — proportional digits
 * make prices and counts jitter between rows. */
.go-numeric {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.go-mono {
  font-family: var(--go-font-mono);
  font-variant-numeric: tabular-nums;
}

/* Clamp helpers. Line-clamped text stays on the grid because max-height is a
 * whole multiple of the line-height. */
.go-truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.go-clamp-1,
.go-clamp-2,
.go-clamp-3 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.go-clamp-1 { -webkit-line-clamp: 1; }
.go-clamp-2 { -webkit-line-clamp: 2; }
.go-clamp-3 { -webkit-line-clamp: 3; }

/* Rich text: the only place where descendants get automatic spacing. */
.go-prose > * + * { margin-top: var(--go-space-4); }
.go-prose p { max-width: 68ch; }
.go-prose a {
  color: var(--go-color-ink);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  text-decoration-color: var(--go-color-brand);
}
.go-prose a:hover { background: var(--go-color-brand); }

/* Inline link inside UI copy. */
.go-link {
  color: var(--go-color-ink);
  font-weight: var(--go-weight-semibold);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  text-decoration-color: var(--go-color-brand);
  border-radius: var(--go-radius-xs);
}
.go-link:hover { text-decoration-color: var(--go-color-ink); }

/* ==== 04-layout.css ===================================================== */
/* ============================================================================
 * Layout primitives
 * ----------------------------------------------------------------------------
 * Components never set their own outer margins. All spacing between things is
 * owned by one of these primitives, which is why arbitrary combinations of
 * components stay on the grid.
 *
 *   .go-container   centred page gutter
 *   .go-grid        12-column grid
 *   .go-bento       the tile grid (12-col, content-height rows)
 *   .go-stack       vertical rhythm  (gap only, no margins)
 *   .go-cluster     horizontal group, wraps, vertically centred
 *   .go-row         horizontal group, no wrap, vertically centred
 *   .go-split       two ends pushed apart, vertically centred
 *   .go-media       fixed-width leading block + fluid body  <- the alignment
 *                   workhorse behind every list row
 * ========================================================================== */

/* --- container ----------------------------------------------------------- */

.go-container {
  width: 100%;
  max-width: var(--go-container-max);
  margin-inline: auto;
  padding-inline: var(--go-container-pad);
}

.go-container--narrow { max-width: 760px; }
.go-container--flush { padding-inline: 0; }

/* --- 12 column grid ------------------------------------------------------ */

.go-grid {
  display: grid;
  grid-template-columns: repeat(var(--go-grid-columns), minmax(0, 1fr));
  gap: var(--go-grid-gap);
}

/* Column spans. minmax(0,1fr) above is what stops a long word from widening
 * a column and knocking the whole grid out of alignment. */
.go-col-1  { grid-column: span 1; }
.go-col-2  { grid-column: span 2; }
.go-col-3  { grid-column: span 3; }
.go-col-4  { grid-column: span 4; }
.go-col-5  { grid-column: span 5; }
.go-col-6  { grid-column: span 6; }
.go-col-7  { grid-column: span 7; }
.go-col-8  { grid-column: span 8; }
.go-col-9  { grid-column: span 9; }
.go-col-10 { grid-column: span 10; }
.go-col-11 { grid-column: span 11; }
.go-col-12 { grid-column: span 12; }

@media (max-width: 1120px) {
  .go-col-md-4  { grid-column: span 4; }
  .go-col-md-6  { grid-column: span 6; }
  .go-col-md-8  { grid-column: span 8; }
  .go-col-md-12 { grid-column: span 12; }
}

@media (max-width: 760px) {
  .go-col-sm-6  { grid-column: span 6; }
  .go-col-sm-12 { grid-column: span 12; }
  /* Below this width a 12-column grid is theatre: everything goes full width. */
  .go-grid--collapse > * { grid-column: 1 / -1; }
}

/* --- bento --------------------------------------------------------------- */

.go-bento {
  display: grid;
  grid-template-columns: repeat(var(--go-grid-columns), minmax(0, 1fr));
  gap: var(--go-grid-gap);
  /* Tiles size to their content instead of stretching to the tallest tile in
   * the row. Stretching is what produces half-empty cards. */
  align-items: start;
}

@media (max-width: 1120px) {
  .go-bento > * { grid-column: span 6; }
}
@media (max-width: 760px) {
  .go-bento > * { grid-column: span 12 !important; }
}

/* --- stack: the vertical rhythm primitive -------------------------------- */

/* Uses gap, never margins: margins collapse, gaps do not, so the spacing you
 * declare is the spacing you get regardless of what the children are. */
.go-stack {
  display: flex;
  flex-direction: column;
  gap: var(--go-stack-gap, var(--go-space-4));
  min-width: 0;
}

.go-stack--0  { --go-stack-gap: var(--go-space-0); }
.go-stack--1  { --go-stack-gap: var(--go-space-1); }
.go-stack--2  { --go-stack-gap: var(--go-space-2); }
.go-stack--3  { --go-stack-gap: var(--go-space-3); }
.go-stack--4  { --go-stack-gap: var(--go-space-4); }
.go-stack--5  { --go-stack-gap: var(--go-space-5); }
.go-stack--6  { --go-stack-gap: var(--go-space-6); }
.go-stack--8  { --go-stack-gap: var(--go-space-8); }
.go-stack--10 { --go-stack-gap: var(--go-space-10); }
.go-stack--12 { --go-stack-gap: var(--go-space-12); }
.go-stack--16 { --go-stack-gap: var(--go-space-16); }

/* Pushes everything after it to the bottom of a flex container. */
.go-push { margin-top: auto; }

/* --- cluster / row / split ----------------------------------------------- */

/* ALIGNMENT: align-items:center is the default for every horizontal primitive.
 * A 40px button next to 20px text next to a 20px icon centre on one axis. */
.go-cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--go-cluster-gap, var(--go-space-2));
  min-width: 0;
}

.go-row {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--go-cluster-gap, var(--go-space-2));
  min-width: 0;
}

.go-cluster--1 , .go-row--1  { --go-cluster-gap: var(--go-space-1); }
.go-cluster--2 , .go-row--2  { --go-cluster-gap: var(--go-space-2); }
.go-cluster--3 , .go-row--3  { --go-cluster-gap: var(--go-space-3); }
.go-cluster--4 , .go-row--4  { --go-cluster-gap: var(--go-space-4); }
.go-cluster--6 , .go-row--6  { --go-cluster-gap: var(--go-space-6); }

/* Align a cluster to the top instead — for a row whose items are different
 * heights on purpose (e.g. an icon beside a two-line paragraph). */
.go-cluster--top, .go-row--top { align-items: flex-start; }
.go-cluster--baseline, .go-row--baseline { align-items: baseline; }

.go-split {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--go-space-4);
  min-width: 0;
}

.go-spacer { flex: 1 1 auto; min-width: 0; }

/* --- media: fixed leading block + fluid body ----------------------------- */

/* Every list row in the system is this shape. The leading block is a fixed
 * token width, so text starts at exactly the same x-offset in every row of a
 * list — which is the single most visible alignment property of a feed. */
.go-media {
  display: flex;
  align-items: center;
  gap: var(--go-media-gap, var(--go-space-3));
  min-width: 0;
}

.go-media--top { align-items: flex-start; }

.go-media__figure {
  flex: none;
  /* never shrinks, never grows: the text edge cannot move */
}

.go-media__body {
  flex: 1 1 auto;
  min-width: 0;   /* lets .go-truncate work inside */
}

.go-media__aside {
  flex: none;
  margin-left: auto;
  text-align: right;
}

/* --- misc ---------------------------------------------------------------- */

.go-section { padding-block: var(--go-space-8); }
.go-section--tight { padding-block: var(--go-space-6); }
.go-section--loose { padding-block: var(--go-space-12); }

.go-divider {
  height: var(--go-border-width);
  background: var(--go-color-line-soft);
  border-radius: var(--go-radius-pill);
}

.go-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Horizontal scroller for chip/tab rows on narrow screens. */
.go-scroller {
  display: flex;
  gap: var(--go-space-2);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.go-scroller::-webkit-scrollbar { display: none; }
.go-scroller > * { flex: none; }

/* ==== 05-icon.css ======================================================= */
/* ============================================================================
 * Icons
 * ----------------------------------------------------------------------------
 * Rules that make icons sit correctly next to text, every time:
 *
 *   1. An icon is always a square box from the token set (12/16/20/24/32).
 *   2. The box is `display:block` and `flex:none` — never inline (phantom
 *      descender gap) and never shrinkable (squashed icons).
 *   3. The box is paired with the line-height of the text beside it, not with
 *      the font-size. 20px icon + 24px line box = optically centred.
 *   4. Colour comes from `currentColor` so an icon always matches its label.
 *
 * Markup:
 *   <svg class="go-icon" aria-hidden="true"><use href="#go-i-search"/></svg>
 * ========================================================================== */

.go-icon {
  display: block;
  flex: none;
  width: var(--go-icon-size, var(--go-icon-md));
  height: var(--go-icon-size, var(--go-icon-md));
  color: inherit;
  fill: none;
  stroke: currentColor;
  stroke-width: var(--go-icon-stroke);
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Guards against a parent grid or flex stretching the glyph. */
  align-self: center;
  pointer-events: none;
}

.go-icon--xs { --go-icon-size: var(--go-icon-xs); stroke-width: 2.5; }
.go-icon--sm { --go-icon-size: var(--go-icon-sm); stroke-width: 2.25; }
.go-icon--md { --go-icon-size: var(--go-icon-md); }
.go-icon--lg { --go-icon-size: var(--go-icon-lg); }
.go-icon--xl { --go-icon-size: var(--go-icon-xl); stroke-width: 1.75; }

/* Solid icons (filled glyphs rather than strokes). */
.go-icon--solid { fill: currentColor; stroke: none; }

/* Slot: a fixed square that reserves icon space even when empty, so a list of
 * rows where only some have icons still aligns its text. */
.go-icon-slot {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--go-icon-slot, var(--go-icon-lg));
  height: var(--go-icon-slot, var(--go-icon-lg));
}
.go-icon-slot--sm { --go-icon-slot: var(--go-icon-md); }
.go-icon-slot--lg { --go-icon-slot: var(--go-icon-xl); }

/* ---------------------------------------------------------------------------
 * Hex marker — the GameOn logo silhouette, used as the category bullet on
 * tile headers. Sized to sit in a 24px line box beside a 17/24 title.
 *
 * The BOX is square; the hexagon inside it is not, and must not be. A regular
 * hexagon with its points left and right is √3/2 = 0.866 as tall as it is
 * wide, so its flat top and bottom sit at (1 − √3/2) / 2 = 6.7% and 93.3% of
 * the box. The 25% / 75% corners say the same thing on the other axis: at that
 * height the flat edge is exactly one side length, which is half the width.
 *
 * Pushing those two numbers out towards 0% and 100% is the mistake this shape
 * invites, because it makes the ink fill the square. The result reads as a
 * hexagon stretched taller than the mark it stands in for — the logo's own
 * outer ring measures 0.86 — and looks subtly wrong beside it at every size.
 * ------------------------------------------------------------------------ */
.go-hex {
  display: block;
  flex: none;
  width: var(--go-hex-size, 20px);
  height: var(--go-hex-size, 20px);
  background: var(--go-cat);
  clip-path: polygon(25% 6.7%, 75% 6.7%, 100% 50%, 75% 93.3%, 25% 93.3%, 0 50%);
}
.go-hex--sm { --go-hex-size: 16px; }
.go-hex--lg { --go-hex-size: 24px; }

/* ---------------------------------------------------------------------------
 * Decorative icon tile — icon on a filled, bordered square. Used in empty
 * states and callouts. Sizes are control heights so it lines up with buttons.
 * ------------------------------------------------------------------------ */
.go-icon-box {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--go-control-h-lg);
  height: var(--go-control-h-lg);
  border: var(--go-border);
  border-radius: var(--go-radius-md);
  background: var(--go-cat);
  color: var(--go-cat-ink);
}
.go-icon-box--sm {
  width: var(--go-control-h-md);
  height: var(--go-control-h-md);
  border-radius: var(--go-radius-sm);
}
.go-icon-box--lg {
  width: var(--go-space-16);
  height: var(--go-space-16);
  border-radius: var(--go-radius-lg);
}

/* ==== 10-button.css ===================================================== */
/* ============================================================================
 * Button
 * ----------------------------------------------------------------------------
 * The reference implementation of the control contract:
 *
 *   height comes from a token, NOT from padding
 *   + display:inline-flex + align-items:center
 *   = a button, an input and a select of the same size are pixel-identical,
 *     and an icon inside any of them is centred without nudging.
 *
 * Never set vertical padding on a control. If content needs more room, move up
 * a size. This is the rule that keeps toolbars flat.
 *
 *   <button class="go-btn go-btn--primary">
 *     <svg class="go-icon go-icon--sm" aria-hidden="true">…</svg>
 *     Suscribirme
 *   </button>
 * ========================================================================== */

.go-btn {
  /* box */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--go-control-gap-md);
  height: var(--go-control-h-md);
  padding-block: 0;                 /* height owns the vertical axis */
  padding-inline: var(--go-control-px-md);
  border: var(--go-border);
  border-radius: var(--go-radius-control);
  background: var(--go-color-surface);
  color: var(--go-color-ink);

  /* type */
  font-family: var(--go-font-sans);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-bold);
  letter-spacing: var(--go-tracking-normal);
  white-space: nowrap;
  text-align: center;

  /* behaviour */
  cursor: pointer;
  user-select: none;
  text-decoration: none;
  flex: none;
  transition:
    background-color var(--go-duration-fast) var(--go-ease),
    box-shadow var(--go-duration-fast) var(--go-ease),
    transform var(--go-duration-fast) var(--go-ease);
}

.go-btn:hover { background: var(--go-sand-200); }
.go-btn:active { transform: translate(1px, 1px); }

.go-btn:disabled,
.go-btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
  /* A link cannot be truly disabled, so aria-disabled has to be backed up here
   * — otherwise the button looks dead and still navigates on click. */
  pointer-events: none;
}

/* --- sizes ---------------------------------------------------------------
 * Only height, horizontal padding, gap and type change. Nothing else.
 * ------------------------------------------------------------------------ */

.go-btn--xs {
  height: var(--go-control-h-xs);
  padding-inline: var(--go-control-px-xs);
  gap: var(--go-control-gap-xs);
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  border-width: var(--go-border-width-hair);
}

.go-btn--sm {
  height: var(--go-control-h-sm);
  padding-inline: var(--go-control-px-sm);
  gap: var(--go-control-gap-sm);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
}

.go-btn--md {
  height: var(--go-control-h-md);
  padding-inline: var(--go-control-px-md);
  gap: var(--go-control-gap-md);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
}

.go-btn--lg {
  height: var(--go-control-h-lg);
  padding-inline: var(--go-control-px-lg);
  gap: var(--go-control-gap-lg);
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
}

/* --- variants ------------------------------------------------------------ */

.go-btn--primary {
  background: var(--go-color-brand);
  color: var(--go-color-on-brand);
  box-shadow: var(--go-shadow-xs);
}
.go-btn--primary:hover { background: var(--go-color-brand-hover); }
.go-btn--primary:active { box-shadow: none; }

.go-btn--secondary {
  background: var(--go-color-surface);
  box-shadow: var(--go-shadow-xs);
}
.go-btn--secondary:hover { background: var(--go-sand-200); }
.go-btn--secondary:active { box-shadow: none; }

/* The offset shadow is lightened rather than inked: a black shadow on a black
 * button is invisible. (This used to carry two box-shadow declarations, the
 * first of them dead.) */
.go-btn--solid {
  background: var(--go-color-ink);
  color: var(--go-color-ink-invert);
  box-shadow: var(--go-border-width) var(--go-border-width) 0 var(--go-sand-600);
}
.go-btn--solid:hover { background: var(--go-sand-800); }
.go-btn--solid:active { box-shadow: none; }

/* Quiet: no border, no fill. Still the same height, so it lines up with the
 * loud buttons beside it. */
.go-btn--ghost {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
}
.go-btn--ghost:hover { background: var(--go-sand-200); }

.go-btn--danger {
  background: var(--go-color-danger);
  color: var(--go-color-ink-invert);
  border-color: var(--go-color-line);
  box-shadow: var(--go-shadow-xs);
}
.go-btn--danger:hover { background: var(--go-red-400); }
.go-btn--danger:active { box-shadow: none; }

/* Follows the surrounding category colour.
 *
 * The hover is the only one in this file that is DERIVED rather than picked,
 * and it has to be: every variant above hovers to a second hex the palette
 * ships, and a category colour has no second hex — it is whatever the app set
 * --go-cat to. Without a rule of its own this variant fell through to
 * `.go-btn:hover`, which outranks `.go-btn--cat` on specificity (0,2,0 against
 * 0,1,0) whatever the source order, so hovering a category button replaced the
 * accent with pale sand-200 and left --go-cat-ink sitting on it. Text picked to
 * be readable on a dark fill washed out completely.
 *
 * The move is: mix a little of the direction AWAY from the ink into the fill.
 * Away, not towards, because that is the only direction that cannot cost
 * contrast — the fill steps further from its own text, never closer, so a pair
 * that was readable at rest is more readable on hover. Measured in Chrome on
 * the shipped palette and on hand-picked pairs: 11.63→12.43 (tiendas yellow),
 * 3.35→4.49 (bga purple), 3.53→4.68 (noticias blue), 2.92→4.27 (a light blue
 * with white text), 15.78→17.38 (navy with white text), 10.78→12.59 (brown
 * with cream text).
 *
 * `oklch(from …)` reads the ink's own lightness, and clamp() is standing in for
 * an `if`: multiplying the ink's distance from mid lightness by 1000 saturates
 * the bounds, so the third colour is pure white for a dark ink and pure black
 * for a light one, with nothing in between. 14% is the step that reproduces the
 * one hand-picked precedent for this direction — brand yellow hovering to the
 * lighter yellow-300 — landing on #FAD150 against the token's #FCD84D, oklab
 * lightness 0.874 against 0.889 from a base of 0.853.
 *
 * A browser without relative colour syntax drops the whole declaration and gets
 * `.go-btn:hover` back, which is exactly today's behaviour rather than a break.
 */
.go-btn--cat {
  background: var(--go-cat);
  color: var(--go-cat-ink);
  box-shadow: var(--go-shadow-xs);
}
.go-btn--cat:hover {
  background: color-mix(in oklab, var(--go-cat) 86%,
                        oklch(from var(--go-cat-ink) clamp(0, calc((0.5 - l) * 1000), 1) 0 h));
}
.go-btn--cat:active { box-shadow: none; }

/* --- shape --------------------------------------------------------------- */

/* Square: width locked to height so the glyph is centred both ways. */
.go-btn--icon {
  width: var(--go-control-h-md);
  padding-inline: 0;
}
.go-btn--icon.go-btn--xs { width: var(--go-control-h-xs); }
.go-btn--icon.go-btn--sm { width: var(--go-control-h-sm); }
.go-btn--icon.go-btn--lg { width: var(--go-control-h-lg); }

.go-btn--block { display: flex; width: 100%; flex: 1 1 auto; }

.go-btn--square { border-radius: var(--go-radius-md); }

/* --- button group --------------------------------------------------------
 * Buttons joined into one control. Borders overlap so the seam stays 2px.
 * ------------------------------------------------------------------------ */

.go-btn-group {
  display: inline-flex;
  align-items: center;
}
.go-btn-group > .go-btn { border-radius: 0; }
.go-btn-group > .go-btn + .go-btn { margin-left: calc(var(--go-border-width) * -1); }
.go-btn-group > .go-btn:first-child {
  border-start-start-radius: var(--go-radius-control);
  border-end-start-radius: var(--go-radius-control);
}
.go-btn-group > .go-btn:last-child {
  border-start-end-radius: var(--go-radius-control);
  border-end-end-radius: var(--go-radius-control);
}
.go-btn-group > .go-btn:hover,
.go-btn-group > .go-btn[aria-pressed="true"] { position: relative; z-index: 1; }
.go-btn-group > .go-btn[aria-pressed="true"] { background: var(--go-color-brand); }

/* --- loading -------------------------------------------------------------
 * The label stays in the DOM and keeps its width, so the button does not
 * resize and the row does not reflow while a request is in flight.
 * ------------------------------------------------------------------------ */

.go-btn--loading {
  position: relative;
  color: transparent !important;
  pointer-events: none;
}
.go-btn--loading::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: var(--go-icon-sm);
  height: var(--go-icon-sm);
  margin: calc(var(--go-icon-sm) / -2) 0 0 calc(var(--go-icon-sm) / -2);
  border: 2px solid currentColor;
  border-top-color: var(--go-color-ink);
  border-radius: 50%;
  color: color-mix(in srgb, var(--go-color-ink) 25%, transparent);
  animation: go-spin 700ms linear infinite;
}

@keyframes go-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .go-btn--loading::after { animation-duration: 2s; }
}

/* ==== 11-field.css ====================================================== */
/* ============================================================================
 * Fields — input, textarea, select, search
 * ----------------------------------------------------------------------------
 * Same control contract as .go-btn: explicit height from a token, no vertical
 * padding. An input and a button on the same row are the same height by
 * construction, not by coincidence.
 *
 *   <div class="go-field">
 *     <label class="go-field__label" for="email">Correo</label>
 *     <input class="go-input" id="email" type="email" placeholder="tu@correo.mx">
 *     <p class="go-field__help">Un correo los lunes. Nada más.</p>
 *   </div>
 * ========================================================================== */

.go-field {
  display: flex;
  flex-direction: column;
  gap: var(--go-space-2);
  min-width: 0;
}

.go-field__label {
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-bold);
  color: var(--go-color-ink);
}

.go-field__label--required::after {
  content: "*";
  margin-left: var(--go-space-1);
  color: var(--go-color-danger-ink);
}

.go-field__help {
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  color: var(--go-color-ink-subtle);
}

.go-field__error {
  display: flex;
  align-items: center;
  gap: var(--go-space-1);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-semibold);
  color: var(--go-color-danger-ink);
}

/* --- the control itself -------------------------------------------------- */

.go-input,
.go-select,
.go-textarea {
  display: block;
  width: 100%;
  height: var(--go-control-h-md);
  padding-block: 0;
  padding-inline: var(--go-control-px-md);
  border: var(--go-border);
  border-radius: var(--go-radius-control);
  background: var(--go-color-surface);
  color: var(--go-color-ink);
  font-family: var(--go-font-sans);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-medium);
  /* Lets an input shrink inside a flex row instead of forcing overflow.
   * Browsers give inputs an intrinsic width of ~20 characters otherwise. */
  min-width: 0;
  transition: border-color var(--go-duration-fast) var(--go-ease),
              background-color var(--go-duration-fast) var(--go-ease);
}

.go-input::placeholder,
.go-textarea::placeholder { color: var(--go-color-ink-subtle); }

.go-input:hover,
.go-select:hover,
.go-textarea:hover { background: var(--go-sand-50); }

.go-input:disabled,
.go-select:disabled,
.go-textarea:disabled {
  background: var(--go-sand-200);
  color: var(--go-color-ink-subtle);
  border-color: var(--go-color-line-medium);
}

.go-input[aria-invalid="true"],
.go-select[aria-invalid="true"],
.go-textarea[aria-invalid="true"] {
  border-color: var(--go-color-danger);
  background: var(--go-color-danger-surface);
}

/* Sizes */
.go-input--sm, .go-select--sm {
  height: var(--go-control-h-sm);
  padding-inline: var(--go-control-px-sm);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
}
.go-input--lg, .go-select--lg {
  height: var(--go-control-h-lg);
  padding-inline: var(--go-control-px-lg);
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
}

/* Textarea is the one control whose height is not fixed. It is sized in whole
 * line-heights plus padding, so it still lands on the 4px grid:
 *   3 rows = 3 * 20px + 2 * 8px padding + 2 * 2px border = 80px */
.go-textarea {
  height: auto;
  min-height: calc(var(--go-leading-sm) * 3 + var(--go-space-2) * 2 + var(--go-border-width) * 2);
  padding-block: var(--go-space-2);
  border-radius: var(--go-radius-md);
  line-height: var(--go-leading-sm);
}

/* --- select --------------------------------------------------------------
 * Native arrow removed and redrawn so the control matches the others exactly.
 * ------------------------------------------------------------------------ */

.go-select {
  appearance: none;
  -webkit-appearance: none;
  padding-inline-end: var(--go-space-8);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%2317150F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--go-space-3) center;
  background-size: var(--go-icon-md) var(--go-icon-md);
  cursor: pointer;
}

/* --- input with leading/trailing content --------------------------------- */

/* The wrapper owns the border and the height; the inner input is transparent
 * and borderless. That keeps the affordance one single box — nesting two
 * bordered boxes is what makes search fields look 1px off. */
.go-input-group {
  display: flex;
  align-items: center;
  gap: var(--go-space-2);
  height: var(--go-control-h-md);
  padding-inline: var(--go-control-px-md);
  border: var(--go-border);
  border-radius: var(--go-radius-control);
  background: var(--go-color-surface);
  min-width: 0;
}

.go-input-group:focus-within {
  outline: var(--go-focus-width) solid var(--go-focus-color);
  outline-offset: var(--go-focus-offset);
}

.go-input-group > .go-input {
  height: auto;
  border: 0;
  padding: 0;
  background: transparent;
  border-radius: 0;
  flex: 1 1 auto;
}
.go-input-group > .go-input:hover { background: transparent; }
.go-input-group > .go-input:focus-visible { outline: none; }

.go-input-group > .go-icon { color: var(--go-color-ink-subtle); }

.go-input-group--sm {
  height: var(--go-control-h-sm);
  padding-inline: var(--go-control-px-sm);
}
.go-input-group--lg {
  height: var(--go-control-h-lg);
  padding-inline: var(--go-control-px-lg);
}

/* Affix: static text glued to the field, e.g. a currency symbol. */
.go-input-group__affix {
  flex: none;
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-bold);
  color: var(--go-color-ink-subtle);
}

/* --- inline form: field + button on one row ------------------------------ */

.go-form-inline {
  display: flex;
  align-items: center;
  gap: var(--go-space-2);
  min-width: 0;
}
.go-form-inline > .go-input,
.go-form-inline > .go-input-group { flex: 1 1 auto; min-width: 0; }

/* On a phone the field and the button stack full width. Without this the
 * button's intrinsic width forces the row wider than the viewport. */
@media (max-width: 560px) {
  .go-form-inline { flex-direction: column; align-items: stretch; }
  .go-form-inline > .go-btn { width: 100%; }
  /* The flex-grow above was written for a ROW. Once the container flips to a
   * column, the main axis is vertical and `flex:1 1 auto` inflates the field
   * to fill the container's height — a 40px control rendered 272px tall. Reset
   * it explicitly; the width is what should stretch here, not the height. */
  .go-form-inline > .go-input,
  .go-form-inline > .go-input-group,
  .go-form-inline > .go-select {
    flex: 0 0 auto;
    width: 100%;
  }
}

/* --- range --------------------------------------------------------------- */

.go-range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: var(--go-control-h-md);   /* keeps it aligned in a control row */
  background: transparent;
  cursor: pointer;
}
.go-range::-webkit-slider-runnable-track {
  height: 8px;
  border: var(--go-border-width-hair) solid var(--go-color-line);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-surface-sunk);
}
.go-range::-moz-range-track {
  height: 8px;
  border: var(--go-border-width-hair) solid var(--go-color-line);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-surface-sunk);
}
.go-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: var(--go-icon-md);
  height: var(--go-icon-md);
  margin-top: -7px;
  border: var(--go-border);
  border-radius: 50%;
  background: var(--go-color-brand);
}
.go-range::-moz-range-thumb {
  width: var(--go-icon-md);
  height: var(--go-icon-md);
  border: var(--go-border);
  border-radius: 50%;
  background: var(--go-color-brand);
}

/* ==== 12-choice.css ===================================================== */
/* ============================================================================
 * Choice controls — checkbox, radio, switch
 * ----------------------------------------------------------------------------
 * The control box is 20px and sits in a 24px line box, so it centres against
 * 15/24 label text without a nudge. A list of checkboxes has its labels on the
 * same x-offset as any other .go-media row.
 *
 *   <label class="go-choice">
 *     <input class="go-choice__input" type="checkbox" checked>
 *     <span class="go-choice__box"></span>
 *     <span class="go-choice__label">En stock</span>
 *     <span class="go-choice__count go-numeric">5</span>
 *   </label>
 * ========================================================================== */

/* position:relative is not decoration. The real input below is absolutely
 * positioned with no offsets, so it PAINTS at its static position either way —
 * but without a positioned ancestor its containing block is the page, and an
 * ancestor's `overflow` cannot clip it. Put a choice inside a .go-table-scroll
 * and the input's 20px box is the one thing the scroller does not absorb: it
 * holds its screen position past the right edge and the document grows the
 * horizontal scrollbar the scroller existed to prevent. */
.go-choice {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--go-space-2);
  min-height: var(--go-control-h-sm);   /* comfortable hit area, still on grid */
  cursor: pointer;
  user-select: none;
  min-width: 0;
}

.go-choice--top { align-items: flex-start; }

/* The real input stays in the DOM for accessibility and is visually replaced.
 * It is NOT display:none — that removes it from the a11y tree in some AT. */
.go-choice__input {
  position: absolute;
  width: 20px;
  height: 20px;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}

.go-choice__box {
  display: grid;
  place-items: center;
  flex: none;
  width: 20px;
  height: 20px;
  border: var(--go-border);
  border-radius: var(--go-radius-xs);
  background: var(--go-color-surface);
  transition: background-color var(--go-duration-fast) var(--go-ease);
}

/* Radio: same box, round. Same size, so a mixed list still aligns. */
.go-choice--radio .go-choice__box { border-radius: 50%; }

/* Checkmark drawn with a pseudo-element so no icon dependency. */
.go-choice__box::after {
  content: "";
  width: 10px;
  height: 6px;
  border-left: 2.5px solid var(--go-color-ink);
  border-bottom: 2.5px solid var(--go-color-ink);
  transform: rotate(-45deg) translate(1px, -1px) scale(0.6);
  opacity: 0;
  transition: opacity var(--go-duration-fast) var(--go-ease),
              transform var(--go-duration-fast) var(--go-ease);
}
.go-choice--radio .go-choice__box::after {
  width: 8px;
  height: 8px;
  border: 0;
  border-radius: 50%;
  background: var(--go-color-ink);
  transform: scale(0.5);
}

.go-choice__input:checked + .go-choice__box {
  background: var(--go-color-brand);
}
.go-choice__input:checked + .go-choice__box::after {
  opacity: 1;
  transform: rotate(-45deg) translate(1px, -1px) scale(1);
}
.go-choice--radio .go-choice__input:checked + .go-choice__box::after {
  transform: scale(1);
}

/* Checkboxes only. A RADIO matches :indeterminate whenever no radio in its
 * group is checked — that is the spec, not a browser quirk — so without the
 * :not() every option in an untouched radio group renders filled brand-yellow
 * with a dash through it: the "some but not all" state, drawn on a control
 * that cannot mean it, at the exact moment the user has answered nothing.
 *
 * Found on a question list where pre-selecting an option was not allowed
 * (the choice had to be the reader's), which is what made the usual dodge —
 * check one by default — unavailable. docs/page.html has no unanswered radio
 * group, so nothing here had ever rendered this state. */
.go-choice__input:indeterminate:not([type="radio"]) + .go-choice__box { background: var(--go-color-brand); }
.go-choice__input:indeterminate:not([type="radio"]) + .go-choice__box::after {
  opacity: 1;
  width: 10px; height: 0;
  border-left: 0;
  border-bottom: 2.5px solid var(--go-color-ink);
  transform: none;
}

.go-choice__input:focus-visible + .go-choice__box {
  outline: var(--go-focus-width) solid var(--go-focus-color);
  outline-offset: var(--go-focus-offset);
}

.go-choice:hover .go-choice__box { background: var(--go-sand-200); }
.go-choice__input:checked:hover + .go-choice__box { background: var(--go-color-brand-hover); }

.go-choice__input:disabled + .go-choice__box {
  background: var(--go-sand-200);
  border-color: var(--go-color-line-medium);
}
.go-choice:has(.go-choice__input:disabled) {
  cursor: not-allowed;
  color: var(--go-color-ink-subtle);
}

.go-choice__label {
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-medium);
  min-width: 0;
}

/* Right-aligned facet count, as used in a filter sidebar. */
.go-choice__count {
  margin-left: auto;
  flex: none;
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-semibold);
  color: var(--go-color-ink-subtle);
}

/* --- switch --------------------------------------------------------------
 * 40x24 track: the height matches the 24px line box, so a switch aligns with
 * label text exactly like a checkbox does.
 * ------------------------------------------------------------------------ */

/* position:relative for the same reason as .go-choice above — the hidden input
 * has to be clipped by the same overflow that clips the label. */
.go-switch { position: relative; display: flex; align-items: center; gap: var(--go-space-3); cursor: pointer; }

.go-switch__input {
  position: absolute;
  width: 40px; height: 24px;
  opacity: 0; margin: 0; cursor: pointer;
}

.go-switch__track {
  position: relative;
  flex: none;
  width: 40px;
  height: 24px;
  border: var(--go-border);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-surface-sunk);
  transition: background-color var(--go-duration-base) var(--go-ease);
}

.go-switch__track::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--go-color-ink);
  transition: transform var(--go-duration-base) var(--go-ease);
}

.go-switch__input:checked + .go-switch__track { background: var(--go-color-brand); }
.go-switch__input:checked + .go-switch__track::after { transform: translateX(16px); }

.go-switch__input:focus-visible + .go-switch__track {
  outline: var(--go-focus-width) solid var(--go-focus-color);
  outline-offset: var(--go-focus-offset);
}

.go-switch__input:disabled + .go-switch__track { opacity: 0.5; }

/* --- fieldset ------------------------------------------------------------ */

.go-fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }

.go-fieldset__legend {
  padding: 0;
  margin-bottom: var(--go-space-2);
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-caps);
  text-transform: uppercase;
  color: var(--go-color-ink-subtle);
}

/* ==== 13-chip.css ======================================================= */
/* ============================================================================
 * Chip — a toggleable filter pill
 * ----------------------------------------------------------------------------
 * A chip is a control, so it obeys the control heights. A row of chips beside
 * a button or a search field is flat by construction.
 *
 * Use a real <button aria-pressed> so the state is announced, not just painted.
 *
 *   <button class="go-chip" type="button" aria-pressed="true">
 *     <span class="go-chip__dot" style="--go-cat: var(--go-color-cat-video)"></span>
 *     Video
 *     <span class="go-chip__count go-numeric">6</span>
 *   </button>
 * ========================================================================== */

.go-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--go-space-2);
  height: var(--go-control-h-sm);
  padding-block: 0;
  padding-inline: var(--go-control-px-sm);
  border: var(--go-border);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-surface);
  color: var(--go-color-ink);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-bold);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  flex: none;
  transition: background-color var(--go-duration-fast) var(--go-ease),
              box-shadow var(--go-duration-fast) var(--go-ease);
}

.go-chip:hover { background: var(--go-sand-200); }

/* Selected. The shadow appears on selection, which reads as "pressed in" and
 * gives a non-colour cue for the state. */
.go-chip[aria-pressed="true"],
.go-chip--selected {
  background: var(--go-color-brand);
  box-shadow: var(--go-shadow-xs);
}

/* Category-tinted selection, for the content-type filter row. */
.go-chip--cat[aria-pressed="true"] {
  background: var(--go-cat);
  color: var(--go-cat-ink);
}

.go-chip:disabled,
.go-chip[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }

.go-chip--md {
  height: var(--go-control-h-md);
  padding-inline: var(--go-control-px-md);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
}

.go-chip--xs {
  height: var(--go-control-h-xs);
  padding-inline: var(--go-control-px-xs);
  gap: var(--go-space-1);
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  border-width: var(--go-border-width-hair);
}

.go-chip__dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--go-cat);
}

.go-chip__count {
  flex: none;
  font-weight: var(--go-weight-semibold);
  color: var(--go-color-ink-subtle);
}
.go-chip[aria-pressed="true"] .go-chip__count { color: var(--go-color-ink); opacity: 0.65; }

/* Removable chip: the × is a real button so it is reachable by keyboard. */
.go-chip__remove {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--go-icon-sm);
  height: var(--go-icon-sm);
  margin-inline-end: calc(var(--go-space-1) * -1);
  border-radius: 50%;
  color: var(--go-color-ink-subtle);
  cursor: pointer;
}
.go-chip__remove:hover { background: var(--go-color-ink); color: var(--go-color-ink-invert); }

/* A chip row that scrolls sideways on narrow screens instead of wrapping. */
.go-chip-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--go-space-2);
}
@media (max-width: 760px) {
  .go-chip-row {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
    /* bleed to the container edge so the last chip is visibly cut, which is
     * the affordance that tells the user it scrolls */
    margin-inline: calc(var(--go-container-pad) * -1);
    padding-inline: var(--go-container-pad);
  }
  .go-chip-row::-webkit-scrollbar { display: none; }
}

/* ==== 14-badge.css ====================================================== */
/* ============================================================================
 * Badge — a non-interactive status or category label
 * ----------------------------------------------------------------------------
 * Badges are NOT controls: they are 20px or 24px tall so they sit inside a
 * 24px line box next to text without pushing the line taller. Never put a
 * badge at a control height (32/40) inline with copy — it will change the
 * leading of that line and break the rhythm of the paragraph.
 *
 *   <span class="go-badge go-badge--success">En stock</span>
 * ========================================================================== */

.go-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--go-space-1);
  height: 20px;
  padding-inline: var(--go-space-2);
  border: var(--go-border-width-hair) solid var(--go-color-line);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-surface);
  color: var(--go-color-ink);
  font-size: var(--go-text-2xs);
  line-height: 1;         /* the 20px height owns the box; see note above */
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-wide);
  text-transform: uppercase;
  white-space: nowrap;
  flex: none;
  vertical-align: middle;
}

.go-badge--lg {
  height: 24px;
  padding-inline: var(--go-space-3);
  font-size: var(--go-text-xs);
}

/* Loud variant with the full 2px border, for a badge that stands alone rather
 * than sitting inside running text. */
.go-badge--strong { border-width: var(--go-border-width); height: 24px; }

/* --- semantic tones ------------------------------------------------------ */

.go-badge--neutral { background: var(--go-sand-300); }
.go-badge--brand   { background: var(--go-color-brand); }
.go-badge--success { background: var(--go-color-success-surface); color: var(--go-color-success-ink); }
.go-badge--warning { background: var(--go-color-warning-surface); color: var(--go-color-warning-ink); }
.go-badge--danger  { background: var(--go-color-danger-surface);  color: var(--go-color-danger-ink); }
.go-badge--info    { background: var(--go-color-info-surface);    color: var(--go-color-info-ink); }

/* Filled, high-contrast. For the one badge on screen that must win. */
.go-badge--solid {
  background: var(--go-color-ink);
  color: var(--go-color-ink-invert);
  border-color: var(--go-color-ink);
}
.go-badge--cat {
  background: var(--go-cat);
  border-color: var(--go-color-line);
  color: var(--go-cat-ink);
}

/* Quiet: no border. Reads as metadata, not as a control. */
.go-badge--ghost { border-color: transparent; background: var(--go-sand-200); }

/* --- dot marker ----------------------------------------------------------
 * Status expressed as a coloured square + text, for dense tables where a
 * pill would be too heavy. The 8px dot sits in the text's own line box.
 * ------------------------------------------------------------------------ */

.go-status {
  display: inline-flex;
  align-items: center;
  gap: var(--go-space-2);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-semibold);
  white-space: nowrap;
}
.go-status::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  background: var(--go-color-ink-subtle);
}
.go-status--success::before { background: var(--go-color-success); }
.go-status--warning::before { background: var(--go-color-warning); }
.go-status--danger::before  { background: var(--go-color-danger); }
.go-status--info::before    { background: var(--go-color-info); }
.go-status--cat::before     { background: var(--go-cat); }

/* --- count bubble --------------------------------------------------------
 * The little number on a nav item. Fixed 20px height, min-width equal to the
 * height so a single digit is a circle and two digits are a pill.
 * ------------------------------------------------------------------------ */

.go-count {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 20px;
  min-width: 20px;
  padding-inline: var(--go-space-1);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-brand);
  color: var(--go-color-on-brand);
  font-size: var(--go-text-2xs);
  line-height: 1;
  font-weight: var(--go-weight-extrabold);
  font-variant-numeric: tabular-nums;
  flex: none;
}
.go-count--quiet { background: var(--go-sand-300); color: var(--go-color-ink-muted); }
.go-count--solid { background: var(--go-color-ink); color: var(--go-color-ink-invert); }

/* ==== 15-card.css ======================================================= */
/* ============================================================================
 * Card / Tile — the module container
 * ----------------------------------------------------------------------------
 * The signature of this direction: 2px border, hard offset shadow, generous
 * radius. Alignment rules baked in:
 *
 *   - ONE padding token (--go-card-pad) on every card, so the content of two
 *     cards side by side starts at the same x-offset.
 *   - The header is a fixed 24px line box, so headers align across a row even
 *     when one title wraps to a different length.
 *   - The offset shadow is a box-shadow, so it never occupies layout space and
 *     never pushes a neighbour off the grid.
 *   - Dividers between rows are drawn with border-top on rows 2..n, so the
 *     first and last row have identical padding to the card edge.
 *
 *   <section class="go-tile" style="--go-cat: var(--go-color-cat-video)">
 *     <header class="go-tile__head">
 *       <span class="go-hex"></span>
 *       <h2 class="go-tile__title">Video y reseñas</h2>
 *       <a class="go-tile__action" href="#">Canales →</a>
 *     </header>
 *     <div class="go-tile__body"> … </div>
 *     <a class="go-tile__foot" href="#">Ver todo</a>
 *   </section>
 * ========================================================================== */

/* ALIGNMENT — padding is measured from the OUTER edge.
 * A 2px border plus a 16px padding insets content by 18px, so everything in
 * every card sits 2px off the absolute grid. The declared padding token is the
 * distance from the card's outer edge to its content, and the border is paid
 * for out of it: 16 - 2 = 14. Every bordered container in this system follows
 * the same rule. */
.go-card,
.go-tile {
  --go-card-inset: calc(var(--go-card-pad) - var(--go-border-width));
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: var(--go-card-inset);
  border: var(--go-border);
  border-radius: var(--go-radius-xl);
  background: var(--go-color-surface);
  box-shadow: var(--go-shadow-md);
}

/* Tinted shadow, keyed to the tile's category. */
.go-tile--cat { box-shadow: var(--go-shadow-cat); }

.go-card--flat,
.go-tile--flat { box-shadow: none; }

.go-card--sunk {
  background: var(--go-color-surface-sunk);
  box-shadow: none;
}

.go-card--quiet {
  border-color: var(--go-color-line-soft);
  box-shadow: none;
}

.go-card--pad-lg { --go-card-pad: var(--go-card-pad-lg); }
.go-card--pad-0  { padding: 0; }

/* Interactive card: the whole tile is a link. Movement on hover is a translate
 * plus a shadow change, never a size change — resizing would reflow the grid. */
.go-card--link { transition: transform var(--go-duration-fast) var(--go-ease),
                             box-shadow var(--go-duration-fast) var(--go-ease); }
.go-card--link:hover { transform: translate(-2px, -2px); box-shadow: var(--go-shadow-lg); }
.go-card--link:active { transform: translate(1px, 1px); box-shadow: var(--go-shadow-xs); }

/* --- header --------------------------------------------------------------
 * Fixed 24px line box. The hex is 20px and the title is 17/24, so the marker
 * optically centres on the title's cap-height without a manual offset.
 * ------------------------------------------------------------------------ */

.go-tile__head {
  display: flex;
  align-items: center;
  gap: var(--go-space-2);
  min-height: var(--go-leading-lg);   /* 24px */
  margin-bottom: var(--go-space-3);
  min-width: 0;
}

.go-tile__title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--go-text-lg);
  line-height: var(--go-leading-lg);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-snug);
  color: var(--go-color-ink);
}

/* Trailing link in a header. Sits on the title's baseline row. */
.go-tile__action {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: var(--go-space-1);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-bold);
  color: var(--go-color-ink-subtle);
  white-space: nowrap;
  border-radius: var(--go-radius-xs);
}
.go-tile__action:hover { color: var(--go-color-ink); }

.go-tile__body { min-width: 0; }

/* Footer action pinned to the bottom of the tile. Only meaningful when the
 * tile is stretched to a fixed height; in a .go-bento (align-items:start) the
 * tile hugs its content and this is just the last row. */
.go-tile__foot {
  display: block;
  margin-top: var(--go-space-3);
  padding: var(--go-space-2);
  border: var(--go-border);
  border-radius: var(--go-radius-md);
  background: var(--go-color-surface-sunk);
  color: var(--go-color-ink);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-bold);
  text-align: center;
}
.go-tile__foot:hover { background: var(--go-color-brand); }

/* --- panel: a card with an edge-to-edge body -----------------------------
 * For tables and lists that should touch the card border. Padding moves from
 * the card to the individual rows so the divider lines still run full width.
 * ------------------------------------------------------------------------ */

.go-panel {
  border: var(--go-border);
  border-radius: var(--go-radius-lg);
  background: var(--go-color-surface);
  box-shadow: var(--go-shadow-md);
  overflow: hidden;   /* clips child corners to the radius */
  min-width: 0;
}

.go-panel__head {
  display: flex;
  align-items: center;
  gap: var(--go-space-2);
  min-height: var(--go-control-h-lg);
  padding-inline: calc(var(--go-card-pad) - var(--go-border-width));
  border-bottom: var(--go-border);
  background: var(--go-color-surface-sunk);
}

.go-panel__body { padding: calc(var(--go-card-pad) - var(--go-border-width)); }
.go-panel__body--flush { padding: 0; }

.go-panel__foot {
  display: flex;
  align-items: center;
  gap: var(--go-space-2);
  min-height: var(--go-control-h-lg);
  padding-inline: calc(var(--go-card-pad) - var(--go-border-width));
  border-top: var(--go-border);
  background: var(--go-color-surface-sunk);
}

/* --- hero tile: card with a full-bleed image at the top ------------------- */

.go-tile__media {
  margin: calc(var(--go-card-inset) * -1) calc(var(--go-card-inset) * -1) var(--go-space-3);
  border-bottom: var(--go-border);
  border-start-start-radius: calc(var(--go-radius-xl) - var(--go-border-width));
  border-start-end-radius: calc(var(--go-radius-xl) - var(--go-border-width));
  overflow: hidden;
}

/* --- callout panel: the newsletter / CTA block --------------------------- */

/* align-items:flex-start, not center. Centring offsets an item by half the
 * difference in sibling heights, and that difference changes with text wrap —
 * a 40px actions row beside an 84px text block lands on a 22px offset. Starting
 * both blocks at the content edge is the only placement that stays on the grid
 * at every width. */
.go-cta {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--go-space-5);
  padding: calc(var(--go-space-6) - var(--go-border-width));
  border: var(--go-border);
  border-radius: var(--go-radius-xl);
  background: var(--go-color-brand);
  box-shadow: var(--go-shadow-md);
  min-width: 0;
}
.go-cta__body { flex: 1 1 320px; min-width: 0; }
.go-cta__actions { flex: 1 1 320px; min-width: 0; max-width: 480px; }

/* flex-direction is restated because .go-cta is often also a .go-tile, which
 * sets `column`; without this the actions block keeps its content width and
 * overflows the card on narrow screens. */
@media (max-width: 700px) {
  .go-cta { flex-direction: column; align-items: stretch;
    padding: calc(var(--go-space-5) - var(--go-border-width)); }
  .go-cta__actions { max-width: none; }
}

/* ==== 16-list.css ======================================================= */
/* ============================================================================
 * List & list row — the workhorse
 * ----------------------------------------------------------------------------
 * Nearly every module in the product is a list of rows: releases, videos,
 * editions, deals, events, BGA games. One row component serves all of them,
 * which is what makes six different modules look like one product.
 *
 * Anatomy (left to right):
 *   [figure]  fixed width from a token   ← text edge can never move
 *   [body]    fluid, min-width:0         ← truncates instead of pushing
 *   [aside]   fixed, right-aligned       ← prices/badges align in a column
 *
 *   <li class="go-row-item">
 *     <div class="go-row-item__figure"> <img class="go-thumb"> </div>
 *     <div class="go-row-item__body">
 *       <p class="go-row-item__title">Bomb Busters</p>
 *       <p class="go-row-item__meta">Edición en español · La Ludoteca Roma</p>
 *     </div>
 *     <div class="go-row-item__aside"> … </div>
 *   </li>
 * ========================================================================== */

.go-list {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* Dividers on every row after the first. Doing it this way (rather than
 * border-bottom on all rows plus a :last-child reset) means the first and last
 * rows have identical spacing to the card edge. */
.go-list > * + * {
  border-top: var(--go-border-width) solid var(--go-color-line-soft);
}

/* ALIGNMENT: a 2px divider added on top of an 8px padding makes the row 2px
 * taller than its neighbour, so the distance between row tops stops being a
 * multiple of 4 and a long list drifts off the grid. The divider is paid for
 * out of the row's own top padding, keeping every row box a clean 4px multiple.
 * Higher specificity than .go-row-item so it wins the padding-block shorthand. */
.go-list > .go-row-item + .go-row-item {
  padding-top: calc(var(--go-space-2) - var(--go-border-width));
}
.go-list .go-row-item--sm + .go-row-item--sm {
  padding-top: calc(var(--go-space-1) - var(--go-border-width));
}
.go-list .go-row-item--lg + .go-row-item--lg {
  padding-top: calc(var(--go-space-3) - var(--go-border-width));
}

/* Wrapper for a linked row: <li class="go-list__item"><a class="go-row-item">.
 * An <a> cannot be a direct child of <ul>, so the <li> carries the divider and
 * the anchor keeps the row layout. The divider compensation moves to the inner
 * row so the total box is unchanged. */
.go-list__item { display: block; min-width: 0; }
.go-list > * + .go-list__item > .go-row-item {
  padding-top: calc(var(--go-space-2) - var(--go-border-width));
}

.go-list--gap {
  gap: var(--go-space-2);
}
.go-list--gap > * + * { border-top: 0; }

/* Rows separated by the full 2px ink border. */
.go-list--strong > * + * { border-top-color: var(--go-color-line); }

.go-list--plain > * + * { border-top: 0; }

/* --- the row ------------------------------------------------------------- */

.go-row-item {
  display: flex;
  align-items: center;
  gap: var(--go-space-3);
  padding-block: var(--go-space-2);
  min-width: 0;
  min-height: var(--go-space-12);   /* 48px: keeps sparse rows on the grid */
  color: inherit;
}

/* Rows inside a bordered panel need horizontal padding of their own so the
 * divider lines can run edge to edge. The value is held in a variable because
 * --feature has to bleed *relative to it*; hard-coding both meant the feature
 * rule silently overrode the inset padding and shifted its title by 8px. */
.go-list--inset .go-row-item {
  --go-row-pad: calc(var(--go-card-pad) - var(--go-border-width));
  padding-inline: var(--go-row-pad);
}

.go-row-item--sm { min-height: var(--go-control-h-md); padding-block: var(--go-space-1); }
.go-row-item--lg { min-height: var(--go-space-16); padding-block: var(--go-space-3); }

/* Top-aligned variant, for rows whose body runs to several lines. */
.go-row-item--top { align-items: flex-start; }

/* Whole row is a link. */
a.go-row-item,
.go-row-item--link { transition: background-color var(--go-duration-fast) var(--go-ease); }
a.go-row-item:hover,
.go-row-item--link:hover { background: var(--go-sand-50); }

/* Highlighted row — the featured event, the deal of the day. The background
 * bleeds 8px past the row's normal padding on both sides while the CONTENT edge
 * stays put: padding = normal padding + the 8px bleed.
 *
 * The class is doubled for specificity: `.go-list--inset .go-row-item` is
 * (0,2,0) and would otherwise win the padding-inline, shifting the featured
 * row's text 8px away from every other row in the list. */
.go-row-item.go-row-item--feature {
  background: var(--go-color-brand-surface);
  border-radius: var(--go-radius-md);
  margin-inline: calc(var(--go-space-2) * -1);
  padding-inline: calc(var(--go-row-pad, 0px) + var(--go-space-2));
  border-top-color: transparent;
}

.go-row-item__figure { flex: none; }

/* Fixed-width leading slot for variable-width labels — a category tag, a time,
 * a short date. ALIGNMENT: a badge placed directly in the row is as wide as its
 * own text, so "INDUSTRIA" and "GUÍA" would start their titles 34px apart. The
 * slot pins the text edge; override the width with --go-lead-w. */
.go-row-item__lead {
  flex: none;
  display: flex;
  align-items: center;
  width: var(--go-lead-w, 88px);
  min-width: 0;
}
.go-row-item__lead--sm { --go-lead-w: 64px; }
.go-row-item__lead--lg { --go-lead-w: 112px; }

.go-row-item__body {
  flex: 1 1 auto;
  min-width: 0;   /* required for truncation to work */
}

.go-row-item__aside {
  flex: none;
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--go-space-1);
  text-align: right;
}

.go-row-item__aside--row {
  flex-direction: row;
  align-items: center;
  gap: var(--go-space-2);
}

/* --- row text ------------------------------------------------------------
 * Title 15/24 over meta 12/16 = a 40px text block, which matches the 40px
 * control height. A row with a button in its aside is therefore flat.
 * ------------------------------------------------------------------------ */

.go-row-item__title {
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
  font-weight: var(--go-weight-bold);
  letter-spacing: var(--go-tracking-snug);
  color: var(--go-color-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.go-row-item__title--wrap { white-space: normal; }

.go-row-item__meta {
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-medium);
  color: var(--go-color-ink-subtle);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.go-row-item__title + .go-row-item__meta { margin-top: 0; }

/* --- index number -------------------------------------------------------- */

/* Defaults to the width of a .go-thumb--sm so a ranked row and a thumbnail row
 * in the SAME list put their titles on one edge. Override --go-index-w when the
 * list uses a different thumb size (md 48px, lg 60px). */
.go-row-item__index {
  flex: none;
  width: var(--go-index-w, 36px);
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
  font-weight: var(--go-weight-extrabold);
  font-variant-numeric: tabular-nums;
  color: var(--go-color-line-medium);
  text-align: center;
}

/* --- compact definition row ---------------------------------------------
 * label on the left, value on the right, dotted leader between. Used for
 * spec lists (jugadores, peso, duración).
 * ------------------------------------------------------------------------ */

.go-deflist { display: flex; flex-direction: column; gap: var(--go-space-2); }

.go-deflist__row {
  display: flex;
  align-items: baseline;
  gap: var(--go-space-2);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
}
.go-deflist__label { color: var(--go-color-ink-subtle); flex: none; }
.go-deflist__fill {
  flex: 1 1 auto;
  border-bottom: var(--go-border-width-hair) dotted var(--go-color-line-medium);
  transform: translateY(-3px);
}
.go-deflist__value { flex: none; font-weight: var(--go-weight-bold); }

/* ==== 17-media.css ====================================================== */
/* ============================================================================
 * Media — thumbnails, box art, video cards, aspect ratios
 * ----------------------------------------------------------------------------
 * Thumbnail sizes are a fixed set, chosen so each is a multiple of 4px in BOTH
 * axes. A 3:4 box-art thumb is 36x48, not 35x47 — arbitrary aspect maths is
 * what puts a row half a pixel off and makes a list look wobbly.
 *
 *   xs  24x32     dense table row
 *   sm  36x48     list row (default)
 *   md  48x64     comfortable list row
 *   lg  60x80     hero row
 *   Video thumbs use 16:9 at 64x36 / 96x54 / 128x72.
 * ========================================================================== */

.go-thumb {
  display: block;
  flex: none;
  width: var(--go-thumb-w, 36px);
  height: var(--go-thumb-h, 48px);
  border: var(--go-border-width) solid var(--go-color-line);
  border-radius: var(--go-radius-sm);
  background-color: var(--go-sand-300);
  background-size: cover;
  background-position: center;
  object-fit: cover;
  overflow: hidden;
}

.go-thumb--xs { --go-thumb-w: 24px; --go-thumb-h: 32px; border-radius: var(--go-radius-xs); border-width: var(--go-border-width-hair); }
.go-thumb--sm { --go-thumb-w: 36px; --go-thumb-h: 48px; }
.go-thumb--md { --go-thumb-w: 48px; --go-thumb-h: 64px; }
.go-thumb--lg { --go-thumb-w: 60px; --go-thumb-h: 80px; }

/* Square variants, for avatars-of-things and BGA tiles. */
.go-thumb--square { --go-thumb-h: var(--go-thumb-w); }
.go-thumb--sq-sm { --go-thumb-w: 32px; --go-thumb-h: 32px; }
.go-thumb--sq-md { --go-thumb-w: 40px; --go-thumb-h: 40px; }
.go-thumb--sq-lg { --go-thumb-w: 56px; --go-thumb-h: 56px; }

/* Wide (video) variants. sm and lg are exact 16:9; md is 12:7, because between
 * 36px and 72px tall there is no exact 16:9 size whose width is also a multiple
 * of 4 (16:9 needs h = 54 there, and 54 is off-grid). The grid wins over the
 * ratio: images are object-fit:cover, so the 2px of crop is invisible, whereas
 * a 54px thumbnail visibly drags its whole row off the grid. */
.go-thumb--wide-sm { --go-thumb-w: 64px;  --go-thumb-h: 36px; }  /* 16:9  */
.go-thumb--wide-md { --go-thumb-w: 96px;  --go-thumb-h: 56px; }  /* 12:7  */
.go-thumb--wide-lg { --go-thumb-w: 128px; --go-thumb-h: 72px; }  /* 16:9  */

/* --- aspect boxes for fluid media ---------------------------------------- */

.go-aspect {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: var(--go-aspect, 16 / 9);
  border-radius: var(--go-radius-md);
  background-color: var(--go-sand-300);
  background-size: cover;
  background-position: center;
  overflow: hidden;
}
.go-aspect--16x9 { --go-aspect: 16 / 9; }
.go-aspect--4x3  { --go-aspect: 4 / 3; }
.go-aspect--3x2  { --go-aspect: 3 / 2; }
.go-aspect--1x1  { --go-aspect: 1 / 1; }
.go-aspect--3x4  { --go-aspect: 3 / 4; }
.go-aspect--21x9 { --go-aspect: 21 / 9; }

.go-aspect--bordered { border: var(--go-border); }

/* ALIGNMENT: an aspect-ratio box on a FLUID width has a fluid — and therefore
 * usually fractional — height. A 21:9 hero at 660px is 282.86px tall, and every
 * row stacked below it inherits that .86 and sits off the grid for the rest of
 * the page.
 *
 * Use a ratio box when the media is the last thing in its column. Use a fixed
 * height whenever content follows it inside the same vertical rhythm. Images
 * are object-fit:cover, so the crop is invisible; the drift is not. */
.go-aspect--h-xs { aspect-ratio: auto; height: 96px; }
.go-aspect--h-sm { aspect-ratio: auto; height: 140px; }
.go-aspect--h-md { aspect-ratio: auto; height: 200px; }
.go-aspect--h-lg { aspect-ratio: auto; height: 280px; }

.go-aspect > img,
.go-aspect > video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* --- video affordances ---------------------------------------------------
 * The play button is centred with position:absolute + inset:0 + grid, never
 * with a translate offset — translate leaves it half a pixel off on odd sizes.
 * ------------------------------------------------------------------------ */

.go-play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
}

.go-play__btn {
  display: grid;
  place-items: center;
  width: var(--go-control-h-md);
  height: var(--go-control-h-md);
  padding-left: 2px;              /* optical: a triangle looks off-centre
                                     when geometrically centred */
  border: var(--go-border);
  border-radius: 50%;
  background: var(--go-color-brand);
  color: var(--go-color-ink);
}
.go-play__btn--sm { width: var(--go-control-h-sm); height: var(--go-control-h-sm); }
.go-play__btn--lg { width: var(--go-control-h-lg); height: var(--go-control-h-lg); }

/* Duration / corner tag over media. */
.go-media-tag {
  position: absolute;
  right: var(--go-space-2);
  bottom: var(--go-space-2);
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding-inline: var(--go-space-2);
  border-radius: var(--go-radius-xs);
  background: var(--go-color-ink);
  color: var(--go-color-ink-invert);
  font-size: var(--go-text-2xs);
  line-height: 1;
  font-weight: var(--go-weight-bold);
  font-variant-numeric: tabular-nums;
}
.go-media-tag--tl { top: var(--go-space-2); bottom: auto; left: var(--go-space-2); right: auto; }
.go-media-tag--tr { top: var(--go-space-2); bottom: auto; }
.go-media-tag--brand { background: var(--go-color-brand); color: var(--go-color-on-brand); }
.go-media-tag--cat { background: var(--go-cat); color: var(--go-cat-ink); border: var(--go-border-width-hair) solid var(--go-color-line); }

/* --- video card ---------------------------------------------------------- */

.go-video {
  display: flex;
  flex-direction: column;
  gap: var(--go-space-2);
  min-width: 0;
  color: inherit;
}

.go-video__frame {
  position: relative;
  border: var(--go-border);
  border-radius: var(--go-radius-md);
  overflow: hidden;
}

.go-video__title {
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-bold);
  letter-spacing: var(--go-tracking-snug);
  /* Two lines exactly = 40px, so a grid of video cards has aligned metadata
   * rows even when one title is short. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  min-height: calc(var(--go-leading-sm) * 2);
}

.go-video__channel {
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-bold);
  color: var(--go-cat);
}

.go-video__meta {
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  color: var(--go-color-ink-subtle);
}

.go-video:hover .go-video__title { text-decoration: underline; text-underline-offset: 2px; }

/* --- date block ----------------------------------------------------------
 * The stacked day/month chip used by every event row. 48x48 so it matches the
 * .go-row-item minimum height and lines up with a 48px thumb.
 * ------------------------------------------------------------------------ */

.go-date {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 48px;
  height: 48px;
  border: var(--go-border);
  border-radius: var(--go-radius-md);
  background: var(--go-color-surface-sunk);
  color: var(--go-color-ink);
}

.go-date__day {
  font-size: var(--go-text-lg);
  line-height: 20px;
  font-weight: var(--go-weight-black);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--go-tracking-snug);
}

.go-date__month {
  font-size: var(--go-text-2xs);
  line-height: 12px;
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-wide);
  text-transform: uppercase;
  color: var(--go-color-ink-subtle);
}

.go-date--cat { background: var(--go-cat); color: var(--go-cat-ink); }
.go-date--cat .go-date__month { color: var(--go-cat-ink); opacity: 0.7; }

/* --- avatar -------------------------------------------------------------- */

.go-avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: var(--go-avatar-size, 32px);
  height: var(--go-avatar-size, 32px);
  border-radius: 50%;
  border: var(--go-border-width-hair) solid var(--go-color-line);
  background: var(--go-color-ink);
  color: var(--go-color-ink-invert);
  font-size: var(--go-text-xs);
  line-height: 1;
  font-weight: var(--go-weight-bold);
  overflow: hidden;
  object-fit: cover;
}
.go-avatar--sm { --go-avatar-size: 24px; font-size: var(--go-text-2xs); }
.go-avatar--md { --go-avatar-size: 32px; }
.go-avatar--lg { --go-avatar-size: 40px; font-size: var(--go-text-sm); }
.go-avatar--xl { --go-avatar-size: 48px; font-size: var(--go-text-md); }

/* ==== 18-table.css ====================================================== */
/* ============================================================================
 * Table
 * ----------------------------------------------------------------------------
 * Alignment rules for data:
 *   - Row height is fixed by a token, not by content, so a table with mixed
 *     cell contents (text, badge, thumb, button) has flat rows.
 *   - Numeric columns are right-aligned AND tabular. Both, always. Right
 *     alignment without tabular figures still jitters.
 *   - The header is uppercase 11/16 and 40px tall, matching a control row.
 *   - Wrap in .go-table-scroll so a wide table scrolls itself instead of
 *     widening the page.
 * ========================================================================== */

.go-table-scroll {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.go-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  min-width: var(--go-table-min, 640px);
}

.go-table th,
.go-table td {
  padding-inline: var(--go-space-3);
  text-align: left;
  vertical-align: middle;
}

.go-table thead th {
  height: var(--go-control-h-md);
  border-bottom: var(--go-border);
  background: var(--go-color-surface);
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-caps);
  text-transform: uppercase;
  color: var(--go-color-ink-subtle);
  white-space: nowrap;
  user-select: none;
}

.go-table tbody td {
  height: var(--go-table-row-h, 56px);
  border-bottom: var(--go-border-width-hair) solid var(--go-color-line-soft);
}

.go-table--dense { --go-table-row-h: 40px; }
.go-table--relaxed { --go-table-row-h: 64px; }

.go-table tbody tr:last-child td { border-bottom: 0; }
.go-table tbody tr:hover td { background: var(--go-sand-50); }

/* Sticky header for long tables. */
.go-table--sticky thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

/* Numeric column. */
.go-table .go-td-num,
.go-table th.go-th-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

.go-table .go-td-num { font-weight: var(--go-weight-semibold); }

/* Fixed-width utility columns so a column of buttons never jumps between
 * tables. */
.go-table .go-td-action { width: 1%; white-space: nowrap; text-align: right; }

/* --- sortable header ----------------------------------------------------- */

.go-th-sort {
  cursor: pointer;
}
.go-th-sort > button {
  display: inline-flex;
  align-items: center;
  gap: var(--go-space-1);
  height: var(--go-control-h-sm);
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  border-radius: var(--go-radius-xs);
}
.go-th-num.go-th-sort > button { flex-direction: row-reverse; }
.go-th-sort:hover > button { color: var(--go-color-ink); }

.go-th-sort__arrow {
  font-size: 9px;
  line-height: 1;
  opacity: 0.35;
}
.go-th-sort[aria-sort="ascending"],
.go-th-sort[aria-sort="descending"] { color: var(--go-color-ink); }
.go-th-sort[aria-sort="ascending"] .go-th-sort__arrow,
.go-th-sort[aria-sort="descending"] .go-th-sort__arrow {
  opacity: 1;
  color: var(--go-yellow-600);
}

/* --- cell helpers -------------------------------------------------------- */

/* Thumb + two lines of text inside a cell, using the media shape so the text
 * edge matches across every row. */
.go-cell-media {
  display: flex;
  align-items: center;
  gap: var(--go-space-3);
  min-width: 0;
}
.go-cell-media__body { min-width: 0; }
.go-cell-title {
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-semibold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.go-cell-meta {
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  color: var(--go-color-ink-subtle);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.go-table caption {
  padding-block: var(--go-space-2);
  text-align: left;
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  color: var(--go-color-ink-subtle);
}

/* --- responsive: stacked cards ------------------------------------------
 * Below the breakpoint each row becomes a block. Requires data-label on each
 * cell. Opt in with .go-table--stack; a table that only needs to scroll should
 * stay in .go-table-scroll instead.
 * ------------------------------------------------------------------------ */

@media (max-width: 700px) {
  .go-table--stack { min-width: 0; }
  .go-table--stack thead { display: none; }
  .go-table--stack, .go-table--stack tbody, .go-table--stack tr, .go-table--stack td {
    display: block;
    width: auto;
  }
  /* Bottom padding pays for the 2px divider, same rule as .go-list, so the
     stacked card's chrome is 24px and every row stays a multiple of 4. */
  .go-table--stack tr {
    padding: var(--go-space-3) 0 calc(var(--go-space-3) - var(--go-border-width));
    border-bottom: var(--go-border-width) solid var(--go-color-line-soft);
  }
  .go-table--stack td {
    /* Fixed, not min-height: a cell whose content is shorter than 32px would
       otherwise collapse to its line box and desync the stack. */
    height: var(--go-control-h-sm);
    border: 0;
    padding-inline: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--go-space-3);
  }
  .go-table--stack td::before {
    content: attr(data-label);
    flex: none;
    font-size: var(--go-text-2xs);
    line-height: var(--go-leading-2xs);
    font-weight: var(--go-weight-extrabold);
    letter-spacing: var(--go-tracking-caps);
    text-transform: uppercase;
    color: var(--go-color-ink-subtle);
  }
  .go-table--stack td:first-child::before { display: none; }
  .go-table--stack .go-td-num { text-align: right; }
}

/* ==== 19-nav.css ======================================================== */
/* ============================================================================
 * Navigation — app bar, pill nav, tabs, breadcrumb, pagination
 * ----------------------------------------------------------------------------
 * The app bar is a single control row: everything in it is a control height, so
 * the logo, the nav pills, the search field and the avatar all centre on one
 * axis with no per-item nudging.
 * ========================================================================== */

/* --- app bar ------------------------------------------------------------- */

/* ALIGNMENT: the rule under the bar is a box-shadow, not a border.
 * A 2px border would make a 64px bar 66px tall and push the entire page 2px off
 * the absolute grid — and shrinking the inner to 62 to compensate just moves
 * the problem, because a 32px control centred in 62px lands on y=15. A shadow
 * draws the same 2px line while occupying no layout at all, so the bar is
 * exactly 64 and its children centre on the grid. */
.go-appbar {
  position: sticky;
  top: 0;
  z-index: var(--go-z-header);
  background: var(--go-color-canvas);
  box-shadow: 0 var(--go-border-width) 0 var(--go-color-line);
}

.go-appbar__inner {
  display: flex;
  align-items: center;
  gap: var(--go-space-3);
  min-height: var(--go-space-16);   /* 64px, border-free */
  padding-block: var(--go-space-3);
  min-width: 0;
}

/* DOES NOT SHRINK, and letting it was tried and reverted. `flex: 0 1 auto` with
 * `min-width: 0` does make room, by shrinking the brand past its own word: at
 * 280px the wordmark rendered as «GameO» underneath the sign-out button. And
 * without `min-width: 0` it shrinks by exactly nothing, because a flex item's
 * automatic minimum is its min-content width and every word in here is
 * unbreakable — so the ellipsis it looked like it was buying was never
 * reachable. A bar that does not fit is a bar with one control too many in it;
 * it is fixed by dropping a word from a control (see the panel's «Salir»), not
 * by grinding down the one element that names the site. */
.go-brand {
  display: flex;
  align-items: center;
  gap: var(--go-space-2);
  flex: none;
  font-size: var(--go-text-xl);
  line-height: var(--go-leading-xl);
  font-weight: var(--go-weight-black);
  letter-spacing: var(--go-tracking-tight);
  color: var(--go-color-ink);
}

.go-brand__mark {
  display: block;
  flex: none;
  /* 40×32, not square: the news mark is wider than tall (its 80×64 artwork).
   * The height is what has to stay on the grid — it is what the 64px app bar
   * measures against — so the width is free to follow the artwork. A square box
   * would letterbox the mark and render it 20% smaller than the wordmark wants. */
  width: var(--go-space-10);  /* 40px */
  height: var(--go-space-8);  /* 32px */
  color: var(--go-color-brand);
  /* No drop shadow. The mark carries its own weight; on the light grounds this
   * system uses, legibility comes from the mark's mass, not from an outline. */
}

.go-brand__suffix {
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-semibold);
  letter-spacing: var(--go-tracking-normal);
  color: var(--go-color-ink-subtle);
}

/* The suffix is the first thing out of a bar that will not fit, because it is
 * the only token in there that is not a destination or an action — «GameOn»
 * alone still names the site, and the heading under the bar says which half of
 * it you are in.
 *
 * 360, the same width as .go-hide-xs, and measured on the fuller of the two
 * bars: with its suffix and a labelled sign-out the panel's bar wants 307px of
 * content and so a 331px screen; with both gone it wants 228 and fits from
 * 252px up. One breakpoint at 360 therefore carries both bars intact from 361
 * and clears the narrowest real phone by 28px below it — and the suffix and
 * that one label go together rather than each getting a threshold pinned to its
 * own cliff, which would buy the suffix 29px of extra life for a second magic
 * number. */
@media (max-width: 360px) {
  .go-brand__suffix { display: none; }
}

/* --- app bar menu (phone) ------------------------------------------------ */

/* The bar's disclosure panel: what the pill nav becomes when there is no room
 * for it beside the brand. Put it INSIDE .go-appbar, after the inner row, and
 * give it `hidden` when closed — the reset makes that `display: none
 * !important`, so a closed panel cannot be left on the page by any later rule,
 * and there is no second class to keep in step with aria-expanded.
 *
 * Inside the sticky bar on purpose: opening it grows the bar and pushes the
 * page down rather than floating over it, so it needs no backdrop, no scroll
 * lock and no z-index of its own.
 *
 * Fill it with a .go-rail — the same vertical nav the desktop shell puts in a
 * column — and not with a second, shorter list. A phone menu naming fewer
 * destinations than the wide layout is a second registry to keep in step. */
.go-appbar__menu {
  /* The bar's own 12px of air under the rule, and 16px below the last item so
   * the rail does not sit flush on the edge of the bar. */
  padding-block: var(--go-space-3) var(--go-space-4);
  /* A sticky element taller than the viewport is pinned at top: 0 and its
   * bottom never comes into view, because it is the page that scrolls and not
   * the bar. A rail of a dozen destinations reaches that height on a small
   * phone, so the panel caps at what is left of the screen under the bar and
   * scrolls within itself. dvh and not vh, or a collapsing address bar leaves
   * the last item under the fold. */
  max-height: calc(100dvh - var(--go-space-16));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* --- pill nav ------------------------------------------------------------ */

/* CLIPPING: `overflow-x: auto` makes overflow-y compute to `auto` too — one
 * axis cannot scroll while the other stays visible — so this is a scroll box
 * exactly as tall as a 32px pill, and the active pill's 2px offset shadow is
 * cut off at the bottom. The padding gives the shadow somewhere to be drawn and
 * the equal negative margin takes it straight back off the layout, so the row
 * still measures 32px and everything in the app bar stays on the grid. */
.go-navpills {
  display: flex;
  align-items: center;
  gap: var(--go-space-1);
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  padding: var(--go-space-1);
  margin: calc(var(--go-space-1) * -1);
}
.go-navpills::-webkit-scrollbar { display: none; }

.go-navpill {
  display: inline-flex;
  align-items: center;
  gap: var(--go-space-2);
  height: var(--go-control-h-sm);
  padding-inline: var(--go-control-px-sm);
  border: var(--go-border-width) solid transparent;
  border-radius: var(--go-radius-pill);
  color: var(--go-color-ink-muted);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-semibold);
  white-space: nowrap;
  flex: none;
}
.go-navpill:hover { background: var(--go-sand-300); color: var(--go-color-ink); }

.go-navpill[aria-current],
.go-navpill--active {
  background: var(--go-color-brand);
  border-color: var(--go-color-line);
  box-shadow: var(--go-shadow-xs);
  color: var(--go-color-ink);
  font-weight: var(--go-weight-bold);
}

/* --- vertical rail nav --------------------------------------------------- */

/* gap comes from the scale: a 2px gap with 40px items gives a 42px stride, so
 * every item after the first walks further off the grid. 40 + 4 = 44. */
.go-rail {
  display: flex;
  flex-direction: column;
  gap: var(--go-space-1);
  min-width: 0;
}

.go-railitem {
  display: flex;
  align-items: center;
  gap: var(--go-space-3);
  height: var(--go-control-h-md);
  padding-inline: var(--go-space-3);
  border-radius: var(--go-radius-md);
  color: var(--go-color-ink-muted);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-semibold);
  min-width: 0;
}
.go-railitem:hover { background: var(--go-sand-200); color: var(--go-color-ink); }
.go-railitem[aria-current],
.go-railitem--active {
  background: var(--go-color-brand-surface);
  color: var(--go-color-ink);
  font-weight: var(--go-weight-bold);
  box-shadow: inset 3px 0 0 var(--go-color-brand);
}
.go-railitem__label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.go-railitem__trail { flex: none; margin-left: auto; }

/* --- tabs ----------------------------------------------------------------
 * Underline tabs. The active indicator is a border on the tab itself, and an
 * equal transparent border sits on inactive tabs, so switching tabs never
 * shifts the row by 2px.
 * ------------------------------------------------------------------------ */

.go-tabs {
  display: flex;
  align-items: center;
  gap: 0;
  border-bottom: var(--go-border-width) solid var(--go-color-line-soft);
  overflow-x: auto;
  scrollbar-width: none;
  min-width: 0;
}
.go-tabs::-webkit-scrollbar { display: none; }

.go-tab {
  display: inline-flex;
  align-items: center;
  gap: var(--go-space-2);
  height: var(--go-control-h-lg);
  padding-inline: var(--go-space-4);
  border: 0;
  border-bottom: var(--go-border-width) solid transparent;
  margin-bottom: calc(var(--go-border-width) * -1);
  color: var(--go-color-ink-subtle);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  font-weight: var(--go-weight-semibold);
  white-space: nowrap;
  flex: none;
  background: none;
}
.go-tab:hover { color: var(--go-color-ink); }
.go-tab[aria-selected="true"],
.go-tab--active {
  color: var(--go-color-ink);
  font-weight: var(--go-weight-bold);
  border-bottom-color: var(--go-color-ink);
}

/* Pill tabs — the city switcher inside a tile. */
.go-tabs--pills {
  border-bottom: 0;
  flex-wrap: wrap;
  gap: var(--go-space-2);
}
.go-tabs--pills .go-tab {
  height: var(--go-control-h-sm);
  padding-inline: var(--go-control-px-sm);
  border: var(--go-border);
  border-radius: var(--go-radius-pill);
  margin-bottom: 0;
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  background: var(--go-color-surface);
  color: var(--go-color-ink);
}
.go-tabs--pills .go-tab:hover { background: var(--go-sand-200); }
.go-tabs--pills .go-tab[aria-selected="true"] {
  background: var(--go-cat);
  color: var(--go-cat-ink);
  border-color: var(--go-color-line);
}
/* A count keeps its own subtle grey by default, which is correct on the
 * surface and unreadable once the pill fills with a category colour — measured
 * at 1.33:1 on eventos teal. Inherit the tab's colour instead, the same way
 * .go-chip[aria-pressed="true"] .go-chip__count does. Hierarchy comes from the
 * bold label beside it, not from a dimmer count. */
.go-tabs--pills .go-tab[aria-selected="true"] .go-chip__count { color: currentColor; }

/* --- breadcrumb ---------------------------------------------------------- */

.go-breadcrumb {
  display: flex;
  align-items: center;
  gap: var(--go-space-2);
  min-height: var(--go-control-h-sm);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  color: var(--go-color-ink-subtle);
  flex-wrap: wrap;
}
.go-breadcrumb__sep { color: var(--go-color-line-medium); }
.go-breadcrumb a:hover { color: var(--go-color-ink); text-decoration: underline; }
.go-breadcrumb [aria-current] { color: var(--go-color-ink); font-weight: var(--go-weight-semibold); }

/* --- pagination ---------------------------------------------------------- */

.go-pagination {
  display: flex;
  align-items: center;
  gap: var(--go-space-1);
}

.go-page {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--go-control-h-sm);
  min-width: var(--go-control-h-sm);
  padding-inline: var(--go-space-2);
  border: var(--go-border);
  border-radius: var(--go-radius-sm);
  background: var(--go-color-surface);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-semibold);
  font-variant-numeric: tabular-nums;
}
.go-page:hover { background: var(--go-sand-200); }
.go-page[aria-current] {
  background: var(--go-color-ink);
  border-color: var(--go-color-ink);
  color: var(--go-color-ink-invert);
  font-weight: var(--go-weight-bold);
}
.go-page[aria-disabled="true"] { opacity: 0.4; pointer-events: none; }

/* --- bottom tab bar (mobile) --------------------------------------------- */

/* Same reasoning as the app bar: the rule is a shadow so the bar is exactly
 * 56px, which is what .go-has-tabbar reserves below the content. */
.go-tabbar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--go-z-sticky);
  display: none;
  box-shadow: 0 calc(var(--go-border-width) * -1) 0 var(--go-color-line);
  background: var(--go-color-surface);
  padding-bottom: env(safe-area-inset-bottom);
}
.go-tabbar__inner { display: flex; justify-content: space-around; align-items: stretch; }
/* Fixed height, not min-height: the icon + label stack measures 40px, so a
 * min-height plus padding would resolve to whatever the content happened to be
 * rather than to the token. */
.go-tabbar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--go-space-1);
  flex: 1 1 0;
  height: var(--go-space-14);   /* 56px */
  padding-block: var(--go-space-1);
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  font-weight: var(--go-weight-semibold);
  color: var(--go-color-ink-subtle);
}
.go-tabbar__item[aria-current] { color: var(--go-color-ink); font-weight: var(--go-weight-bold); }

@media (max-width: 760px) {
  .go-tabbar { display: block; }
  /* Reserve the bar's height so it never covers the end of the page. */
  .go-has-tabbar { padding-bottom: calc(var(--go-space-14) + env(safe-area-inset-bottom)); }
}

/* ==== 20-data.css ======================================================= */
/* ============================================================================
 * Data display — progress, price, stat, sparkline, skeleton
 * ========================================================================== */

/* --- progress ------------------------------------------------------------
 * Crowdfunding is the awkward case: campaigns routinely pass 100%, and simply
 * clamping the fill makes 340% and 180% look identical. The track therefore
 * represents --go-progress-max (default 400%) and a tick marks the 100% goal.
 * Set --go-progress-max: 100 for an ordinary 0-100 bar.
 * ------------------------------------------------------------------------ */

.go-progress {
  /* Documented API. --go-progress-width is the fill (already scaled by the
   * caller); --go-progress-max only documents what that scale means, and
   * --go-progress-goal positions the tick. Declared here so they exist as real
   * custom properties rather than only in a comment. */
  --go-progress-max: 400;
  --go-progress-width: 0%;
  --go-progress-goal: 25%;
  position: relative;
  width: 100%;
  height: 8px;
  border: var(--go-border-width-hair) solid var(--go-color-line);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-surface-sunk);
  overflow: hidden;
}

.go-progress__fill {
  display: block;
  height: 100%;
  width: var(--go-progress-width, 0%);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-success);
  transition: width var(--go-duration-slow) var(--go-ease);
}

.go-progress--md { height: 12px; border-width: var(--go-border-width); }
.go-progress--lg { height: 16px; border-width: var(--go-border-width); }

.go-progress--brand  .go-progress__fill { background: var(--go-color-brand); }
.go-progress--danger .go-progress__fill { background: var(--go-color-danger); }
.go-progress--cat    .go-progress__fill { background: var(--go-cat); }

/* Goal marker. Positioned as a percentage of the track, so it stays correct
 * whatever --go-progress-max is set to. */
.go-progress--goal { overflow: visible; }
.go-progress--goal::after {
  content: "";
  position: absolute;
  top: -3px;
  bottom: -3px;
  left: var(--go-progress-goal, 25%);
  width: 2px;
  background: var(--go-color-ink);
  opacity: 0.55;
  border-radius: 1px;
}

/* Stat line under a progress bar. */
.go-progress-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--go-space-2);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  color: var(--go-color-ink-subtle);
  font-variant-numeric: tabular-nums;
}
.go-progress-meta strong { color: var(--go-color-ink); font-weight: var(--go-weight-extrabold); }

/* --- price ---------------------------------------------------------------
 * Prices are the most alignment-sensitive text in the product: they sit in a
 * right-aligned column, so they are always tabular and always right-aligned.
 * ------------------------------------------------------------------------ */

.go-price {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0;
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.go-price__now {
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-snug);
  color: var(--go-color-ink);
}

.go-price__was {
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  font-weight: var(--go-weight-medium);
  color: var(--go-color-ink-subtle);
  text-decoration: line-through;
}

.go-price--lg .go-price__now {
  font-size: var(--go-text-xl);
  line-height: var(--go-leading-xl);
}
.go-price--inline { flex-direction: row; align-items: baseline; gap: var(--go-space-2); }

/* Discount flag. */
.go-discount {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding-inline: var(--go-space-2);
  border: var(--go-border-width-hair) solid var(--go-color-line);
  border-radius: var(--go-radius-xs);
  background: var(--go-coral-500);
  color: var(--go-white);
  font-size: var(--go-text-2xs);
  line-height: 1;
  font-weight: var(--go-weight-black);
  font-variant-numeric: tabular-nums;
  flex: none;
}
.go-discount--brand { background: var(--go-color-brand); color: var(--go-color-on-brand); }

/* Delta: a signed change. */
.go-delta {
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-bold);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.go-delta--down { color: var(--go-color-success-ink); }
.go-delta--up { color: var(--go-color-danger-ink); }

/* --- stat tiles ----------------------------------------------------------
 * A row of figures. Each cell is the same height because the label and value
 * line boxes are fixed, not content-derived.
 * ------------------------------------------------------------------------ */

.go-stats {
  display: flex;
  flex-wrap: wrap;
  border: var(--go-border);
  border-radius: var(--go-radius-lg);
  background: var(--go-color-surface);
  overflow: hidden;
}

.go-stat {
  flex: 1 1 160px;
  min-width: 0;
  padding: var(--go-space-3) var(--go-space-4);
  border-right: var(--go-border-width-hair) solid var(--go-color-line-soft);
}
.go-stat:last-child { border-right: 0; }

.go-stat__label {
  font-size: var(--go-text-2xs);
  line-height: var(--go-leading-2xs);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-caps);
  text-transform: uppercase;
  color: var(--go-color-ink-subtle);
  margin-bottom: var(--go-space-1);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.go-stat__value {
  display: flex;
  align-items: baseline;
  gap: var(--go-space-2);
  font-size: var(--go-text-xl);
  line-height: var(--go-leading-xl);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-snug);
  font-variant-numeric: tabular-nums;
}

.go-stat__delta { font-size: var(--go-text-xs); font-weight: var(--go-weight-semibold); }

/* --- sparkline ----------------------------------------------------------- */

.go-spark {
  display: block;
  width: var(--go-spark-w, 72px);
  height: var(--go-spark-h, 24px);
  flex: none;
  overflow: visible;
}
.go-spark path,
.go-spark polyline {
  fill: none;
  stroke: var(--go-color-ink-subtle);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.go-spark--down path, .go-spark--down polyline { stroke: var(--go-color-success); }
.go-spark--up path, .go-spark--up polyline { stroke: var(--go-color-danger); }

/* --- skeleton ------------------------------------------------------------
 * Placeholder heights are line-heights and control heights, so a loading page
 * occupies exactly the same grid rows as the loaded page and nothing jumps.
 * ------------------------------------------------------------------------ */

.go-skeleton {
  display: block;
  border-radius: var(--go-radius-xs);
  background: linear-gradient(
    90deg,
    var(--go-sand-200) 25%,
    var(--go-sand-300) 37%,
    var(--go-sand-200) 63%
  );
  background-size: 400% 100%;
  animation: go-shimmer 1.4s ease infinite;
}
.go-skeleton--text  { height: var(--go-leading-md); }
.go-skeleton--text-sm { height: var(--go-leading-sm); }
.go-skeleton--title { height: var(--go-leading-lg); }
.go-skeleton--control { height: var(--go-control-h-md); border-radius: var(--go-radius-pill); }
.go-skeleton--thumb { width: 36px; height: 48px; border-radius: var(--go-radius-sm); }
.go-skeleton--circle { border-radius: 50%; }

@keyframes go-shimmer {
  0%   { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}
@media (prefers-reduced-motion: reduce) {
  .go-skeleton { animation: none; }
}

/* ==== 21-feedback.css =================================================== */
/* ============================================================================
 * Feedback — callout, empty state, toolbar, section header, toast
 * ========================================================================== */

/* --- callout / alert -----------------------------------------------------
 * The icon sits in a fixed 24px slot at the top, aligned to the first line of
 * the title, so a one-line and a three-line callout both look deliberate.
 * ------------------------------------------------------------------------ */

.go-callout {
  display: flex;
  align-items: flex-start;
  gap: var(--go-space-3);
  padding: calc(var(--go-space-4) - var(--go-border-width));
  border: var(--go-border);
  border-radius: var(--go-radius-lg);
  background: var(--go-color-surface);
  min-width: 0;
}

.go-callout__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: var(--go-icon-lg);
  height: var(--go-leading-lg);   /* aligns to the title's line box, not the top */
}

.go-callout__body { flex: 1 1 auto; min-width: 0; }

.go-callout__title {
  font-size: var(--go-text-md);
  line-height: var(--go-leading-md);
  font-weight: var(--go-weight-bold);
  color: var(--go-color-ink);
}

.go-callout__text {
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  color: var(--go-color-ink-muted);
}
.go-callout__title + .go-callout__text { margin-top: var(--go-space-1); }

.go-callout__actions { margin-top: var(--go-space-3); }

.go-callout--info    { background: var(--go-color-info-surface); }
.go-callout--success { background: var(--go-color-success-surface); }
.go-callout--warning { background: var(--go-color-warning-surface); }
.go-callout--danger  { background: var(--go-color-danger-surface); }
.go-callout--brand   { background: var(--go-color-brand); box-shadow: var(--go-shadow-md); }

/* --- empty state --------------------------------------------------------- */

.go-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--go-space-3);
  padding: var(--go-space-10) var(--go-space-5);
  text-align: center;
  border: var(--go-border-width) dashed var(--go-color-line-medium);
  border-radius: var(--go-radius-lg);
  background: var(--go-color-surface);
  min-height: 200px;
}
.go-empty__title {
  font-size: var(--go-text-lg);
  line-height: var(--go-leading-lg);
  font-weight: var(--go-weight-extrabold);
  letter-spacing: var(--go-tracking-snug);
}
.go-empty__text {
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  color: var(--go-color-ink-subtle);
  max-width: 44ch;
}

/* --- toolbar -------------------------------------------------------------
 * A row of controls with a result count. min-height is a control height so an
 * empty toolbar does not collapse and shift the content below it.
 * ------------------------------------------------------------------------ */

.go-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--go-space-2);
  min-height: var(--go-control-h-md);
  min-width: 0;
}
.go-toolbar__count {
  margin-right: auto;
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  color: var(--go-color-ink-subtle);
}
.go-toolbar__count strong {
  color: var(--go-color-ink);
  font-weight: var(--go-weight-bold);
  font-variant-numeric: tabular-nums;
}

/* --- section header ------------------------------------------------------ */

.go-sectionhead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--go-space-4);
  margin-bottom: var(--go-space-5);
  min-width: 0;
}
.go-sectionhead__body { min-width: 0; }
.go-sectionhead__title {
  font-size: var(--go-text-3xl);
  line-height: var(--go-leading-3xl);
  font-weight: var(--go-weight-black);
  letter-spacing: var(--go-tracking-tight);
}
.go-sectionhead__text {
  margin-top: var(--go-space-1);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
  color: var(--go-color-ink-subtle);
  max-width: 60ch;
}
/* A row, not a bare box. Half of what a section header puts here is a
 * `button_to`, and a form is block-level: with no display of its own, this
 * element stacked a link and a form vertically at every width — on a desktop
 * as much as on a phone. It is a cluster for the same reason .go-cluster
 * exists: the actions are a group of controls, and one of them being a form is
 * an implementation detail of the framework, not a layout instruction.
 *
 * It wraps, because three sm buttons do not fit beside each other at 320px and
 * wrapping within the group is better than the group dropping whole. */
.go-sectionhead__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--go-space-2);
  flex: none;
}

/* Highlighted word in a title — the yellow marker from the direction. */
.go-mark {
  background: var(--go-color-brand);
  padding-inline: var(--go-space-2);
  border-radius: var(--go-radius-sm);
  box-shadow: var(--go-shadow-sm);
  /* inline-block would break the line box; this keeps the heading's leading */
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* --- live indicator ------------------------------------------------------ */

.go-live {
  display: inline-flex;
  align-items: center;
  gap: var(--go-space-2);
  height: var(--go-control-h-sm);
  padding-inline: var(--go-control-px-sm);
  border: var(--go-border);
  border-radius: var(--go-radius-pill);
  background: var(--go-color-surface);
  box-shadow: var(--go-shadow-xs);
  font-size: var(--go-text-xs);
  line-height: var(--go-leading-xs);
  font-weight: var(--go-weight-semibold);
  white-space: nowrap;
}
.go-live__dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--go-color-success);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--go-color-success) 25%, transparent);
}

/* --- toast --------------------------------------------------------------- */

.go-toast-region {
  position: fixed;
  inset: auto var(--go-space-4) var(--go-space-4) auto;
  z-index: var(--go-z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--go-space-2);
  width: min(360px, calc(100vw - var(--go-space-8)));
}

.go-toast {
  display: flex;
  align-items: flex-start;
  gap: var(--go-space-3);
  padding: var(--go-space-3) var(--go-space-4);
  border: var(--go-border);
  border-radius: var(--go-radius-md);
  background: var(--go-color-surface);
  box-shadow: var(--go-shadow-md);
  font-size: var(--go-text-sm);
  line-height: var(--go-leading-sm);
}
.go-toast--success { background: var(--go-color-success-surface); }
.go-toast--danger { background: var(--go-color-danger-surface); }

/* ==== 90-utilities.css ================================================== */
/* ============================================================================
 * Utilities
 * ----------------------------------------------------------------------------
 * Deliberately small. Utilities here exist to place components, not to style
 * them — anything visual belongs in a component. If you find yourself needing
 * a new utility to make something line up, the component is wrong.
 * ========================================================================== */

/* --- category scope ------------------------------------------------------
 * Sets --go-cat for a subtree. Every category-aware component (tile shadow,
 * hex marker, chip dot, badge, tab, progress fill) follows from this one line.
 * ------------------------------------------------------------------------ */
.go-cat-tiendas  { --go-cat: var(--go-color-cat-tiendas); }
.go-cat-video    { --go-cat: var(--go-color-cat-video); }
.go-cat-noticias { --go-cat: var(--go-color-cat-noticias); }
.go-cat-bga      { --go-cat: var(--go-color-cat-bga); }
.go-cat-crowd    { --go-cat: var(--go-color-cat-crowd); }
.go-cat-eventos  { --go-cat: var(--go-color-cat-eventos); }
.go-cat-brand    { --go-cat: var(--go-color-brand); }

/* --- display ------------------------------------------------------------- */
.go-hidden { display: none !important; }
.go-block { display: block; }
.go-inline-block { display: inline-block; }
.go-flex { display: flex; }
.go-grid-d { display: grid; }

/* --- flex helpers -------------------------------------------------------- */
.go-grow { flex: 1 1 auto; min-width: 0; }
.go-shrink-0 { flex: none; }
.go-items-start { align-items: flex-start; }
.go-items-center { align-items: center; }
.go-items-end { align-items: flex-end; }
.go-items-baseline { align-items: baseline; }
.go-justify-start { justify-content: flex-start; }
.go-justify-center { justify-content: center; }
.go-justify-end { justify-content: flex-end; }
.go-justify-between { justify-content: space-between; }
.go-wrap { flex-wrap: wrap; }
.go-nowrap { flex-wrap: nowrap; }

/* min-width:0 is the single most useful utility in this system: without it a
 * flex or grid child refuses to shrink below its content and pushes the
 * layout out of alignment. */
.go-min-0 { min-width: 0; }

/* --- gap ----------------------------------------------------------------- */
.go-gap-0 { gap: var(--go-space-0); }
.go-gap-1 { gap: var(--go-space-1); }
.go-gap-2 { gap: var(--go-space-2); }
.go-gap-3 { gap: var(--go-space-3); }
.go-gap-4 { gap: var(--go-space-4); }
.go-gap-5 { gap: var(--go-space-5); }
.go-gap-6 { gap: var(--go-space-6); }
.go-gap-8 { gap: var(--go-space-8); }

/* --- margin (block only) -------------------------------------------------
 * Only top/bottom margins are offered, and only from the scale. Inline margins
 * are not: horizontal placement is the job of a layout primitive.
 * ------------------------------------------------------------------------ */
.go-mt-0 { margin-top: var(--go-space-0); }
.go-mt-1 { margin-top: var(--go-space-1); }
.go-mt-2 { margin-top: var(--go-space-2); }
.go-mt-3 { margin-top: var(--go-space-3); }
.go-mt-4 { margin-top: var(--go-space-4); }
.go-mt-5 { margin-top: var(--go-space-5); }
.go-mt-6 { margin-top: var(--go-space-6); }
.go-mt-8 { margin-top: var(--go-space-8); }
.go-mt-auto { margin-top: auto; }
.go-mb-0 { margin-bottom: var(--go-space-0); }
.go-mb-1 { margin-bottom: var(--go-space-1); }
.go-mb-2 { margin-bottom: var(--go-space-2); }
.go-mb-3 { margin-bottom: var(--go-space-3); }
.go-mb-4 { margin-bottom: var(--go-space-4); }
.go-mb-5 { margin-bottom: var(--go-space-5); }
.go-mb-6 { margin-bottom: var(--go-space-6); }
.go-mb-8 { margin-bottom: var(--go-space-8); }

/* --- width --------------------------------------------------------------- */
.go-w-full { width: 100%; }
.go-w-auto { width: auto; }
.go-max-w-prose { max-width: 68ch; }

/* --- surface ------------------------------------------------------------- */
.go-surface { background: var(--go-color-surface); }
.go-surface-sunk { background: var(--go-color-surface-sunk); }
.go-canvas { background: var(--go-color-canvas); }
.go-bordered { border: var(--go-border); border-radius: var(--go-radius-md); }
.go-rounded { border-radius: var(--go-radius-md); }
.go-rounded-lg { border-radius: var(--go-radius-lg); }
.go-rounded-pill { border-radius: var(--go-radius-pill); }
.go-shadow { box-shadow: var(--go-shadow-md); }
.go-shadow-sm { box-shadow: var(--go-shadow-xs); }
.go-shadow-none { box-shadow: none; }

/* --- responsive visibility ----------------------------------------------- */

/* 360px is the narrowest width in common use — the Android baseline, and the
 * floor most phones sit at or above. `xs` is for the last word that has to go
 * before a bar overflows, and only that: at 361px and up everything it hides
 * comes back, so it must never be the only place something is said. It is a
 * much smaller hammer than `sm`, which starts at 760 and would strip a label
 * off a tablet with 400px of empty space beside it. */
@media (max-width: 360px) {
  .go-hide-xs { display: none !important; }
}
@media (max-width: 760px) {
  .go-hide-sm { display: none !important; }
}
@media (min-width: 761px) {
  .go-only-sm { display: none !important; }
}
@media (max-width: 1120px) {
  .go-hide-md { display: none !important; }
}

/* --- print --------------------------------------------------------------- */
@media print {
  .go-no-print { display: none !important; }
  .go-card, .go-tile, .go-panel { box-shadow: none; break-inside: avoid; }
}
