/* ================================================================
   QUÉ HAY RGV — "CARTELERA"
   Visual direction v2. Drop-in replacement for style.css.
   Product of Pragmatic Business Solutions, Rio Grande City, TX.

   AXES (independent, never forked):
     html[data-theme="valle"]   default. dense, warm, 16px root
     html[data-theme="winter"]  larger, calmer, higher contrast, 18px root
     html[data-scheme="light"|"dark"]  forced; absent = OS preference
     (legacy html[data-theme="light"|"dark"] still honoured)

   RULES GRAMMAR — rules carry meaning, they are not decoration:
     3px ink        section boundary        (the expressway)
     2px ink/mid    block boundary          (the farm road)
     1px hairline   row inside a block      (the irrigation lateral)
     1px dashed mid provisional / not yet   (the unpaved caliche road)

   NO shadows anywhere except one hard, un-blurred print offset on
   the price flash. NO border radius. NO backdrop-filter.
   ================================================================ */

/* ---------------------------------------------------------------- 1. FONTS
   Both faces are variable (wght). Subset to the Latin+Spanish set the
   product actually renders — see docs/plan/brainstorm/visual-redesign.md §9
   for the repeatable fontTools script and the byte counts.
   Metric overrides are measured from the real files so the swap is
   zero-CLS: Libre Franklin upem 1000, hhea asc 966 / desc -246 / gap 0;
   Archivo upem 1000, hhea asc 878 / desc -210 / gap 0.
   ---------------------------------------------------------------- */
@font-face{
  font-family:"Libre Franklin";
  src:url("/assets/fonts/libre-body.woff2") format("woff2");
  font-weight:400 700; font-style:normal; font-display:swap;
  ascent-override:96.6%; descent-override:24.6%; line-gap-override:0%;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2013-2014,U+2018-201A,U+201C-201E,U+2026,U+00B7,U+00BF,U+00A1;
}
@font-face{
  font-family:"Archivo";
  src:url("/assets/fonts/archivo-display.woff2") format("woff2");
  font-weight:400 900; font-style:normal; font-display:swap;
  ascent-override:87.8%; descent-override:21%; line-gap-override:0%;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2013-2014,U+2018-201A,U+201C-201E,U+2026,U+00B7,U+00BF,U+00A1;
}
/* Metric-matched fallbacks. Arial x-height 0.51855em; Libre Franklin 0.530
   -> 102.2%;  Archivo 0.526 -> 101.4%. Overrides divided by size-adjust. */
@font-face{
  font-family:"LF Fallback"; src:local("Arial"),local("Helvetica Neue"),local("Liberation Sans");
  size-adjust:102.2%; ascent-override:94.5%; descent-override:24.1%; line-gap-override:0%;
}
@font-face{
  font-family:"AR Fallback"; src:local("Arial"),local("Helvetica Neue"),local("Liberation Sans");
  size-adjust:101.4%; ascent-override:86.6%; descent-override:20.7%; line-gap-override:0%;
}

/* ---------------------------------------------------------------- 2. TOKENS
   Every value verified against WCAG 2.2. Ratios in the design doc §3.
   ---------------------------------------------------------------- */
:root{
  /* ---- valle · light (default) ---- */
  --canvas:#F4F1EA;      /* caliche */
  --raised:#FFFFFF;
  --sunken:#E7E3D8;
  --ink:#1A1814;         /* poster ink */
  --ink-2:#4E4839;
  --ink-3:#6B6555;
  --hair:#D5D0C1;
  --mid:#837B69;
  --accent:#BB2547;      /* toronja — Ruby Red grapefruit */
  --accent-hover:#96122F;
  --accent-ink:#FFFFFF;
  --accent-tint:#F6DCE3;
  --accent-on-tint:#8E1230;
  --free:#0E5A3C;        /* sabal */
  --free-ink:#FFFFFF;
  --free-tint:#D6E9DF;
  --free-on-tint:#0B4630;
  --warn:#8A5A00;
  --danger:#B3221C;
  --focus:#0B7F97;       /* resaca */
  --slab:#1A1814;        /* the always-dark band */
  --on-slab:#F4F1EA;
  --on-slab-2:#BDB7A6;
  --slab-hair:#403A2C;
  --accent-on-slab:#FF6B84;
  --free-on-slab:#3FD79A;

  /* ---- type ---- */
  --display:"Archivo","AR Fallback",Arial,sans-serif;
  --body:"Libre Franklin","LF Fallback",Arial,sans-serif;

  --t-d1:clamp(2.75rem,8.5vw,5rem);   /* hero            44 -> 80 */
  --t-d2:clamp(2rem,5vw,3.25rem);     /* section head    32 -> 52 */
  --t-d3:clamp(1.5rem,2.6vw,1.875rem);/* sub-head        24 -> 30 */
  --t-t1:1.25rem;
  --t-t2:1.0625rem;
  --t-t3:.9375rem;
  --t-body:1rem;
  --t-sm:.875rem;
  --t-meta:.8125rem;
  --t-label:.75rem;
  --t-micro:.6875rem;

  --w-display:900;      /* the poster weight */
  --w-head:800;
  --lh-d1:.86;
  --lh-d2:.94;
  --tr-d1:-.045em;
  --tr-d2:-.032em;
  --tr-label:.14em;
  --lh-body:1.55;

  /* ---- structure ---- */
  --rw:2px;             /* block rule   */
  --rw-heavy:3px;       /* section rule */
  --gut:clamp(20px,4.5vw,56px);
  --maxw:1220px;
  --measure:66ch;
  --root-size:16px;
  --knockout-pad:.02em .14em .08em;
  --flash-d:clamp(6.5rem,15vw,9.5rem);
  --flash-rotate:-8deg;
  --flash-spike:7.5deg;
  --sp:clamp(2.75rem,6vw,5.5rem);   /* section rhythm */
  --sp-tight:clamp(1.75rem,3.5vw,3rem);
}

/* ---- winter: same tokens, calmer values ---- */
:root[data-theme="winter"]{--root-size:18px;--knockout-pad:.06em .18em .12em;--flash-d:clamp(7.5rem,16vw,11rem);--flash-rotate:-3deg;--flash-spike:11.25deg;
  --canvas:#FFFFFF; --raised:#FFFFFF; --sunken:#F0EEE9;
  --ink:#101010; --ink-2:#3A362F; --ink-3:#5A5449;
  --hair:#C9C4B8; --mid:#6E6759;
  --accent:#A31739; --accent-hover:#7E0F2B; --accent-ink:#FFFFFF;
  --accent-tint:#F7DFE6; --accent-on-tint:#8C1230;
  --free:#0A4B31; --free-ink:#FFFFFF; --free-tint:#DCEDE4; --free-on-tint:#083D28;
  --warn:#6E4700; --danger:#96170F; --focus:#0B6A80;
  --slab:#101010; --on-slab:#FFFFFF; --on-slab-2:#C8C4BA; --slab-hair:#3A3A3A;
  --accent-on-slab:#FF8FA1; --free-on-slab:#5EE3AC;

  --t-d1:clamp(2.5rem,6vw,3.75rem);
  --t-d2:clamp(1.875rem,4vw,2.75rem);
  --t-d3:1.5rem;
  --t-t1:1.3333rem; --t-t2:1.1667rem; --t-t3:1rem;
  --t-body:1rem; --t-sm:.9444rem; --t-meta:.8889rem;
  --t-label:.7778rem; --t-micro:.7778rem;   /* winter has no micro tier */

  --w-display:800; --w-head:700;
  --lh-d1:1; --lh-d2:1.1;
  --tr-d1:-.015em; --tr-d2:-.01em; --tr-label:.1em;
  --lh-body:1.65;
  --rw:3px; --rw-heavy:4px;
  --measure:60ch;
  --sp:clamp(3.25rem,6.5vw,6rem);
}


/* ---- dark scheme, valle ---- */
@media (prefers-color-scheme:dark){
  :root:not([data-scheme="light"]):not([data-theme="light"]){
    --canvas:#0F1218; --raised:#171B23; --sunken:#0A0C11;
    --ink:#F2F0EA; --ink-2:#B9B4A8; --ink-3:#8E897C;
    --hair:#262C36; --mid:#6B7688;
    --accent:#FF6B84; --accent-hover:#FF97A9; --accent-ink:#2A0710;
    --accent-tint:#3E1B28; --accent-on-tint:#FF8A9E;
    --free:#3FD79A; --free-ink:#04281A; --free-tint:#103226; --free-on-tint:#4FE0A6;
    --warn:#F0B429; --danger:#FF8072; --focus:#4CC7E0;
    --slab:#05070B; --on-slab:#F2F0EA; --on-slab-2:#9C9689; --slab-hair:#242A34;
    --accent-on-slab:#FF6B84; --free-on-slab:#3FD79A;
  }
  :root[data-theme="winter"]:not([data-scheme="light"]){
    --canvas:#12141A; --raised:#1C1F27; --sunken:#0C0E13;
    --ink:#FFFFFF; --ink-2:#CFCBC1; --ink-3:#A19C90;
    --hair:#333A45; --mid:#78828F;
    --accent:#FF8FA1; --accent-hover:#FFB3BF; --accent-ink:#2A0710;
    --accent-tint:#401D27; --accent-on-tint:#FFA2B1;
    --free:#5EE3AC; --free-ink:#04281A; --free-tint:#13372A; --free-on-tint:#6FE9B5;
    --warn:#F5C458; --danger:#FF9A8E; --focus:#6FD6EA;
    --slab:#05070B; --on-slab:#FFFFFF; --on-slab-2:#B4AFA4; --slab-hair:#2A3038;
    --accent-on-slab:#FF8FA1; --free-on-slab:#5EE3AC;
  }
}
:root[data-scheme="dark"],:root[data-theme="dark"]{
  --canvas:#0F1218; --raised:#171B23; --sunken:#0A0C11;
  --ink:#F2F0EA; --ink-2:#B9B4A8; --ink-3:#8E897C;
  --hair:#262C36; --mid:#6B7688;
  --accent:#FF6B84; --accent-hover:#FF97A9; --accent-ink:#2A0710;
  --accent-tint:#3E1B28; --accent-on-tint:#FF8A9E;
  --free:#3FD79A; --free-ink:#04281A; --free-tint:#103226; --free-on-tint:#4FE0A6;
  --warn:#F0B429; --danger:#FF8072; --focus:#4CC7E0;
  --slab:#05070B; --on-slab:#F2F0EA; --on-slab-2:#9C9689; --slab-hair:#242A34;
  --accent-on-slab:#FF6B84; --free-on-slab:#3FD79A;
}
:root[data-theme="winter"][data-scheme="dark"]{
  --canvas:#12141A; --raised:#1C1F27; --sunken:#0C0E13;
  --ink:#FFFFFF; --ink-2:#CFCBC1; --ink-3:#A19C90;
  --hair:#333A45; --mid:#78828F;
  --accent:#FF8FA1; --accent-hover:#FFB3BF; --accent-ink:#2A0710;
  --accent-tint:#401D27; --accent-on-tint:#FFA2B1;
  --free:#5EE3AC; --free-ink:#04281A; --free-tint:#13372A; --free-on-tint:#6FE9B5;
  --warn:#F5C458; --danger:#FF9A8E; --focus:#6FD6EA;
  --slab:#05070B; --on-slab:#FFFFFF; --on-slab-2:#B4AFA4; --slab-hair:#2A3038;
  --accent-on-slab:#FF8FA1; --free-on-slab:#5EE3AC;
}

/* ---------------------------------------------------------------- 3. BASE */
*,*::before,*::after{box-sizing:border-box}
html{font-size:var(--root-size);-webkit-text-size-adjust:100%;scroll-padding-top:5rem}
body{
  margin:0;background:var(--canvas);color:var(--ink);
  font-family:var(--body);font-size:var(--t-body);line-height:var(--lh-body);
  font-synthesis-weight:none;
  /* NO -webkit-font-smoothing: it thins type on the low-DPI Android we target */
}
img,svg{max-width:100%;display:block}
a{color:var(--accent);text-underline-offset:.18em;text-decoration-thickness:.08em}
p{margin:0 0 .9em}
ul,ol{margin:0 0 1em;padding-left:1.25rem}
li{margin:0 0 .4em}
li::marker{color:var(--mid)}
strong,b{font-weight:600;color:var(--ink)}
::selection{background:var(--accent);color:var(--accent-ink)}

/* Focus: a double ring. The canvas-coloured spacer guarantees >=3:1 against
   whatever the control is filled with, and the outer ring is measured against
   the canvas. This is the only construction that survives a focus landing on a
   filled accent button. */
:focus-visible{
  outline:none;
  box-shadow:0 0 0 2px var(--canvas),0 0 0 5px var(--focus);
  position:relative;z-index:2;
}
.band.ink :focus-visible,footer :focus-visible,.langbar :focus-visible,.board :focus-visible{
  box-shadow:0 0 0 2px var(--slab),0 0 0 5px var(--focus);
}
.cartel :focus-visible{box-shadow:0 0 0 2px var(--accent-ink),0 0 0 5px var(--slab)}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--gut)}
.narrow{max-width:56rem}
.skip{position:absolute;left:-9999px}
.skip:focus{left:.75rem;top:.75rem;z-index:200;background:var(--slab);color:var(--on-slab);padding:.7rem 1.1rem}

/* ---------------------------------------------------------------- 4. TYPE */
h1,h2,h3,h4{font-family:var(--display);margin:0 0 .5em;text-wrap:pretty}
h1{
  font-weight:var(--w-display);font-size:var(--t-d1);
  line-height:var(--lh-d1);letter-spacing:var(--tr-d1);
  margin:0 0 .35em;text-wrap:balance;
}
/* THE DISPLAY TREATMENT. The accent word is knocked out of a solid field of
   toronja — the hand-painted price/headline block off a dance poster. It is
   the one place a big area of colour lands, and it costs nothing. */
h1 em,h2 em{
  font-style:normal;
  background:var(--accent);color:var(--accent-ink);
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
  padding:var(--knockout-pad);
  margin-left:-.05em;
}

h2{
  font-weight:var(--w-display);font-size:var(--t-d2);
  line-height:var(--lh-d2);letter-spacing:var(--tr-d2);
  margin:0 0 .4em;text-wrap:balance;
}
h3{font-weight:var(--w-head);font-size:var(--t-t1);line-height:1.2;letter-spacing:-.012em;margin:0 0 .35em}
h4{font-weight:var(--w-head);font-size:var(--t-t2);line-height:1.25;letter-spacing:-.008em}

/* the small caps label — used everywhere, always in the display face */
.kicker,.eyebrow,.card .meta,.cartel .k,.stats span,.fcol h2,label,
thead th,.step .n,.tier .badge,.legal .toc h2,.indice .sub,.glance dt{
  font-family:var(--display);font-weight:800;
  font-size:var(--t-label);letter-spacing:var(--tr-label);
  text-transform:uppercase;line-height:1.2;
}
/* every number in the product is set in Archivo, because the shipped
   Libre Franklin subset carries no `tnum` and tabular-nums is a no-op in it */
.stats b,.tier .price,.flash,.indice .no,.season b,td.num,.ledger b{
  font-family:var(--display);font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
}
.lede{
  font-size:clamp(1.0625rem,2.1vw,1.375rem);line-height:1.4;
  font-weight:500;color:var(--ink);margin:0 0 .7em;max-width:32ch;
}
.sub{font-size:var(--t-t2);color:var(--ink-2);max-width:52ch;margin:0 0 1.4em;line-height:1.55}
.prose{max-width:var(--measure)}
.prose p,.prose li{color:var(--ink-2)}
.prose h3{margin-top:1.6em}

/* ---------------------------------------------------------------- 5. LANGBAR */
.langbar{background:var(--slab);color:var(--on-slab);font-size:var(--t-sm);display:none;
  border-bottom:var(--rw) solid var(--accent)}
.langbar.on{display:block}
.langbar .wrap{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap;padding-top:.6rem;padding-bottom:.6rem}
.langbar p{margin:0;flex:1 1 16rem}
.langbar a{
  color:var(--slab);background:var(--on-slab);text-decoration:none;
  font-family:var(--display);font-weight:800;font-size:var(--t-label);
  letter-spacing:.06em;text-transform:uppercase;padding:.45rem .9rem;white-space:nowrap;
}
.langbar button{
  background:none;border:1px solid var(--slab-hair);color:var(--on-slab-2);
  font:inherit;font-size:var(--t-sm);padding:.4rem .8rem;cursor:pointer;
}
.langbar button:hover{color:var(--on-slab);border-color:var(--on-slab-2)}

/* ---------------------------------------------------------------- 6. HEADER */
.topbar{
  position:sticky;top:0;z-index:100;
  background:var(--canvas);                 /* solid: no backdrop-filter */
  border-bottom:var(--rw-heavy) solid var(--ink);
}
.topbar .wrap{display:flex;align-items:center;gap:1.1rem;padding-top:.7rem;padding-bottom:.7rem}
/* .brand / .mark / .rgv are owned by the logo designer — untouched */
.brand{display:flex;align-items:center;gap:.55rem;text-decoration:none;color:var(--ink);flex:none}

nav.main{display:flex;gap:0;margin-left:auto;align-items:stretch}
nav.main a{
  font-family:var(--display);font-weight:700;font-size:var(--t-t3);
  letter-spacing:-.005em;color:var(--ink-2);text-decoration:none;
  padding:.55rem .7rem;white-space:nowrap;
  border-bottom:var(--rw-heavy) solid transparent;margin-bottom:calc(-1 * var(--rw-heavy));
  display:flex;align-items:center;
}
nav.main a:hover{color:var(--ink);border-bottom-color:var(--mid)}
nav.main a[aria-current="page"]{color:var(--ink);border-bottom-color:var(--accent)}
.langsw{display:flex;border:var(--rw) solid var(--ink);flex:none;align-self:center}
.langsw a{
  font-family:var(--display);font-weight:800;font-size:var(--t-micro);letter-spacing:.08em;
  padding:.3rem .55rem;text-decoration:none;color:var(--ink);background:transparent;line-height:1.4;
}
.langsw a[aria-current="true"]{background:var(--ink);color:var(--canvas)}
.navtoggle{
  display:none;margin-left:auto;background:none;border:var(--rw) solid var(--ink);
  padding:.5rem .65rem;cursor:pointer;color:var(--ink);
}
.navtoggle span{display:block;width:1.05rem;height:2px;background:currentColor;margin:.2rem 0}
@media (max-width:60rem){
  .navtoggle{display:block}
  nav.main{
    display:none;position:absolute;top:100%;left:0;right:0;
    background:var(--canvas);border-bottom:var(--rw-heavy) solid var(--ink);
    flex-direction:column;align-items:stretch;padding:0 var(--gut) .75rem;margin-left:0;
  }
  nav.main.open{display:flex}
  nav.main a{
    padding:.85rem 0;font-size:var(--t-t2);
    border-bottom:1px solid var(--hair);margin-bottom:0;
    border-left:var(--rw-heavy) solid transparent;padding-left:.7rem;
  }
  nav.main a[aria-current="page"]{border-left-color:var(--accent);border-bottom-color:var(--hair)}
  .topbar .wrap{position:relative}
}

/* ---------------------------------------------------------------- 7. BUTTONS */
.btn{
  font-family:var(--display);font-weight:800;font-size:var(--t-t3);
  letter-spacing:.01em;line-height:1.15;
  padding:.8rem 1.3rem;text-decoration:none;border:var(--rw) solid transparent;
  display:inline-flex;align-items:center;justify-content:center;gap:.5rem;cursor:pointer;
  min-width:0;text-align:center;
  transition:background-color .12s linear,border-color .12s linear,color .12s linear;
}
.btn.primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.btn.primary:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
.btn.ghost{background:transparent;color:var(--ink);border-color:var(--ink)}
.btn.ghost:hover{background:var(--ink);color:var(--canvas)}
.btn.light{background:var(--on-slab);color:var(--slab);border-color:var(--on-slab)}
.btn.light:hover{background:transparent;color:var(--on-slab)}
.btn.sm{font-size:var(--t-label);padding:.55rem .95rem;letter-spacing:.04em;text-transform:uppercase}
.cta-row{display:flex;flex-wrap:wrap;gap:.7rem;align-items:stretch}

/* ---------------------------------------------------------------- 8. HERO */
.hero{
  background:var(--canvas);
  border-bottom:var(--rw-heavy) solid var(--ink);
  position:relative;overflow:hidden;
}
.hero .wrap{padding-top:var(--sp-tight);padding-bottom:var(--sp)}
.herogrid{
  display:grid;grid-template-columns:minmax(0,6fr) minmax(0,5fr);
  gap:clamp(1.75rem,4vw,3.5rem);align-items:end;
}
@media (max-width:56rem){.herogrid{grid-template-columns:minmax(0,1fr);gap:2rem;align-items:start}}

/* the eyebrow is a ruled slab label, not a pill */
.eyebrow{
  display:flex;align-items:center;gap:.6rem;
  color:var(--ink-2);margin:0 0 1.3rem;padding:0 0 .55rem;
  border-bottom:1px solid var(--hair);
}
.eyebrow::before{
  content:"";width:1.6rem;height:var(--rw-heavy);background:var(--accent);flex:none;
}
.hero .lede{margin-top:1rem}
.geopick{margin:0 0 1.2rem;display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}
.geopick label{display:inline;margin:0}
.geopick select{width:auto;min-width:11rem;margin:0;padding:.45rem .6rem;font-size:var(--t-t3)}

/* interior page header */
.phead{background:var(--canvas);border-bottom:var(--rw-heavy) solid var(--ink)}
.phead .wrap{padding-top:1rem;padding-bottom:var(--sp-tight)}
.phead h1{font-size:var(--t-d2);margin-bottom:.5em}
.phead .sub{margin-bottom:0;max-width:58ch}
.crumbs{
  font-family:var(--display);font-weight:700;
  font-size:var(--t-micro);letter-spacing:.09em;text-transform:uppercase;
  color:var(--ink-3);margin:0 0 1.5rem;display:flex;flex-wrap:wrap;gap:.45rem;
  padding-bottom:.6rem;border-bottom:1px solid var(--hair);
}
.crumbs a{color:var(--ink-3);text-decoration:none}
.crumbs a:hover{color:var(--accent)}
.crumbs span[aria-hidden]{color:var(--mid)}

/* ---------------------------------------------------------------- 9. CARTEL
   The flyer-absent panel. This is a poster, not a jumbotron: a solid field of
   toronja, square corners, a hard un-blurred registration offset in ink, and a
   knockout header bar. It is honest — it says "your flyer goes here" — so it
   never pretends to be a real event. */
.cartel{
  background:var(--accent);color:var(--accent-ink);
  padding:clamp(1.4rem,2.6vw,2.2rem);
  position:relative;
  box-shadow:8px 8px 0 var(--slab);
  isolation:isolate;
}
@media (max-width:56rem){.cartel{box-shadow:5px 5px 0 var(--slab)}}
/* screenprint register band across the top — one gradient, zero bytes of image */
.cartel::before{
  content:"";position:absolute;left:0;right:0;top:0;height:.5rem;
  background:repeating-linear-gradient(90deg,
    var(--slab) 0 1.25rem,transparent 1.25rem 2.5rem);
  opacity:.85;
}
.cartel .k{
  display:inline-block;background:var(--accent-ink);color:var(--accent);
  padding:.3rem .6rem;margin:.9rem 0 1.1rem;
}
.cartel .t{
  font-family:var(--display);font-weight:var(--w-display);
  font-size:clamp(1.75rem,4.2vw,2.75rem);line-height:var(--lh-d1);
  letter-spacing:var(--tr-d1);margin:0 0 .5em;text-wrap:balance;
}
.cartel .d{font-size:var(--t-t3);margin:0 0 1.2rem;line-height:1.5;max-width:38ch}
.cartel .meta{
  display:flex;flex-wrap:wrap;gap:0;
  border-top:var(--rw) solid var(--accent-ink);padding-top:.85rem;
}
.cartel .meta span{
  font-family:var(--display);font-weight:800;font-size:var(--t-label);
  letter-spacing:.08em;text-transform:uppercase;
  padding:.25rem .85rem;border-right:1px solid var(--accent-ink);
}
.cartel .meta span:first-child{padding-left:0}
.cartel .meta span:last-child{border-right:0}

/* ---------------------------------------------------------------- 10. SECTIONS */
section{padding:var(--sp) 0}
section.tight{padding:var(--sp-tight) 0}
.band{background:var(--sunken);border-top:var(--rw) solid var(--mid);border-bottom:var(--rw) solid var(--mid)}
.band.ink{background:var(--slab);border-color:var(--slab);color:var(--on-slab)}
.band.ink h2,.band.ink h3,.band.ink h4{color:var(--on-slab)}
.band.ink p,.band.ink .sub{color:var(--on-slab-2)}
.band.ink .kicker{color:var(--accent-on-slab)}
.band.ink a{color:var(--accent-on-slab)}
.band.ink h2 em{background:var(--accent-on-slab);color:var(--slab)}

/* THE SECTION HEAD — the mile marker. A heavy rule, then a caps label whose
   hairline runs out to the full page width, then the head. This is what makes
   a page read as a board rather than a stack of marketing slabs, and it works
   with the markup gen.py already emits. */
.sec-head{margin:0 0 var(--sp-tight);max-width:none;border-top:var(--rw-heavy) solid var(--ink);padding-top:.9rem}
.band.ink .sec-head{border-top-color:var(--on-slab)}
.sec-head > h2{max-width:22ch}
.sec-head > p:not(.kicker){font-size:var(--t-t2);color:var(--ink-2);margin:0;max-width:52ch}
.sec-head.center{text-align:center}
h2.kicker{font-size:var(--t-meta);font-weight:inherit;letter-spacing:inherit}
.kicker{
  color:var(--accent);margin:0 0 1rem;
  display:flex;align-items:center;gap:.75rem;
}
.kicker::after{content:"";flex:1;height:1px;background:var(--hair)}
.band.ink .kicker::after{background:var(--slab-hair)}
/* a section head that carries a right-hand element (a link, the flash) */
.sec-head.split{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:1.5rem;align-items:end}
.sec-head.split .kicker{grid-column:1/-1}
@media (max-width:44rem){.sec-head.split{grid-template-columns:minmax(0,1fr)}}

/* ---------------------------------------------------------------- 11. GRIDS + CARDS */
.grid{display:grid;gap:0}
.g2{grid-template-columns:repeat(auto-fit,minmax(min(19rem,100%),1fr))}
.g3{grid-template-columns:repeat(auto-fit,minmax(min(16rem,100%),1fr))}
.g4{grid-template-columns:repeat(auto-fit,minmax(min(13rem,100%),1fr))}
/* cards butt against each other and share rules — a board, not floating tiles */
.card{
  background:var(--raised);
  border-right:1px solid var(--hair);border-bottom:1px solid var(--hair);
  border-top:var(--rw-heavy) solid var(--ink);
  padding:1.3rem 1.25rem 1.5rem;
  transition:background-color .12s linear,border-top-color .12s linear;
}
.band .card{background:var(--raised)}
a.card{text-decoration:none;color:inherit;display:block;position:relative}
a.card:hover,a.card:focus-visible{border-top-color:var(--accent);background:var(--accent-tint)}
.card h2,.card h3{margin-bottom:.4em;letter-spacing:-.018em}
.card p{color:var(--ink-2);font-size:var(--t-sm);margin:0;line-height:1.5}
.card .meta{color:var(--ink-3);margin:0 0 .7rem;display:block}
/* the arrow "Learn more ->" span is redundant with a whole-card link: it is
   hidden from sight but kept in the DOM for screen readers until gen.py drops it */
.card .more{
  display:block;margin-top:1rem;
  font-family:var(--display);font-weight:800;font-size:var(--t-micro);
  letter-spacing:.12em;text-transform:uppercase;color:var(--accent);
}

/* numbered steps — a ruled ledger */
.steps{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(16rem,100%),1fr));
  gap:0;border-top:var(--rw-heavy) solid var(--ink);
}
.step{
  background:transparent;padding:1.2rem 1.4rem 1.6rem 0;
  border-right:1px solid var(--hair);
}
.step:last-child{border-right:0}
@media (max-width:52rem){
  .step{border-right:0;border-bottom:1px solid var(--hair);padding:1.1rem 0 1.3rem}
  .step:last-child{border-bottom:0}
}
.step .n{
  color:var(--accent);margin:0 0 .8rem;font-size:1.5rem;
  font-family:var(--display);font-weight:900;letter-spacing:-.03em;
  font-variant-numeric:tabular-nums;text-transform:none;
}
.step h3{font-size:var(--t-t2)}
.step p{margin:0;color:var(--ink-2);font-size:var(--t-sm);line-height:1.5}

/* ---------------------------------------------------------------- 12. CHIPS
   Hard-edged tabs with a meaning-bearing left bar. No pills anywhere. */
.chips{display:flex;flex-wrap:wrap;gap:.4rem}
.chip{
  font-family:var(--display);font-weight:700;font-size:var(--t-t3);
  letter-spacing:-.005em;line-height:1.3;
  padding:.5rem .8rem;
  border:1px solid var(--hair);border-left:var(--rw-heavy) solid var(--mid);
  background:var(--raised);color:var(--ink);text-decoration:none;display:inline-block;
  transition:border-left-color .12s linear,background-color .12s linear;
}
a.chip:hover,a.chip:focus-visible{border-left-color:var(--accent);background:var(--accent-tint)}
.chip.free{border-left-color:var(--free);background:var(--free-tint);color:var(--free-on-tint)}
a.chip.free:hover{border-left-color:var(--free);background:var(--free-tint)}
.chip.hot{border-left-color:var(--accent);background:var(--accent-tint);color:var(--accent-on-tint)}

/* ---------------------------------------------------------------- 13. STATS / LEDGER */
.stats,.ledger{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(9rem,100%),1fr));gap:0;
  border-top:var(--rw-heavy) solid currentColor;
}
.stats > div,.ledger > div{
  padding:1rem 1.1rem 1.2rem 0;border-right:1px solid var(--hair);
}
.stats > div:last-child,.ledger > div:last-child{border-right:0}
.band.ink .stats > div{border-right-color:var(--slab-hair)}
.stats b,.ledger b{
  display:block;font-weight:900;font-size:clamp(1.75rem,3.4vw,2.5rem);
  letter-spacing:-.035em;line-height:1;
}
.stats span,.ledger span{display:block;color:var(--ink-3);margin-top:.5rem;max-width:16ch}
.band.ink .stats span{color:var(--on-slab-2)}

/* ---------------------------------------------------------------- 14. NOTE
   dashed = provisional. This is the honest "not launched yet" voice, made
   into a rule the reader can learn. */
.note{
  background:transparent;border:1px dashed var(--mid);border-left:var(--rw-heavy) solid var(--accent);
  padding:1rem 1.1rem;margin:1.5rem 0;font-size:var(--t-sm);color:var(--ink-2);
}
.note.palm{border-left-color:var(--free)}
.note p:last-child{margin-bottom:0}
.note strong{color:var(--ink)}

/* ---------------------------------------------------------------- 15. PRICING */
.tiers{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(16rem,100%),1fr));gap:0;
  align-items:stretch;border-top:var(--rw-heavy) solid var(--ink);
  border-bottom:1px solid var(--hair);
}
.tier{
  background:var(--raised);border-right:1px solid var(--hair);
  padding:1.4rem 1.3rem 1.6rem;display:flex;flex-direction:column;
}
.tier:last-child{border-right:0}
.tier.feat{background:var(--accent-tint);outline:var(--rw) solid var(--accent);outline-offset:calc(-1 * var(--rw))}
.tier .badge{
  color:var(--accent-ink);background:var(--accent);padding:.25rem .6rem;
  align-self:flex-start;margin:0 0 .8rem;display:inline-block;
}
.tier h2,.tier h3{font-size:var(--t-t1);margin-bottom:.15em}
.tier .who{font-size:var(--t-meta);color:var(--ink-3);margin:0 0 1.1rem;min-height:3.2em;line-height:1.4}
.tier .price{
  font-weight:900;font-size:clamp(2.5rem,5vw,3.5rem);letter-spacing:-.05em;
  line-height:.9;margin:0 0 .2rem;
}
.tier .price small{font-size:var(--t-t2);font-weight:700;color:var(--ink-3);letter-spacing:0}
.tier .per{font-size:var(--t-meta);color:var(--ink-3);margin:0 0 1.2rem;padding-bottom:1rem;border-bottom:1px solid var(--hair)}
.tier ul{list-style:none;padding:0;margin:0 0 1.4rem;flex:1}
.tier li{
  position:relative;padding:.5rem 0 .5rem 1.4rem;margin:0;
  font-size:var(--t-sm);color:var(--ink-2);line-height:1.45;
  border-bottom:1px solid var(--hair);
}
.tier li:last-child{border-bottom:0}
.tier li::before{
  content:"";position:absolute;left:0;top:.95em;width:.55rem;height:.3rem;
  border-left:var(--rw) solid var(--free);border-bottom:var(--rw) solid var(--free);
  transform:rotate(-45deg);
}
.tier.feat .who,.tier.feat .per{color:var(--ink-2)}
.tier .btn{width:100%}

/* ---------------------------------------------------------------- 16. TABLE */
.tablewrap{overflow-x:auto;border-top:var(--rw-heavy) solid var(--ink);background:transparent;margin:1.5rem 0}
table{width:100%;border-collapse:collapse;font-size:var(--t-sm);min-width:34rem}
thead th{
  text-align:left;color:var(--ink-3);padding:.75rem 1rem .75rem 0;
  border-bottom:var(--rw) solid var(--mid);white-space:nowrap;vertical-align:bottom;
}
tbody td{padding:.75rem 1rem .75rem 0;border-bottom:1px solid var(--hair);vertical-align:top;color:var(--ink-2)}
tbody tr:last-child td{border-bottom:0}
tbody td:first-child{color:var(--ink);font-weight:600;font-family:var(--display)}
td.num{text-align:right;padding-right:0}
tbody tr:hover td{background:var(--sunken)}

/* ---------------------------------------------------------------- 17. FORMS */
.formcard{
  background:var(--raised);border:1px solid var(--hair);
  border-top:var(--rw-heavy) solid var(--ink);
  padding:clamp(1.25rem,3vw,2rem);
}
.formcard h2,.formcard h3{font-size:var(--t-d3);font-weight:var(--w-display);letter-spacing:var(--tr-d2)}
.formcard > p{color:var(--ink-2);font-size:var(--t-sm);margin:0 0 1.4rem}
label{display:block;color:var(--ink-2);margin:0 0 .35rem}
input[type=text],input[type=email],input[type=tel],select,textarea{
  width:100%;font-family:var(--body);font-size:1.0625rem;color:var(--ink);
  background:var(--canvas);border:var(--rw) solid var(--mid);
  padding:.7rem .75rem;margin:0 0 1rem;line-height:1.4;
  border-radius:0;-webkit-appearance:none;appearance:none;
}
select{
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 1.1rem) 55%,calc(100% - .75rem) 55%;
  background-size:.36rem .36rem,.36rem .36rem;background-repeat:no-repeat;
  padding-right:2.2rem;
}
input:focus,select:focus,textarea:focus{border-color:var(--ink)}
input::placeholder,textarea::placeholder{color:var(--ink-3);opacity:1}
.consent{
  display:flex;gap:.7rem;align-items:flex-start;
  background:var(--sunken);border-left:var(--rw-heavy) solid var(--mid);
  padding:.85rem .9rem;margin:.25rem 0 1.2rem;
}
.consent input{margin:.2rem 0 0;width:1.2rem;height:1.2rem;flex:none;accent-color:var(--accent)}
.consent p{margin:0;font-size:var(--t-meta);line-height:1.45;color:var(--ink-2)}
.formnote{font-size:var(--t-meta);color:var(--ink-3);margin:.9rem 0 0;line-height:1.45}
.msg{margin:1rem 0 0;padding:.75rem .9rem;font-size:var(--t-sm);display:none;border-left:var(--rw-heavy) solid}
.msg.ok{display:block;background:var(--free-tint);color:var(--free-on-tint);border-left-color:var(--free)}
.msg.err{display:block;background:var(--accent-tint);color:var(--accent-on-tint);border-left-color:var(--danger)}

/* ---------------------------------------------------------------- 18. FAQ */
.faq{border-top:var(--rw-heavy) solid var(--ink);max-width:var(--measure)}
.faq details{border-bottom:1px solid var(--hair)}
.faq summary{
  cursor:pointer;list-style:none;padding:1rem 2.2rem 1rem 0;position:relative;
  font-family:var(--display);font-weight:var(--w-head);font-size:var(--t-t2);
  color:var(--ink);letter-spacing:-.01em;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"";position:absolute;right:0;top:1.15rem;width:.85rem;height:.85rem;
  background:
    linear-gradient(var(--accent),var(--accent)) center/100% 2px no-repeat,
    linear-gradient(var(--accent),var(--accent)) center/2px 100% no-repeat;
  transition:background-size .16s linear;
}
.faq details[open] summary::after{background-size:100% 2px,2px 0}
.faq details[open] summary{color:var(--accent)}
.faq .a{padding:0 0 1.2rem;color:var(--ink-2);font-size:var(--t-sm);max-width:58ch}
.faq .a p:last-child{margin-bottom:0}

/* ---------------------------------------------------------------- 19. LEGAL */
.legal{max-width:70ch;padding:1.5rem 0 var(--sp)}
.legal .updated{color:var(--ink-3);font-size:var(--t-meta);margin:0 0 .5rem;
  font-family:var(--display);font-weight:700;letter-spacing:.06em;text-transform:uppercase}
.legal h2{font-size:var(--t-d3);margin:2.5rem 0 .6em;padding-top:1.1rem;border-top:var(--rw) solid var(--ink)}
.legal h3{font-size:var(--t-t2);margin:1.6rem 0 .4em}
.legal p,.legal li{color:var(--ink-2)}
.legal .box{background:var(--sunken);border-left:var(--rw-heavy) solid var(--accent);padding:1rem 1.1rem;margin:1.4rem 0}
.legal .box p{font-size:var(--t-sm);margin-bottom:.6em}
.legal .box p:last-child{margin-bottom:0}
.legal .toc{border-top:var(--rw-heavy) solid var(--ink);border-bottom:1px solid var(--hair);padding:1rem 0 .6rem;margin:0 0 2.2rem}
.legal .toc h2{color:var(--ink-3);margin:0 0 .8rem;border:0;padding:0;font-size:var(--t-label)}
.legal .toc ol{columns:2;column-gap:2rem;list-style:none;padding:0;margin:0;font-size:var(--t-meta)}
.legal .toc li{break-inside:avoid;margin-bottom:.3rem}
.legal .toc a{color:var(--ink-2);text-decoration:none}
.legal .toc a:hover{color:var(--accent);text-decoration:underline}
@media (max-width:40rem){.legal .toc ol{columns:1}}

/* ---------------------------------------------------------------- 20. FOOTER */
footer{background:var(--slab);color:var(--on-slab);padding:var(--sp-tight) 0 1.5rem;border-top:var(--rw-heavy) solid var(--accent)}
footer a{color:var(--on-slab-2);text-decoration:none}
footer a:hover{color:var(--on-slab);text-decoration:underline}
.fgrid{display:grid;grid-template-columns:minmax(0,1.5fr) repeat(4,minmax(0,1fr));gap:0}
.fgrid > *{padding:0 1.25rem;border-right:1px solid var(--slab-hair)}
.fgrid > *:first-child{padding-left:0}
.fgrid > *:last-child{border-right:0}
@media (max-width:64rem){
  .fgrid{grid-template-columns:repeat(3,minmax(0,1fr));row-gap:2rem}
  .fgrid > *{padding-left:1.25rem}
  .fgrid > *:first-child{grid-column:1/-1;padding-left:0;border-right:0;padding-bottom:1.5rem;border-bottom:1px solid var(--slab-hair)}
  .fgrid > *:nth-child(4){padding-left:0;border-left:0}
}
@media (max-width:34rem){
  .fgrid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .fgrid > *{padding-left:0;border-right:0}
  .fgrid > *:nth-child(odd){border-right:1px solid var(--slab-hair);padding-right:1.25rem}
}
.fbrand p{color:var(--on-slab-2);font-size:var(--t-sm);max-width:32ch;margin:0 0 .9rem}
.fbrand .flogo{margin:0 0 .8rem;display:block;height:2.1rem;width:auto;color:var(--on-slab)}
.fcol h2{color:var(--on-slab-2);margin:0 0 .9rem;padding-bottom:.5rem;border-bottom:1px solid var(--slab-hair)}
.fcol ul{list-style:none;padding:0;margin:0}
.fcol li{margin-bottom:.4rem;font-size:var(--t-meta);line-height:1.4}
.fbot{
  margin:2rem 0 0;padding-top:1.1rem;border-top:var(--rw) solid var(--slab-hair);
  display:flex;flex-wrap:wrap;gap:.6rem 1.6rem;justify-content:space-between;align-items:baseline;
}
.fbot p{margin:0;font-size:var(--t-meta);color:var(--on-slab-2)}
.fbot .pub{color:var(--on-slab)}
.fbot .pubmail{margin:0}
.fbot .pubmail a{color:var(--on-slab-2)}
.postbtn{flex:none}
@media (max-width:66rem){.postbtn{display:none}}

/* ================================================================
   21. THE SIGNATURE MOMENT — "EL FLASH DE PRECIO"
   A 24-point starburst carrying the one number that matters on a page:
   $0 on pricing, GRATIS on the free category, 1.4M on the stat strip.
   Pure CSS: two gradients, one mask, one hard drop-shadow. ~1.1 KB.
   Never above the fold; never on the LCP element.
   Markup:  <span class="flash"><b>$0</b><i>para publicar</i></span>
   ================================================================ */
.flash{
  --flash-d:clamp(6.5rem,15vw,9.5rem);
  position:relative;flex:none;
  width:var(--flash-d);height:var(--flash-d);
  display:grid;place-content:center;place-items:center;
  text-align:center;line-height:.88;
  color:var(--accent-ink);
  font-family:var(--display);font-weight:900;letter-spacing:-.04em;
  rotate:var(--flash-rotate);
}
.flash::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:
    repeating-conic-gradient(from 0deg,var(--accent) 0 var(--flash-spike),transparent var(--flash-spike) calc(var(--flash-spike)*2)),
    radial-gradient(circle at 50% 50%,var(--accent) 0 64%,transparent 64%);
  -webkit-mask-image:radial-gradient(circle at 50% 50%,#000 0 50%,transparent 50%);
  mask-image:radial-gradient(circle at 50% 50%,#000 0 50%,transparent 50%);
  filter:drop-shadow(5px 6px 0 var(--slab));
}
.flash b{display:block;font-size:calc(var(--flash-d) * .34);font-weight:900;color:inherit}
.flash i{
  display:block;font-style:normal;margin-top:.35em;
  font-size:calc(var(--flash-d) * .085);font-weight:800;
  letter-spacing:.1em;text-transform:uppercase;max-width:7em;line-height:1.15;
}
/* winter: fewer spikes, less rotation, larger — loud is not the same as legible */


/* the only entrance animation in the product, and it is opt-in */
@media (prefers-reduced-motion:no-preference){
  .flash.stamp{animation:qh-stamp .28s cubic-bezier(.2,1.4,.4,1) both}
  @keyframes qh-stamp{from{transform:scale(1.22);opacity:0}to{transform:none;opacity:1}}
}
/* graceful degradation: no mask support -> a plain accent disc, still correct */
@supports not ((mask-image:radial-gradient(#000,#000)) or (-webkit-mask-image:radial-gradient(#000,#000))){
  .flash::before{background:var(--accent);border-radius:50%}
}

/* ================================================================
   22. DENSITY BLOCKS
   Layout patterns that make a page substantial without inventing content.
   Every one of these renders data content.py already holds.
   ================================================================ */

/* 22a. EDITORIAL — asymmetric main + sticky sidebar */
.editorial{display:grid;grid-template-columns:minmax(0,8fr) minmax(0,4fr);gap:clamp(1.75rem,4vw,3.5rem);align-items:start}
@media (max-width:56rem){.editorial{grid-template-columns:minmax(0,1fr)}}
.rail{position:sticky;top:5.5rem;border-top:var(--rw-heavy) solid var(--ink);padding-top:1rem}
@media (max-width:56rem){.rail{position:static}}
.rail + .rail{margin-top:2rem}

/* 22b. GLANCE — the at-a-glance fact panel (dl of ruled rows) */
.glance{margin:0;border-top:var(--rw-heavy) solid var(--ink)}
.glance div{display:grid;grid-template-columns:minmax(0,7rem) minmax(0,1fr);gap:.75rem;
  padding:.6rem 0;border-bottom:1px solid var(--hair)}
.glance dt{color:var(--ink-3);margin:0;padding-top:.15em}
.glance dd{margin:0;font-size:var(--t-sm);color:var(--ink)}
@media (max-width:26rem){.glance div{grid-template-columns:minmax(0,1fr);gap:.15rem}}

/* 22c. INDICE — the directory index. Replaces the chip wall of 18 cities.
   Ordered west to east along the river, numbered, county-labelled. */
.indice{border-top:var(--rw-heavy) solid var(--ink)}
.indice ol{list-style:none;margin:0;padding:0;
  display:grid;grid-template-columns:repeat(auto-fill,minmax(min(14rem,100%),1fr));gap:0}
.indice li{margin:0;border-bottom:1px solid var(--hair);border-right:1px solid var(--hair)}
.indice a{
  display:grid;grid-template-columns:2.25rem minmax(0,1fr);gap:.6rem;
  padding:.65rem .9rem .7rem 0;text-decoration:none;color:var(--ink);
  border-left:var(--rw-heavy) solid transparent;padding-left:.7rem;
  transition:border-left-color .12s linear,background-color .12s linear;
}
.indice a:hover,.indice a:focus-visible{border-left-color:var(--accent);background:var(--accent-tint)}
.indice .no{font-weight:800;font-size:var(--t-micro);color:var(--ink-3);padding-top:.4em;letter-spacing:.04em}
.indice .nm{font-family:var(--display);font-weight:var(--w-head);font-size:var(--t-t2);letter-spacing:-.015em;line-height:1.2}
.indice .sub{display:block;color:var(--ink-3);margin:.2rem 0 0;max-width:none;font-size:var(--t-micro)}

/* 22d. SEASON — the twelve-month band. Real festival months, nothing invented. */
.season{border-top:var(--rw-heavy) solid var(--ink);overflow-x:auto}
.season ol{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(12,minmax(5.5rem,1fr));min-width:44rem}
.season li{margin:0;border-right:1px solid var(--hair);padding:.7rem .6rem 1rem 0;min-height:7rem}
.season li:last-child{border-right:0}
.season b{display:block;font-weight:800;font-size:var(--t-micro);letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-3);margin-bottom:.6rem}
.season li.on b{color:var(--accent)}
.season a{display:block;font-family:var(--display);font-weight:700;font-size:var(--t-meta);
  line-height:1.2;color:var(--ink);text-decoration:none;margin-bottom:.5rem;
  border-left:var(--rw) solid var(--accent);padding-left:.45rem}
.season a:hover{color:var(--accent)}

/* 22e. BOARD — a full-bleed ruled strip used between sections */
.board{
  background:var(--slab);color:var(--on-slab);
  border-top:var(--rw) solid var(--accent);border-bottom:var(--rw) solid var(--accent);
}
.board .wrap{display:flex;flex-wrap:wrap;gap:.6rem 1.5rem;align-items:baseline;
  padding-top:.7rem;padding-bottom:.7rem}
.board p{margin:0;font-size:var(--t-meta);color:var(--on-slab-2)}
.board strong{font-family:var(--display);font-weight:800;font-size:var(--t-label);
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--on-slab)}

/* 22f. two-column prose for long documents at desktop */
@media (min-width:64rem){
  .prose.twocol{max-width:none;columns:2;column-gap:3rem;column-rule:1px solid var(--hair)}
  .prose.twocol p{break-inside:avoid}
}

/* ---------------------------------------------------------------- 23. MOTION */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important;
  }
}
/* ---------------------------------------------------------------- 24. PRINT */
@media print{
  .topbar,.langbar,footer,.navtoggle,.langsw,.cta-row,.flash{display:none}
  body{background:#fff;color:#000;font-size:11pt}
  .card,.tier,.formcard{break-inside:avoid}
}
/* ---------------------------------------------------------------- 25. FORCED COLORS */
@media (forced-colors:active){
  .cartel,.tier.feat,.btn.primary,.flash::before{forced-color-adjust:none}
  .card,.chip,.tier{border:1px solid CanvasText}
  :focus-visible{outline:3px solid Highlight;box-shadow:none}
}

/* ================================================================
   ================================================================
   v3 — "AIRE"
   ================================================================
   Everything above this line is v2 sections 1–25, unchanged. Everything
   below replaces the accumulated correction tail and adds four things:

     26. THE LAYOUT TIER      a real spacing scale, six steps
     27. THE READING SPINE    measure, running-text size, the centred column
     28. THE SVG LAYER        one standard, one API — docs/plan/brainstorm/svg-system.md
     29. SECTION BLOCKS       .duo, the alternating text/illustration pattern
     30. RE-AUTHORED TAIL     everything the old tail did, done once, correctly
     31. DEVICE COVERAGE      320 -> ultrawide, landscape, 200% zoom, targets

   Six custom properties in the old tail were never defined — --palm, --gold,
   --rule, --rule-2, --surface, --sunk. Every rule that used one was silently
   dead, which is why the season band had no fills and the border-wait board
   showed no green/amber/red. They are gone; the rules are re-authored against
   real tokens below.
   ================================================================ */

/* ---------------------------------------------------------------- 26. LAYOUT TIER
   Two tiers, the way Firefox's flare system does it and for the same reason:
   a component's internal padding and a page's section rhythm are different
   problems and one 8-step scale cannot serve both without the big end being
   unusably fine and the small end unusably coarse.

     COMPONENT tier   space.0..9   0 2 4 8 12 16 24 32 48 64        (unchanged)
     LAYOUT    tier   --l-3xs..lg  24 -> 160                        (new)

   Firefox ships 64px of section padding on a 1440 container, 128 at the top
   of the page, and 64 under a section heading, flat, at every width above
   600px. Ours is fluid rather than stepped — a stepped scale on a 320px
   Android either wastes a third of the viewport or snaps at 600 — and it
   runs further at the desktop end, because our max-width is narrower than
   theirs and the air has to come from somewhere.

   Every step is expressible in packages/ui/tokens as space.layout.*; the
   proposed source entries are in the design note. Nothing here invents a
   colour, so nothing here can move the contrast gate.
   ---------------------------------------------------------------- */
:root{
  --l-3xs:clamp(1.5rem,1.15rem + 1.75vw,2rem);     /*  24 ->  32  inside a block   */
  --l-2xs:clamp(2rem,1.5rem + 2.5vw,2.75rem);      /*  32 ->  44  block to block   */
  --l-xs:clamp(2.5rem,1.8rem + 3.5vw,3.5rem);      /*  40 ->  56  head to body     */
  --l-sm:clamp(3.25rem,2.3rem + 4.75vw,5rem);      /*  52 ->  80  tight section    */
  --l-md:clamp(4.5rem,3rem + 7.5vw,7rem);          /*  72 -> 112  SECTION          */
  --l-lg:clamp(6rem,3.9rem + 10.5vw,10rem);        /*  96 -> 160  a full stop      */

  --sp:var(--l-md);          /* the name the rest of the sheet already uses */
  --sp-tight:var(--l-sm);
  --gut:clamp(1rem,4.5vw,4.5rem);   /* 16 at 320 — see §31, the header budget */

  --maxw:76.25rem;      /* 1220  the ruled board spine                        */
  --maxw-wide:90rem;    /* 1440  bands, illustration splits, footer           */
  --maxw-text:44rem;    /*  704  the centred single-column reading spine      */

  --tap:2.75rem;        /* 44px. size.target. Every control clears it.        */
  --measure:64ch;
  --t-read:clamp(1.0625rem,1rem + .35vw,1.1875rem);   /* 17 -> 19 running prose */
  --lh-read:1.7;
}
/* winter's root is 18px, so every rem bound above already grows 12.5%. It gets
   a slightly steeper vw ramp on top, because winter is the calm theme and the
   audience it is for reads at arm's length. */
:root[data-theme="winter"]{
  --l-md:clamp(4.75rem,3rem + 8.5vw,7.5rem);
  --l-lg:clamp(6.5rem,4rem + 12vw,11rem);
  --measure:58ch;
  --t-read:clamp(1.0625rem,1rem + .4vw,1.25rem);
  --lh-read:1.75;
  --tap:3rem;
}

/* SECTION RHYTHM. Two adjacent sections give 144px of air at 320 and 224 at
   1440. The first section on a page gets a full stop above it instead, so the
   run from the nav to the first headline stays short — the fix made earlier
   this session, generalised. */
section{padding:var(--sp) 0}
section.tight{padding:var(--sp-tight) 0}
/* The hero carries its padding on .wrap and was ALSO collecting
   section{padding:var(--sp) 0} on top of it — the run from the nav to the first
   headline was doubled at the source. (.phead is a <div>, so it never was.) */
.hero{padding-block:0}
/* The first section after a page header does not need full rhythm on top of the
   header's own bottom padding; neither does a page that opens with a section. */
main > section:first-child:not(.hero){padding-top:var(--l-sm)}
.phead + section{padding-top:var(--l-sm)}

/* INTRA-SECTION RHYTHM. The section head is a mile marker: rule, label, head,
   then a deliberate gap before the content it introduces. Firefox puts 64px
   there; at our type size 40->56 lands in the same optical place. */
.sec-head{margin:0 0 var(--l-xs);padding-top:1rem;border-top:var(--rw-heavy) solid var(--ink)}
.sec-head > h2{max-width:20ch}
.sec-head > p:not(.kicker){font-size:var(--t-t1);line-height:1.45;color:var(--ink-2);max-width:46ch;margin:0}
.kicker{margin:0 0 1.1rem}
/* a second head inside one section — gen.py emits these with inline margins */
.sec-head + .sec-head,.grid + .sec-head,.indice + .sec-head{margin-top:var(--l-2xs)}
/* the gap between two stacked blocks that are not sections */
.grid + .grid,.grid + .note,.prose + .grid,.season + .grid,.steps + .cta-row{margin-top:var(--l-2xs)}
.cta-row{gap:.7rem;margin-top:var(--l-3xs)}
.hero .cta-row{margin-top:var(--l-3xs)}

/* HERO. The one place the old sheet was right to be tight at the top; it was
   wrong to be tight at the bottom. A hero that ends 44px above a rule reads as
   a banner. Ending 96–160px above one reads as an opening. */
.hero .wrap{padding-top:clamp(1.25rem,2.4vw,2.25rem);padding-bottom:var(--l-lg)}
.phead .wrap{padding-top:clamp(.85rem,1.6vw,1.35rem);padding-bottom:var(--l-sm)}
.hero .lede{margin-top:var(--l-3xs)}

/* COMPONENT PADDING. Cards, tiers and form cards were padded on a different
   scale from everything around them. One scale. */
.card{padding:var(--l-3xs) var(--l-3xs) calc(var(--l-3xs) * 1.15)}
.tier{padding:var(--l-3xs) var(--l-3xs) calc(var(--l-3xs) * 1.15)}
.formcard{padding:clamp(1.35rem,3.2vw,2.25rem)}
.step{padding:var(--l-3xs) var(--l-3xs) calc(var(--l-3xs) * 1.15) 0}
.note{padding:1.1rem 1.2rem;margin:var(--l-3xs) 0}
.stats > div,.ledger > div{padding:var(--l-3xs) var(--l-3xs) var(--l-3xs) 0}

/* ---------------------------------------------------------------- 27. READING SPINE
   Firefox's page is one centred column with hard max-widths and body copy set
   two steps above UI copy. Ours was setting long-form prose at the same 16px
   as a nav item, then buying the measure back with more characters per line.
   Wrong lever: the measure comes down and the type goes up. */
/* margin-inline:auto is not cosmetic here. These carry a hard measure inside a
   1220px wrap, so without it the column sits flush left with a third of the
   page empty to its right -- which reads as a broken layout rather than as a
   reading column. The measure was set and the centring was never added. */
.prose,.guide,.citybody,.catbody,.faq .a,.legal{max-width:var(--measure);margin-inline:auto}
.prose p,.prose li,.guide p,.guide li,.citybody p,.catbody p,.legal p,.legal li{
  font-size:var(--t-read);line-height:var(--lh-read);
}
.prose p,.guide p,.citybody p,.catbody p{margin:0 0 .85em}
.prose h3,.guide h3{margin-top:var(--l-3xs);margin-bottom:.4em}
.guide h2{font-size:var(--t-d3);margin:var(--l-2xs) 0 .5em;padding-top:var(--l-3xs);border-top:var(--rw) solid var(--ink)}
.guide > p:first-of-type{font-size:calc(var(--t-read) * 1.14);line-height:1.5;color:var(--ink)}
.guide ul,.prose ul{margin:0 0 1.1em;padding-left:1.35rem}
.guide li,.prose li{margin-bottom:.5em}
.lede{max-width:24ch;font-size:clamp(1.125rem,1rem + 1.15vw,1.625rem);line-height:1.32}
.sub{font-size:var(--t-t1);max-width:48ch;line-height:1.5;margin:0 0 var(--l-3xs)}

/* THE SHARE ROW. Placed after the body -- the "that was useful" moment --
   rather than in the header, where it competes with the thing being shared.
   No brand green: WhatsApp's #25D366 is 1.7:1 on the canvas and can carry
   neither white nor dark text at AA, so the button uses our own accent and the
   glyph carries the recognition. */
.share{max-width:var(--measure);margin:var(--l-2xs) auto 0;padding-top:var(--l-3xs);border-top:1px solid var(--hair)}
.share h2{font-size:var(--t-t2);margin:0 0 .7rem}
.share-row{list-style:none;display:flex;flex-wrap:wrap;gap:.6rem;padding:0;margin:0}
.share-row li{margin:0}

/* .btn is display:inline-flex, which beats the user-agent [hidden] rule. Without
   this the copy button renders and does nothing whenever JS is off or fails. */
[hidden]{display:none!important}

/* Visually hidden, still announced. The copy confirmation is the only feedback
   a screen-reader user gets that the button did anything. */
.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
    clip-path:inset(50%);white-space:nowrap;border:0}

/* THE MONTH BAND. The only element on the site that is different when a reader
   returns, which is the entire argument for it. Three tones because the Valley
   calendar genuinely has three: a festival month and July are not the same
   claim and should not look the same. */
.mband{
  max-width:var(--measure);margin:0 auto var(--l-2xs);
  padding:.7rem .95rem;border-left:var(--rw) solid var(--accent);
  background:var(--slab);
}
.mband p{margin:0;font-size:var(--t-meta);line-height:1.45;color:var(--ink-2)}
.mband b{color:var(--ink)}
.mband--trough{border-left-color:var(--ink-3)}
.mband--fiesta{border-left-color:var(--accent)}
.mband--festival{border-left-color:var(--accent)}

/* THE SPINE. A centred single column for pages that are one argument rather
   than a board. Opt-in: add `spine` to the wrap. */
.wrap.spine{max-width:calc(var(--maxw-text) + var(--gut) * 2)}
.wrap.wide{max-width:var(--maxw-wide)}

/* The drop cap stays — it is the one editorial flourish in the product and it
   costs nothing — but it was sized against a 17.5px body and now floats on a
   fluid one. */
.citybody p:first-child::first-letter,.catbody p:first-child::first-letter{
  font-family:var(--display);font-weight:800;font-size:3.2em;line-height:.8;
  float:left;margin:.05em .1em 0 0;color:var(--accent);
}
.citybody,.catbody{margin-top:var(--l-2xs)}

/* ================================================================
   28. THE SVG LAYER
   ONE standard for every vector in the platform. The whole rationale,
   the grid, the optical rules and the CI gate are in
   docs/plan/brainstorm/svg-system.md. The short version:

     24 grid · 2px stroke · butt caps · miter joins · radius 0
     fill:none · stroke:currentColor · sized in em, never px
     icons are decorative; the host control carries the name
     one source file per glyph in assets/icons/i-NAME.svg
     assets/icons/build-sprite.py lints them and emits the sprite

   Butt caps and miter joins are the SVG defaults, so the house style costs
   zero bytes to declare. Round caps would cost 42 bytes a file or a CSS rule
   we would then have to remember — and they would fight a system whose entire
   grammar is 1px/2px/3px square-cut rules.

   COLOUR IS currentColor AND NOTHING ELSE. An icon's colour is decided by
   where it sits, not by what it depicts: ink in a card, --on-slab on the slab,
   accent when the host is accented. There is no accent slot inside a glyph.
   A second colour inside an icon would need its own row in the contrast gate
   for every theme x scheme x surface — twenty pairs to buy a red dot — and at
   20px two tones read as noise, not as information. Illustrations are the
   documented exception: they are inlined, large enough for tone to mean
   something, and their palette is a fixed reviewable set.
   ================================================================ */

/* The sprite reference. gen.py inlines the five above-the-fold glyphs from the
   same source files; everything else is one immutably-cached request.
     <svg class="i" aria-hidden="true" focusable="false">
       <use href="/assets/icons/sprite.HASH.svg#i-cat-jamaicas"/></svg> */
.i{
  --i-size:1.25em;
  width:var(--i-size);height:var(--i-size);
  flex:none;display:inline-block;vertical-align:-.235em;
  fill:none;stroke:currentColor;stroke-width:2;
  /* the box is sized before the sprite arrives, so a late sprite cannot shift
     a line of text — no containment tricks needed, just an explicit em box */
}
/* Four sizes, all in em, each pinned to a step of the type scale. em is not a
   preference: px would break winter's 1.125 scale and 200% text zoom, and we
   would need two more rules to patch each. */
.i-sm{--i-size:1em;vertical-align:-.14em}       /* beside --t-label / --t-meta */
.i-lg{--i-size:1.6em;vertical-align:-.34em}     /* beside h3 / a card title    */
.i-xl{--i-size:2em;vertical-align:-.44em}       /* the ceiling                 */
/* Past 2em a 2px stroke on a 24 grid renders above 3.3px and stops matching the
   2px block rule. Anything that wants to be bigger is an illustration and lives
   in assets/illus/ with its own weight. That boundary is the reason the two
   things are separate directories. */

/* An icon next to a text label sits on the label's baseline and takes the gap
   from the type, not from a margin. */
.btn .i,.chip .i,.card .i,nav.main a .i,.crumbs .i,.fcol a .i{margin-right:.5em}
.btn .i:last-child,.chip .i:last-child{margin:0 0 0 .5em}
.btn{gap:0}          /* the em margin above replaces the flex gap, so an icon
                        scales with the button's own type instead of the root */

/* The category glyph on a card. One place a glyph is allowed to be the first
   thing you see, because the ten categories are the product's primary axis. */
.card > .i-lg,.card > .i-xl{display:block;margin:0 0 var(--l-3xs);color:var(--accent)}
a.card:hover > .i-lg,a.card:focus-visible > .i-lg{color:var(--accent-on-tint)}
.band.ink .card > .i-lg{color:var(--accent-on-slab)}

/* The nav toggle. Was three <span>s — a CSS shape doing an icon's job, which is
   exactly the inconsistency this layer exists to end. Both forms are supported
   so the stylesheet can ship before the markup change. */
.navtoggle{display:none;background:none;border:var(--rw) solid var(--ink);color:var(--ink);
  cursor:pointer;padding:0;width:var(--tap);height:var(--tap);
  align-items:center;justify-content:center;flex:none}
.navtoggle span{display:block;width:1.05rem;height:2px;background:currentColor;margin:.2rem 0}
.navtoggle .i{--i-size:1.5rem}
.navtoggle .i-close{display:none}
.navtoggle[aria-expanded="true"] .i-menu{display:none}
.navtoggle[aria-expanded="true"] .i-close{display:inline-block}

/* Forced colours: currentColor already follows CanvasText, so an icon needs
   nothing. Saying so out loud is half the value of choosing currentColor. */

/* ---- illustrations ------------------------------------------------------
   Inlined, never spritten: they carry a <title>, they take --qh-* fills that a
   <use> shadow tree could still receive but that are far easier to review in
   place, and there is at most ONE on a page. They carry no text of any kind —
   text in an SVG does not localise, does not wrap, and drags a font dependency
   into a file whose entire justification is that it is 600 bytes. Anything
   that must be read is HTML beside it. */
.illus{display:block;width:100%;height:auto;color:var(--ink)}
.illus--sm{max-width:26rem}
figure.illus-fig{margin:0}
figure.illus-fig figcaption{
  margin-top:var(--l-3xs);font-size:var(--t-sm);color:var(--ink-3);max-width:38ch;
  border-top:1px solid var(--hair);padding-top:.7rem;
}
/* The bridge between this sheet's short token names and the --qh-* names the
   token package emits. The SVGs are authored against --qh-* so that adopting
   packages/ui/tokens/dist/web/theme.css is a deletion of this block and not a
   rewrite of eleven files. */
:root,[data-theme]{
  --qh-color-ink-primary:var(--ink);
  --qh-color-accent-base:var(--accent);
  --qh-color-surface-raised:var(--raised);
  --qh-color-surface-sunken:var(--sunken);
  --qh-color-border-hairline:var(--hair);
  --qh-color-free-base:var(--free);
}
.band.ink,footer,.board,.cartel{
  --qh-color-accent-base:var(--accent-on-slab);
  --qh-color-surface-raised:var(--slab);
  --qh-color-surface-sunken:var(--slab-hair);
  --qh-color-border-hairline:var(--slab-hair);
  --qh-color-free-base:var(--free-on-slab);
}
@media (forced-colors:active){
  .illus{color:CanvasText}
}

/* ================================================================
   29. SECTION BLOCKS
   The Firefox move the owner asked for: alternating text-left/image-right
   blocks on a centred spine, instead of another card grid. Ours differs in
   one way that matters — the illustration is informational, so it gets equal
   width rather than being a decorative half.
   ================================================================ */
.duo{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);
  gap:clamp(2rem,5vw,5rem);align-items:center;
}
.duo > .prose{max-width:38ch}
.duo + .duo{margin-top:var(--l-md)}
.duo.flip > *:first-child{order:2}
/* Below 52rem it stacks — and `flip` unwinds, so the text always precedes the
   picture it describes. An illustration that arrives before its explanation is
   a decoration; that is the line this component is on the right side of. */
@media (max-width:52rem){
  .duo{grid-template-columns:minmax(0,1fr);gap:var(--l-2xs)}
  .duo.flip > *:first-child{order:0}
  .duo > .prose{max-width:var(--measure)}
}
/* The split pairing (a form beside prose) — kept from this session's fix, moved
   onto the layout tier. */
.grid.split{gap:clamp(2rem,4.5vw,4rem);align-items:start}
@media (max-width:44rem){.grid.split{gap:var(--l-2xs)}}
.grid.split > div:not(.formcard){
  border-top:var(--rw-heavy) solid var(--hair);padding-top:var(--l-3xs);
}
.grid.split > div:not(.formcard) > h3:first-child,
.grid.split > div:not(.formcard) > h2:first-child{margin-top:0}

/* ================================================================
   30. RE-AUTHORED TAIL
   Everything the old correction tail did, done once, against tokens that
   exist. Every fix from this session is preserved.
   ================================================================ */

/* ---- logo --------------------------------------------------------------
   Untouched as a drawing. The only change is that below 24rem the lockup is
   swapped for the square mark, which is what buys the 320px header its room
   (§31). If gen.py has not been updated yet, .brandmark simply does not exist
   and the lockup stays — the CSS-only budget below still fits. */
.brand{display:inline-flex;align-items:center;text-decoration:none;color:var(--ink);flex:none;min-width:0}
.brand svg{height:clamp(1.35rem,3.4vw,1.75rem);width:auto;display:block;max-width:100%}
.brand .brandmark{display:none}

/* ---- glance ------------------------------------------------------------- */
.glance{margin:var(--l-2xs) 0 0;border-top:var(--rw-heavy) solid var(--ink)}
.glance h2{
  font-family:var(--display);font-size:var(--t-label);font-weight:800;
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--ink-3);
  margin:.8rem 0 var(--l-3xs);border:0;padding:0;
}
.glance table{min-width:0}
.glance th{text-align:left;font-weight:600;color:var(--ink);white-space:nowrap;
  width:1%;padding-right:1.6rem;vertical-align:top}

/* ---- border wait board -------------------------------------------------
   The three status colours were bound to --palm/--gold, which have not existed
   since v1: the board has been rendering every wait in body ink. They are the
   only thing on that page a driver actually reads. */
.bwt-wrap{overflow-x:auto;overscroll-behavior-x:contain;
  border-top:var(--rw-heavy) solid var(--ink);margin:var(--l-3xs) 0}
.bwt-loading{color:var(--ink-3);padding:1.1rem 0}
table.bwt th[scope=row]{text-align:left;font-weight:600;color:var(--ink);white-space:nowrap;padding-right:1.4rem}
table.bwt .bwt-hours{display:block;font-weight:400;font-size:var(--t-meta);color:var(--ink-3);
  letter-spacing:0;text-transform:none}
table.bwt td.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;font-family:var(--display)}
table.bwt td.num b{font-weight:800;font-size:1.12em}
table.bwt .bwt-good{color:var(--free-on-tint);font-weight:700}
table.bwt .bwt-warn{color:var(--warn);font-weight:700}
table.bwt .bwt-bad{color:var(--accent-on-tint);font-weight:800}
table.bwt .bwt-na,table.bwt .bwt-closed{color:var(--ink-3);font-family:var(--body);font-size:var(--t-sm)}
table.bwt .bwt-upd{color:var(--ink-3);font-size:var(--t-meta);white-space:nowrap}
.bwt-src{margin:var(--l-3xs) 0 0;font-size:var(--t-meta);color:var(--ink-3)}
.bwt-src .bwt-staleflag{color:var(--accent);margin-left:.4rem}

/* ---- the twelve-month season band --------------------------------------
   It had `min-width:44rem` and `overflow-x:auto`, so on a phone the Valley
   year was a 704px-wide horizontal scroller inside a vertically-scrolling
   page — two axes, one of them invisible. It is now a grid whose column count
   always divides twelve: 2 / 3 / 4 / 6. It never scrolls sideways at any
   width, and at six columns it reads as the year in two halves, which is how
   anyone here actually talks about it. */
.season{border-top:var(--rw-heavy) solid var(--ink);overflow:visible;margin:0}
.season h2{
  font-family:var(--display);font-size:var(--t-label);font-weight:800;
  letter-spacing:var(--tr-label);text-transform:uppercase;color:var(--ink-3);
  margin:.8rem 0 var(--l-3xs);border:0;padding:0;
}
.skey{display:flex;gap:1.1rem;flex-wrap:wrap;margin:0 0 var(--l-3xs);
  font-size:var(--t-meta);color:var(--ink-3)}
.skey .k{display:inline-flex;align-items:center;gap:.45rem}
.skey .k::before{content:"";width:.7rem;height:.7rem;flex:none}
.skey .k-festival::before{background:var(--accent)}
.skey .k-trough::before{background:var(--mid)}
.skey .k-fiesta::before{background:var(--free)}
.season ol{
  list-style:none;margin:0;padding:0;min-width:0;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;
  background:var(--hair);border:1px solid var(--hair);
}
@media (min-width:30rem){.season ol{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (min-width:48rem){.season ol{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media (min-width:64rem){.season ol{grid-template-columns:repeat(6,minmax(0,1fr))}}
.season li{
  background:var(--raised);padding:.9rem .95rem 1.05rem;margin:0;
  border:0;border-top:var(--rw-heavy) solid var(--mid);min-height:0;
}
.season li.s-festival{border-top-color:var(--accent)}
.season li.s-fiesta{border-top-color:var(--free)}
.season li.on{background:var(--accent-tint)}
.season li.on.s-fiesta{background:var(--free-tint)}
.season .mo{display:block;font-family:var(--display);font-weight:800;font-size:var(--t-label);
  letter-spacing:var(--tr-label);text-transform:uppercase;margin:0 0 .4rem;color:var(--ink-3)}
.season li.on .mo{color:var(--accent)}
.season li.on.s-fiesta .mo{color:var(--free-on-tint)}
.season .hd{display:block;font-size:var(--t-sm);line-height:1.45;color:var(--ink-2)}
.season li a{display:inline-flex;align-items:center;min-height:var(--tap);
  margin-top:.4rem;font-family:var(--display);font-weight:700;font-size:var(--t-meta);
  border-left:var(--rw) solid var(--accent);padding-left:.45rem;
  color:var(--ink);text-decoration:none}
.season li a:hover{color:var(--accent)}
.snote{margin:var(--l-3xs) 0 0;font-size:var(--t-meta);color:var(--ink-3);max-width:56ch}

/* ---- long-form guide ---------------------------------------------------- */
.guide strong{font-weight:650;color:var(--ink)}
.flashrow{display:flex;align-items:center;gap:clamp(1.5rem,4vw,3.5rem);
  margin:var(--l-2xs) 0 0;flex-wrap:wrap}
.flashrow .prose{flex:1 1 20rem;max-width:46ch;min-width:0}

/* ---- hero city bar ------------------------------------------------------ */
.citybar{display:flex;align-items:center;gap:.75rem;flex-wrap:wrap;margin:0 0 var(--l-3xs)}
.citybar .cb-line{margin:0;font-size:var(--t-t3);color:var(--ink-2)}
.citybar .cb-change{background:none;border:0;padding:.35rem 0;font:inherit;font-size:var(--t-sm);
  color:var(--accent);text-decoration:underline;text-underline-offset:.2em;cursor:pointer;
  min-height:var(--tap);display:inline-flex;align-items:center}
.citybar .cb-picker{flex-basis:100%;display:flex;align-items:center;gap:.6rem;margin-top:.25rem;flex-wrap:wrap}
.citybar .cb-picker label{margin:0;font-size:var(--t-label)}
.citybar .cb-picker select{width:auto;min-width:min(12.5rem,100%);margin:0;padding:.5rem .7rem;font-size:var(--t-t3)}

/* ---- the cartel --------------------------------------------------------
   LIFTED VERBATIM from style.css as of this pass. The cartel was rebuilt as a
   .c-* component while this work was in flight and it is not mine to re-author;
   the only thing added is the shrink at 320 in §31. If it moves again, re-lift
   this block rather than merging by hand. */
.cartel{
  display:flex;flex-direction:column;
  padding:0;                                   /* the sheet has no gutter */
  min-height:clamp(21rem,36vw,29rem);
  overflow:hidden;
}
.cartel > *{padding-inline:clamp(1.1rem,2.4vw,1.9rem)}

.c-eyebrow{
  margin:0;padding-block:.7rem .65rem;
  font-family:var(--display);font-weight:800;
  font-size:clamp(.62rem,1.35vw,.76rem);letter-spacing:.24em;text-transform:uppercase;
  border-bottom:3px solid var(--accent-ink);
}

/* The headline is the sheet. Condensed, tight, and as large as the box allows. */
.c-title{
  margin:0;padding-block:clamp(.7rem,1.8vw,1.15rem) clamp(.5rem,1.4vw,.8rem);
  font-family:var(--display);font-weight:900;
  font-size:clamp(2.5rem,7.1vw,4.4rem);
  line-height:.83;letter-spacing:-.045em;text-transform:uppercase;
  font-stretch:condensed;
}
.c-title span{display:block}
.c-title span:last-child{padding-left:.06em}

/* Date block, time and venue, and the flash — the row a flyer always has. */
.c-when{
  display:flex;align-items:stretch;gap:clamp(.7rem,1.8vw,1.1rem);
  padding-block:clamp(.7rem,1.6vw,1rem);
  border-top:3px solid var(--accent-ink);
  margin-top:auto;
}
.c-date{
  flex:none;display:flex;flex-direction:column;align-items:center;justify-content:center;
  padding:.35rem .65rem;border:3px solid var(--accent-ink);line-height:1;
}
.c-date b{
  font-family:var(--display);font-weight:800;
  font-size:clamp(.6rem,1.25vw,.7rem);letter-spacing:.16em;
}
.c-date i{
  font-style:normal;font-family:var(--display);font-weight:900;
  font-size:clamp(1.9rem,4.6vw,2.7rem);letter-spacing:-.04em;margin:.06em 0;
}
.c-where{display:flex;flex-direction:column;justify-content:center;min-width:0;gap:.15rem}
.c-where p{margin:0;font-family:var(--display);font-weight:800;
  font-size:clamp(.72rem,1.55vw,.88rem);letter-spacing:.09em;text-transform:uppercase;
  overflow-wrap:anywhere}
.c-where .c-time{font-size:clamp(1rem,2.3vw,1.35rem);letter-spacing:.02em}

/* The flash is the one thing on a Valley flyer that is never subtle. */
.c-flash{
  margin:0 0 0 auto;align-self:center;flex:none;
  background:var(--accent-ink);color:var(--accent);
  font-family:var(--display);font-weight:900;
  font-size:clamp(.78rem,1.8vw,1.05rem);letter-spacing:.06em;
  padding:.42em .7em;rotate:-4deg;
}

.c-foot{
  margin:0;padding-block:.85rem 1rem;
  font-size:clamp(.72rem,1.35vw,.82rem);line-height:1.45;
  border-top:1px solid color-mix(in srgb,var(--accent-ink) 34%,transparent);
  opacity:.9;
}

@media (max-width:56rem){
  .cartel{min-height:0}
  .c-title{font-size:clamp(2.6rem,11vw,4rem)}
}
@media (max-width:26rem){
  .c-when{flex-wrap:wrap}
  .c-flash{margin-left:0}
}

/* The flyer is the argument, so it is allowed to be the heaviest object on the
   page. Hard offset shadow, no blur — a printed sheet lying on a surface. */
.cartel{box-shadow:14px 14px 0 var(--slab)}
@media (max-width:56rem){.cartel{box-shadow:8px 8px 0 var(--slab)}}
@media (max-width:34rem){.cartel{box-shadow:6px 6px 0 var(--slab)}}

/* §31 addendum: at 320 the flash and the date block were the two things that
   could still push the sheet wider than its column. */
@media (max-width:22.5rem){
  .cartel{box-shadow:4px 4px 0 var(--slab)}
  .c-title{font-size:clamp(2.2rem,12vw,3rem)}
  .c-date{padding:.3rem .5rem}
  .c-where p{overflow-wrap:anywhere}
}

/* ---- footer ------------------------------------------------------------- */
footer{padding:var(--l-sm) 0 var(--l-3xs)}
.fgrid{gap:0;align-items:start}
.fgrid > *{padding-top:.25rem}
.fbrand{padding-right:clamp(1.5rem,3vw,2.75rem)}
.fbrand .flogo{height:clamp(2.2rem,4vw,2.9rem);margin-bottom:1rem}
.fbrand .ftag{color:var(--on-slab);font-size:var(--t-t2);line-height:1.4;max-width:26ch;
  margin:0 0 .35rem;font-weight:500}
.fbrand .fstate{color:var(--on-slab-2);font-size:var(--t-meta);margin:0 0 1.15rem;max-width:30ch}
.facts{display:flex;flex-wrap:wrap;gap:.55rem}
.facts .btn.ghost{border-color:var(--slab-hair);color:var(--on-slab)}
.facts .btn.ghost:hover{border-color:var(--on-slab);background:transparent}
.fcol h2{border-bottom:0;padding-bottom:0;margin-bottom:.6rem;color:var(--on-slab);letter-spacing:.14em}
.fcol li{margin-bottom:0}
.fcol a{display:flex;align-items:center;min-height:var(--tap);padding:.1rem 0;line-height:1.35}
.fbot{margin:var(--l-2xs) 0 0;padding-top:var(--l-3xs);border-top:var(--rw) solid var(--slab-hair)}
@media (max-width:64rem){
  .fbrand{grid-column:1/-1;padding-right:0;padding-bottom:var(--l-3xs);
    border-bottom:1px solid var(--slab-hair);margin-bottom:var(--l-3xs)}
  .fbrand .ftag{max-width:40ch}
}
@media (max-width:34rem){.facts{width:100%}.facts .btn{flex:1 1 auto;justify-content:center}}

/* ---- the closing band --------------------------------------------------- */
.band.ink.tight{padding:var(--l-md) 0}
.band.ink .sec-head{max-width:52ch}
.band.ink .sec-head h2{font-size:var(--t-d3)}

/* ================================================================
   31. DEVICE COVERAGE
   320 · 360 · 390 · 430 · landscape · 768 · 1024 · 1280 · 1440 · 1920 · ultrawide
   ================================================================ */

/* ---- no horizontal scroll, ever, at any width -------------------------
   Not with overflow-x:hidden on <body>, which breaks position:sticky in
   Safari and would silently kill the topbar. `clip` on the root does not,
   and every genuine overflow source is fixed at source below rather than
   swept under it. */
html{overflow-x:clip;scroll-padding-top:calc(var(--tap) + 1.5rem)}
.wrap{max-width:var(--maxw);margin-inline:auto;padding-inline:var(--gut);width:100%}
.grid,.steps,.tiers,.stats,.ledger,.indice ol,.season ol,.fgrid,.herogrid,.duo,.editorial{min-width:0}
.grid > *,.steps > *,.tiers > *,.fgrid > *,.herogrid > *,.duo > *,.editorial > *{min-width:0}
img,svg,video,iframe{max-width:100%}
pre,code{overflow-wrap:anywhere}
h1,h2,h3,.cartel .t{overflow-wrap:break-word}

/* ---- THE HEADER, and the 320px budget ---------------------------------
   Before: logo 148 + toggle 41 + langsw 62 + gutter 40 + two 17.6px gaps
   = 326 of 320. It overflowed, which is why the language switch was being
   pushed off the right edge on a 320px Android.

   After, with no markup change at all:
     gutter   2 x 16      32     --gut floor moved 20 -> 16
     lockup   19.2px tall 118    2463x400 at 1.2rem, instead of holding at 26px
     toggle               44     a real 44x44 target, not 41x37
     langsw               72     two 44px-tall links inside a 2px frame
     gaps     2 x 8       16     the gap clamps down with the viewport
                         ----
                          282 of 320, with 38px of slack.

   With the recommended markup change (see the design note) the lockup becomes
   the square mark below 24rem and the budget falls to 192 of 320. */
.topbar .wrap{
  display:flex;align-items:center;gap:clamp(.5rem,2vw,1.1rem);
  padding-top:.4rem;padding-bottom:.4rem;min-height:calc(var(--tap) + .8rem);
}
@media (max-width:24rem){
  /* CSS-only path: the wordmark drops to 1.2rem (2463x400 -> 118px wide).
     Markup path: the lockup is hidden and the square mark takes its place. */
  .brand svg{height:1.25rem}
  .brand .flockup{display:none}
  .brand .brandmark{display:block;height:1.75rem;width:auto}
}
nav.main a{min-height:var(--tap);padding:.45rem .7rem}
.langsw{display:flex;border:var(--rw) solid var(--ink);flex:none;align-self:center}
.langsw a{display:inline-flex;align-items:center;justify-content:center;
  min-height:calc(var(--tap) - 4px);padding:0 .5rem;line-height:1}
.navtoggle{margin-left:auto}
@media (max-width:60rem){
  .navtoggle{display:flex}
  nav.main{padding:0 var(--gut) var(--l-3xs)}
  nav.main a{padding:.75rem .7rem;min-height:var(--tap)}
}
/* Above 60rem the toggle is gone, so the nav takes the auto margin instead —
   otherwise `margin-left:auto` sits on a display:none element and the nav
   crowds the logo. */
@media (min-width:60.01rem){nav.main{margin-left:auto}}

/* ---- touch targets -----------------------------------------------------
   WCAG 2.2 AA (2.5.8) asks for 24x24. Every control here clears 44, which is
   the number that matters on the phones this market actually holds. The
   exceptions are links inside running prose, which 2.5.8 exempts, and they
   are the only exceptions. */
.btn{min-height:var(--tap);padding:.75rem 1.3rem}
.btn.sm{min-height:var(--tap);padding:.5rem 1rem}
.chip{display:inline-flex;align-items:center;min-height:var(--tap);padding:.45rem .85rem}
.crumbs a,.crumbs span{display:inline-flex;align-items:center;min-height:2.25rem}
.indice a{min-height:var(--tap);align-content:center}
.faq summary{min-height:var(--tap);display:flex;align-items:center}
.langbar a,.langbar button{min-height:var(--tap);display:inline-flex;align-items:center}
input,select,textarea,button{min-height:var(--tap)}
.consent input[type=checkbox]{min-height:0;width:1.35rem;height:1.35rem}
.tier .btn{width:100%}

/* ---- tables scroll inside their own container, never the page ---------- */
.tablewrap,.bwt-wrap{overflow-x:auto;overscroll-behavior-x:contain;max-width:100%}
.tablewrap table,.bwt-wrap table{min-width:32rem}
.glance .tablewrap table{min-width:0}
@media (max-width:26rem){
  .tablewrap table,.bwt-wrap table{min-width:28rem}
  thead th,tbody td{padding-right:.75rem}
}

/* ---- 320 – 26rem: the smallest real device --------------------------- */
@media (max-width:26rem){
  .herogrid{gap:var(--l-2xs)}
  .flash{--flash-d:clamp(5.5rem,26vw,7.5rem)}
  .flashrow{gap:var(--l-3xs)}
  .stats,.ledger{grid-template-columns:minmax(0,1fr)}
  .stats > div,.ledger > div{border-right:0;border-bottom:1px solid var(--hair);padding-right:0}
  .stats > div:last-child,.ledger > div:last-child{border-bottom:0}
  .legal .toc ol{columns:1}
  .fbot{gap:.5rem}
}

/* ---- phone landscape: short and wide ---------------------------------
   A 390x844 phone turned sideways has 390px of height. Full section rhythm
   there means one section fills the screen twice over and the page reads as
   empty rather than as spacious. Air is a proportion of the viewport, not an
   absolute, so the layout tier compresses on height. */
@media (orientation:landscape) and (max-height:32rem){
  :root{
    --l-md:clamp(2.25rem,7vh,3.25rem);
    --l-lg:clamp(2.75rem,9vh,4.5rem);
    --l-sm:clamp(1.75rem,5.5vh,2.75rem);
    --l-xs:clamp(1.5rem,4.5vh,2.25rem);
  }
  .hero .wrap{padding-top:.75rem}
  .cartel{min-height:0}
  .topbar{position:static}     /* 44px of a 390px viewport is 11% of it */
}

/* ---- 768 tablet portrait ---------------------------------------------- */
@media (min-width:48rem) and (max-width:63.99rem){
  .herogrid{grid-template-columns:minmax(0,1fr)}
  .duo{gap:var(--l-2xs)}
}
/* .g2/.g3/.g4 are left on their auto-fit floors at every width above this. A
   fixed repeat(3,...) forces a hole in a four-item grid, and several of these
   grids are populated from content.py rather than by hand. */

/* ---- ultrawide: 1920 and past it --------------------------------------
   Nothing grows. The page is a document, and a document that keeps widening
   stops being readable long before the monitor stops widening. */
@media (min-width:120rem){
  :root{--gut:5rem}
  body{background:var(--sunken)}
  main,.topbar,footer,.langbar{background:var(--canvas)}
  main,.topbar,.langbar,footer{max-width:120rem;margin-inline:auto}
}

/* ---- 200% text zoom / 400% reflow (WCAG 1.4.4, 1.4.10) -----------------
   Every length in this sheet is rem, em, ch, % or a clamp of them; there is
   no px length that carries layout. At 200% zoom a 1280px window reports
   40rem and takes the phone layout, which is correct and is why nothing here
   needs a zoom-specific rule. The two places a fixed length survived were the
   season band's 44rem min-width and the tables' 34rem, and both are handled
   above. This block only guards the sticky header, which at 200% is tall
   enough to eat a short viewport. */
@media (max-height:26rem){
  .topbar{position:static}
  html{scroll-padding-top:0}
}

/* ---- reduced motion: reduced means removed, not slowed ----------------- */
@media (prefers-reduced-motion:reduce){
  .flash.stamp{animation:none}
  *,*::before,*::after{
    animation-duration:1ms!important;animation-iteration-count:1!important;
    transition-duration:1ms!important;scroll-behavior:auto!important;
  }
}

/* ---- print ------------------------------------------------------------- */
@media print{
  section{padding:1.5rem 0}
  .illus{max-width:14rem}
  .season ol{grid-template-columns:repeat(4,minmax(0,1fr))}
}

/* ---- illustrations -------------------------------------------------- */
/* At most one per page, never above the fold, never the LCP element. */
.illus-wrap{margin:var(--l-sm) 0 0;padding:0}
.illus-wrap .illus{width:100%;height:auto;max-width:38rem;color:var(--ink)}
.illus-wrap.wide .illus{max-width:100%}
.illus-wrap figcaption{
  margin-top:.85rem;font-size:var(--t-sm);color:var(--ink-3);max-width:52ch;line-height:1.5;
}
.band.ink .illus-wrap .illus{color:var(--on-slab)}

/* ---- icons ---------------------------------------------------------- */
svg.i{width:1em;height:1em;flex:none;vertical-align:-.14em}
svg.i.lg{width:1.85em;height:1.85em}
svg.i.xl{width:2.6em;height:2.6em;color:var(--accent)}
.chip{display:inline-flex;align-items:center;gap:.45em}
.chip svg.i{width:1.15em;height:1.15em;opacity:.8}
.chip.free svg.i{opacity:1}
.cat-glyph{margin:0 0 .6rem;line-height:1}
.card-icon svg.i{display:block;margin:0 0 .7rem;color:var(--accent)}
.step svg.i{display:block;margin:0 0 .8rem;color:var(--accent)}
.navtoggle svg.i{width:1.35em;height:1.35em}
.lede-note{color:var(--ink-3);max-width:58ch;margin:var(--l-3xs) 0 var(--l-2xs)}

/* More of what a real sheet carries: the bill, the door line, a contact strip
   and the QR stub that closes the loop between paper and phone. */
.c-bill{
  margin:0;padding-block:.5rem .55rem;
  font-family:var(--display);font-weight:800;
  font-size:clamp(.6rem,1.28vw,.72rem);letter-spacing:.13em;text-transform:uppercase;
  line-height:1.35;opacity:.92;
  border-top:1px solid color-mix(in srgb,var(--accent-ink) 40%,transparent);
}
.c-door{
  margin:0;padding-block:.5rem .5rem;
  font-family:var(--display);font-weight:700;
  font-size:clamp(.56rem,1.16vw,.66rem);letter-spacing:.14em;text-transform:uppercase;
  opacity:.82;border-top:1px solid color-mix(in srgb,var(--accent-ink) 26%,transparent);
}
.c-strip{
  display:flex;align-items:center;justify-content:space-between;gap:.75rem;
  padding-block:.55rem;
  border-top:3px solid var(--accent-ink);
  font-family:var(--display);font-weight:800;
  font-size:clamp(.56rem,1.16vw,.66rem);letter-spacing:.14em;text-transform:uppercase;
}
/* A QR block drawn in CSS — the loop from the printed sheet back to the listing,
   and zero bytes for something that only has to read as one at this size. */
.c-qr{
  width:2.1rem;height:2.1rem;flex:none;
  background:
    linear-gradient(var(--accent-ink) 0 0) 0 0/38% 38% no-repeat,
    linear-gradient(var(--accent-ink) 0 0) 100% 0/38% 38% no-repeat,
    linear-gradient(var(--accent-ink) 0 0) 0 100%/38% 38% no-repeat,
    repeating-linear-gradient(90deg,var(--accent-ink) 0 12%,transparent 12% 25%) 100% 100%/56% 56% no-repeat;
}
.c-foot{border-top:0;padding-block:.35rem .85rem}
@media (max-width:34rem){ .c-bill,.c-door{letter-spacing:.1em} }

/* ============================================================
   Density corrections — fill the room rather than leaving it empty
   ------------------------------------------------------------
   The rhythm from the spacing pass is right; what was wrong is that some
   blocks were not big enough to occupy it, so the air read as a gap rather
   than as breathing room.
   ============================================================ */

/* --- the numbered steps had zero left padding, so 01 sat on the divider --- */
.steps{border-top:var(--rw-heavy) solid var(--ink);border-bottom:1px solid var(--hair)}
.step{
  padding:clamp(1.4rem,2.6vw,2rem) clamp(1.2rem,2.4vw,1.9rem) clamp(1.6rem,3vw,2.3rem);
  border-right:1px solid var(--hair);
}
.step:first-child{padding-left:0}
.step:last-child{padding-right:0}
.step .n{
  font-size:clamp(2.2rem,4.6vw,3.1rem);line-height:.9;margin:0 0 .55rem;
  opacity:.9;
}
.step svg.i{width:2.2em;height:2.2em;margin:0 0 1rem;color:var(--accent)}
.step h3{font-size:var(--t-t1);margin:0 0 .5rem}
.step p{font-size:var(--t-body);line-height:1.55;margin:0}
@media (max-width:52rem){
  .step,.step:first-child,.step:last-child{
    padding:clamp(1.3rem,4vw,1.7rem) 0;border-right:0;border-bottom:1px solid var(--hair);
  }
  .step:last-child{border-bottom:0}
}

/* --- the flyer: taller, and it fills its column --- */
.herogrid{align-items:stretch}
.cartel{
  display:flex;flex-direction:column;padding:0;
  min-height:clamp(26rem,44vw,36rem);
  box-shadow:14px 14px 0 var(--slab);
}
.cartel::before{display:none}          /* the register strip fought the eyebrow */
.cartel > *{padding-inline:clamp(1.2rem,2.6vw,2rem)}
.c-title{font-size:clamp(2.9rem,8.2vw,5.2rem);padding-block:clamp(.9rem,2.2vw,1.5rem) clamp(.6rem,1.6vw,.9rem)}
.c-bill{padding-block:.65rem .7rem}
.c-when{padding-block:clamp(.9rem,2vw,1.3rem)}
.c-date i{font-size:clamp(2.2rem,5.2vw,3.2rem)}
.c-foot{padding-block:.5rem clamp(1rem,2vw,1.4rem)}
@media (max-width:56rem){
  .cartel{min-height:clamp(24rem,70vw,30rem);box-shadow:8px 8px 0 var(--slab)}
}

/* --- illustrations carry the width they were drawn for --- */
.illus-wrap{margin:var(--l-xs) 0 0}
.illus-wrap .illus{max-width:100%;width:100%}
.illus-wrap figcaption{max-width:62ch;font-size:var(--t-body)}
.illus-duo{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(min(19rem,100%),1fr));
  gap:clamp(1.5rem,3.5vw,2.75rem);align-items:center;margin:var(--l-xs) 0 0;
}
.illus-duo .illus{max-width:100%}
.illus-duo p{margin:0;color:var(--ink-2);font-size:var(--t-read)}

/* --- cards fill their space instead of floating in it --- */
.card{padding:clamp(1.5rem,3vw,2.1rem) clamp(1.3rem,2.6vw,1.9rem) clamp(1.8rem,3.4vw,2.4rem)}
.card h2,.card h3{font-size:var(--t-t1);margin-bottom:.55rem}
.card p{font-size:var(--t-body);line-height:1.58}
.card-icon svg.i{width:2.3em;height:2.3em;margin-bottom:.9rem}
.g3{grid-template-columns:repeat(auto-fit,minmax(min(18rem,100%),1fr))}
.chips{gap:.55rem}
.chip{padding:.6rem 1rem;font-size:var(--t-sm)}

/* The category grid is the glyph set doing real work — ten links that fill the
   band instead of a chip cloud floating in it. */
.catgrid{border-top:var(--rw-heavy) solid var(--ink);border-left:1px solid var(--hair)}
.catgrid .card{
  border:0;border-right:1px solid var(--hair);border-bottom:1px solid var(--hair);
  padding:clamp(1.2rem,2.4vw,1.7rem) clamp(1rem,2vw,1.4rem) clamp(1.4rem,2.8vw,1.9rem);
  display:flex;flex-direction:column;gap:.2rem;min-height:8.5rem;justify-content:flex-end;
}
.catgrid .card h2,.catgrid .card h3{font-size:var(--t-t2);margin:0;line-height:1.2}
.catgrid .card svg.i{margin:0 0 auto;width:2.1em;height:2.1em}
.catgrid .card:hover{background:var(--accent-tint)}
.catgrid .card.is-free svg.i{color:var(--free)}
.h-sub{font-size:var(--t-t1)}

/* --- the stat ledger had no padding and its labels were too small to read
       as anything but filler. Give it room and give the words weight. --- */
.stats{
  border-top:var(--rw-heavy) solid currentColor;
  border-left:1px solid color-mix(in srgb,currentColor 22%,transparent);
}
.stats div{
  padding:clamp(1.3rem,2.8vw,2rem) clamp(1.1rem,2.2vw,1.6rem) clamp(1.5rem,3vw,2.2rem);
  border-right:1px solid color-mix(in srgb,currentColor 22%,transparent);
  border-bottom:1px solid color-mix(in srgb,currentColor 22%,transparent);
}
.stats b{
  font-size:clamp(1.9rem,4.4vw,2.9rem);line-height:1;letter-spacing:-.03em;
  display:block;margin:0 0 .5rem;
}
.stats span{
  font-size:var(--t-body);line-height:1.35;letter-spacing:.01em;
  text-transform:none;opacity:.9;max-width:16ch;display:block;
}
.band.ink .stats span{color:rgba(255,255,255,.82)}
.two-aud{margin-top:var(--l-sm)}
.two-aud .illus{max-width:44rem;margin-inline:auto}
.two-aud figcaption{max-width:66ch;margin-inline:auto;text-align:center}
.band.ink figcaption{color:rgba(255,255,255,.72)}

/* --- the middle of the sheet, where a real flyer packs the most in --- */
.c-pres{
  margin:0;padding-block:.55rem .25rem;
  font-family:var(--display);font-weight:700;
  font-size:clamp(.52rem,1.05vw,.6rem);letter-spacing:.3em;text-transform:uppercase;
  opacity:.72;border-top:1px solid color-mix(in srgb,var(--accent-ink) 40%,transparent);
}
.c-bill{
  border-top:0;padding-block:0 .35rem;
  font-size:clamp(.72rem,1.6vw,.92rem);letter-spacing:.09em;line-height:1.3;
  opacity:1;
}
.c-genres{
  margin:0;padding-block:.3rem .45rem;
  font-family:var(--display);font-weight:900;
  font-size:clamp(.62rem,1.34vw,.76rem);letter-spacing:.19em;text-transform:uppercase;
  border-top:1px solid color-mix(in srgb,var(--accent-ink) 26%,transparent);
  border-bottom:1px solid color-mix(in srgb,var(--accent-ink) 26%,transparent);
}
.c-hype{
  margin:0;padding-block:.5rem .3rem;
  font-family:var(--display);font-weight:700;
  font-size:clamp(.58rem,1.2vw,.68rem);letter-spacing:.15em;text-transform:uppercase;
  opacity:.85;line-height:1.45;
}
.c-tix{
  margin:0;padding-block:.15rem .5rem;
  font-family:var(--display);font-weight:800;
  font-size:clamp(.56rem,1.16vw,.66rem);letter-spacing:.14em;text-transform:uppercase;
  opacity:.78;line-height:1.45;
}
/* the date row no longer has to absorb the slack, so it stops floating */
.c-when{margin-top:0;border-top:3px solid var(--accent-ink)}
.c-foot{margin-top:auto}

/* --- wait-board cell spacing ------------------------------------------
   td.num zeroes its right padding, which is right when the number is the last
   column and wrong here, where five numeric columns sit between the crossing
   name and the update time. Without it "Closed" runs straight into "At 2:00 am
   CDT" with nothing between them. */
table.bwt td,
table.bwt th{padding-block:.8rem}
table.bwt td.num{padding-inline:1.15rem 0}
table.bwt td.num:first-of-type{padding-left:.5rem}
table.bwt .bwt-upd{padding-left:1.6rem;text-align:right;white-space:nowrap}
table.bwt thead th{padding-block:.7rem;padding-inline:1.15rem 0}
table.bwt thead th:first-child{padding-left:0}
table.bwt thead th:last-child{padding-left:1.6rem;text-align:right}
table.bwt th[scope=row]{padding-right:1.6rem;padding-left:0}
/* a hairline between the name and the numbers, so the eye has an anchor */
table.bwt th[scope=row]{border-right:1px solid var(--hair)}
table.bwt td.num:first-of-type{padding-left:1.15rem}

/* --- header/data alignment ---------------------------------------------
   td.num right-aligns the numbers, but the rule only matched td, so every
   numeric column header stayed left-aligned above a right-aligned number.
   Structurally the columns were correct; visually nothing lined up. */
th.num{text-align:right}
table.bwt thead th.num{padding-inline:1.15rem 0;text-align:right}
table.bwt thead th:first-child{text-align:left;padding-left:0}
/* the crossing name column carries the same right edge as its rows */
table.bwt thead th:first-child{padding-right:1.6rem;border-right:1px solid var(--hair)}
