/* =============================================================================
   THE CITY GUIDES — labs.llc/nyc/, /miami/, /mke/, /la/
   =============================================================================

   One sheet, four properties. It loads AFTER assets/css/site.css, which brings
   the tokens, the navbar, the hamburger, the bands, the type and the footer;
   everything here is the four things a city guide has that the rest of the site
   does not: a framed picture, a card, a gallery and a reading sheet.

   NOT ONE COLOUR IS A LITERAL. Every value is a house token or derived from
   one, which is what makes the dark edition a palette swap rather than a second
   stylesheet — assets/css/dark.css repoints --ink, --paper, --line and --accent
   under html[data-dark] and this file follows without being told.

   THE PICTURES ARE FRAMED. The guides these replace laid every photograph under
   the type as a `background-image` with `background-size: cover`, including a
   full-viewport hero with `background-attachment: fixed`. A background is not a
   picture: it cannot be printed, it has no alt text, it cannot be saved, it
   cannot lazy-load, and it is cropped by whatever the window happens to be. Here
   every one of them is an <img> in a box with a stated aspect ratio.
   ========================================================================== */

/* ------------------------------------------------------------------ frames */
.cf {
    position: relative;
    display: block;
    width: 100%;
    overflow: hidden;
    border-radius: 10px;
    background: color-mix(in srgb, var(--ink) 6%, var(--paper));
    border: 1px solid var(--line);
}
.cf img {
    display: block;
    width: 100%; height: 100%;
    object-fit: cover;
    /* A photograph in the paper edition is a photograph; in the dark one it is
       one shade quieter, so a wall of them does not glare off the ground. */
    transition: transform .5s var(--ease);
}
html[data-dark] .cf img { filter: brightness(.94) saturate(.96); }
.c:hover .cf img, .gcell:hover .cf img { transform: scale(1.03); }
/* An entry whose picture never arrived is a frame, not a hole. */
.cf--none { background: repeating-linear-gradient(135deg, var(--line-soft) 0 6px, transparent 6px 12px); }

/* A BORROWED ROOM, DRAWN AS ONE. `.cf--stand` is a frame whose picture is a
   New York dining room rather than a photograph of the restaurant on the card
   — see standIn() in js/register.js. It is held back a little from a real
   plate: slightly desaturated and a touch lighter, so the 714 that ARE
   photographed still read as the photographed ones and the page's own figure
   stays honest. Not so far back that it looks broken; this is a stand-in, not
   a fault. */
.cf--stand img { filter: saturate(.62) contrast(.96); opacity: .88; }
html[data-dark] .cf--stand img { filter: saturate(.55) contrast(.94) brightness(.86); opacity: .82; }
.r:hover .cf--stand img,
.r:focus-visible .cf--stand img { filter: saturate(.86) contrast(1); opacity: 1; }

/* -------------------------------------------------------------------- hero
   Text on the left, ONE framed picture on the right. It is not 100dvh and it
   is not fixed: the first thing a guide should do is start. */
.hero { padding: clamp(1.6rem, 4vw, 3.2rem) 0 clamp(1.4rem, 3vw, 2.4rem); }
.hero__in {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    gap: clamp(1.2rem, 3vw, 2.6rem);
    align-items: center;
}
.hero__t .d1 { margin: .2rem 0 .5rem; }
.cf--hero { border-radius: 14px; }
.hstats { display: flex; flex-wrap: wrap; gap: 1.4rem; margin-top: 1.4rem; }
.hstat b {
    display: block; font-size: 1.5rem; font-weight: 600; letter-spacing: -.03em;
    color: var(--accent); font-variant-numeric: tabular-nums;
}
.hstat span {
    display: block; font-size: .55rem; font-weight: 700;
    letter-spacing: .2em; text-transform: uppercase; color: var(--ink-55);
}
@media (max-width: 860px) {
    .hero__in { grid-template-columns: minmax(0, 1fr); }
}

/* ------------------------------------------------------------ group header */
.ghead {
    display: flex; align-items: center; justify-content: space-between;
    flex-wrap: wrap; gap: .8rem;
    margin: 1.2rem 0 1rem;
    padding-bottom: .7rem;
    border-bottom: 1px solid var(--line);
}
.gcount {
    font-size: .6rem; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
    color: var(--ink-55);
}
.gcount b { color: var(--accent); font-size: .85rem; letter-spacing: 0; }
.gbar { display: flex; flex-wrap: wrap; gap: .3rem; }

/* -------------------------------------------------------------------- cards
   minmax(0, 1fr) on the track, never 1fr: a 1fr track grows to min-content, and
   one unbroken hotel name would then set the width of every other card in the
   row — the same trap the shelf and the register both carry a note about. */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr));
    gap: 1rem;
}
.c {
    display: flex; flex-direction: column;
    min-width: 0;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--paper);
    overflow: hidden;
    transition: border-color .2s var(--ease), transform .2s var(--ease);
}
.c:hover { border-color: var(--ink); transform: translateY(-2px); }
.c[hidden] { display: none; }
.c .cf { border: 0; border-radius: 0; border-bottom: 1px solid var(--line); }
.c__b { display: flex; flex-direction: column; gap: .35rem; padding: .85rem .9rem 1rem; flex: 1 1 auto; }
.c__n { margin: 0; font-size: 1.02rem; font-weight: 600; letter-spacing: -.02em; line-height: 1.25; }
.c__sub {
    margin: 0; font-size: .62rem; font-weight: 700;
    letter-spacing: .14em; text-transform: uppercase; color: var(--accent);
}
.c__m {
    display: flex; flex-wrap: wrap; gap: .55rem;
    font-size: .68rem; color: var(--ink-55);
    font-variant-numeric: tabular-nums;
}
.c__m b { color: var(--ink); font-weight: 600; }
.c__d { margin: .1rem 0 0; font-size: .82rem; line-height: 1.5; color: var(--ink-77); }
.c__t { display: flex; flex-wrap: wrap; gap: .3rem; margin-top: .1rem; }
.tag {
    font-size: .58rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase;
    padding: .18rem .42rem; border-radius: 999px;
    border: 1px solid var(--line); color: var(--ink-55);
}
.c__go {
    -webkit-appearance: none; appearance: none;
    margin-top: auto; padding: .55rem 0 0;
    background: none; border: 0; border-top: 1px solid var(--line-soft);
    display: flex; align-items: center; justify-content: space-between; gap: .6rem;
    font: inherit; font-size: .62rem; font-weight: 700;
    letter-spacing: .16em; text-transform: uppercase;
    color: var(--ink-55); cursor: pointer; text-align: left;
    transition: color .18s var(--ease);
}
.c__go:hover { color: var(--accent); }
.c__go i { font-style: normal; transition: transform .18s var(--ease); }
.c__go:hover i { transform: translateX(3px); }
.c__go:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* ------------------------------------------------------------------ gallery */
.gal {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(14rem, 100%), 1fr));
    gap: .8rem;
}
.gcell {
    -webkit-appearance: none; appearance: none;
    display: flex; flex-direction: column; gap: .4rem;
    padding: 0; background: none; border: 0;
    font: inherit; text-align: left; cursor: zoom-in; min-width: 0;
}
.gcell span { font-size: .72rem; color: var(--ink-55); line-height: 1.4; }
.gcell:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* --------------------------------------------------------------- the wire */
.wgrid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr));
    gap: .9rem;
}
.w {
    display: flex; flex-direction: column; gap: .5rem; min-width: 0;
    padding: .9rem 1rem 1rem;
    border: 1px solid var(--line); border-radius: 12px; background: var(--paper);
}
.w__h { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; }
.w__h b { font-size: .88rem; font-weight: 600; letter-spacing: -.01em; }
.w__h span { font-size: .6rem; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-55); }
.w p { margin: 0; font-size: .84rem; line-height: 1.55; color: var(--ink-77); }

/* ---------------------------------------------------------- the whole entry
   A sheet rather than a modal box: the records are long — a hotel carries its
   full description, its amenities, a pro tip and the feel of the place — and a
   centred box that scrolls inside itself is a worse reading surface than a
   column that comes in from the side and scrolls like a page. */
.sheet { position: fixed; inset: 0; z-index: 120; }
.sheet[hidden] { display: none; }
.sheet__scrim {
    position: absolute; inset: 0;
    background: color-mix(in srgb, var(--ink) 55%, transparent);
    opacity: 0; transition: opacity .28s var(--ease);
}
.sheet.is-open .sheet__scrim { opacity: 1; }
.sheet__p {
    position: absolute; top: 0; right: 0; bottom: 0;
    width: min(46rem, 100%);
    background: var(--paper);
    border-left: 1px solid var(--line);
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    transform: translateX(100%);
    transition: transform .34s var(--ease);
}
.sheet.is-open .sheet__p { transform: none; }
.sheet__x {
    position: sticky; top: .7rem; float: right; margin: .7rem .9rem 0 0;
    -webkit-appearance: none; appearance: none;
    width: 2rem; height: 2rem; display: inline-flex; align-items: center; justify-content: center;
    background: var(--paper); border: 1px solid var(--line); border-radius: 999px;
    color: var(--ink-55); cursor: pointer; z-index: 2;
}
.sheet__x svg { width: 14px; height: 14px; }
.sheet__x:hover { color: var(--accent); border-color: var(--accent); }
.sheet__b { padding: 1.4rem clamp(1.1rem, 3vw, 2.2rem) 3rem; }
.sheet__b .cf { margin-bottom: 1.1rem; }
.sheet__b h2 { margin: 0 0 .2rem; font-size: clamp(1.5rem, 3.4vw, 2.1rem); letter-spacing: -.03em; }
.sheet__b .s-sub {
    font-size: .62rem; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
    color: var(--accent); margin: 0 0 1rem;
}
.sheet__b p { font-size: .92rem; line-height: 1.65; color: var(--ink-77); }
.s-meta {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
    gap: .7rem 1rem; margin: 1.1rem 0;
    padding: .9rem 0; border-block: 1px solid var(--line-soft);
}
.s-meta div b {
    display: block; font-size: .95rem; font-weight: 600; color: var(--ink);
    font-variant-numeric: tabular-nums;
}
.s-meta div span {
    display: block; font-size: .55rem; font-weight: 700;
    letter-spacing: .18em; text-transform: uppercase; color: var(--ink-55);
}
.s-h {
    margin: 1.5rem 0 .5rem;
    font-size: .6rem; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
    color: var(--ink-55);
}
.s-list { margin: 0; padding-left: 1.1rem; }
.s-list li { font-size: .86rem; line-height: 1.6; color: var(--ink-77); margin-bottom: .3rem; }
.s-note {
    margin: .5rem 0 0; padding: .75rem .9rem;
    border: 1px solid var(--line); border-left: 2px solid var(--accent); border-radius: 8px;
    font-size: .85rem; line-height: 1.55; color: var(--ink-77);
    background: color-mix(in srgb, var(--accent) 4%, transparent);
}
.s-shots { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: .5rem; margin-top: .7rem; }
.s-links { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .8rem; }

/* ------------------------------------------------------------- the lightbox */
.lb { position: fixed; inset: 0; z-index: 130; display: grid; place-items: center; padding: 4vmin; }
.lb[hidden] { display: none; }
.lb__scrim { position: absolute; inset: 0; background: color-mix(in srgb, var(--ink) 72%, transparent); }
.lb figure { position: relative; margin: 0; max-width: min(80rem, 100%); }
.lb img {
    display: block; max-width: 100%; max-height: 78svh;
    border-radius: 12px; border: 1px solid var(--line); background: var(--paper);
}
.lb figcaption {
    margin-top: .6rem; font-size: .78rem; color: var(--paper);
    text-align: center;
}
html:not([data-dark]) .lb figcaption { color: var(--paper); }
.lb__x, .lb__n, .lb__p {
    position: absolute; -webkit-appearance: none; appearance: none;
    width: 2.4rem; height: 2.4rem; display: inline-flex; align-items: center; justify-content: center;
    background: var(--paper); border: 1px solid var(--line); border-radius: 999px;
    color: var(--ink); cursor: pointer; font: inherit; font-size: 1rem;
}
.lb__x { top: -1.2rem; right: -1.2rem; }
.lb__p { left: -1.2rem; top: 50%; margin-top: -1.2rem; }
.lb__n { right: -1.2rem; top: 50%; margin-top: -1.2rem; }
@media (max-width: 700px) {
    .lb__x { top: -1rem; right: 0; }
    .lb__p { left: 0; top: auto; bottom: -3.4rem; margin: 0; }
    .lb__n { right: 0; top: auto; bottom: -3.4rem; margin: 0; }
}


/* ================================================================ the fold
   Sixty-five pictures is a scroll, not a gallery. The first twenty-four are
   laid out and the rest are in the markup behind an attribute — the rule below
   only bites once city.js has set data-folded, so a reader without JavaScript
   gets all of them and no button rather than a button that does nothing. */
.gal[data-folded] .gcell[data-fold] { display: none; }
.gmore {
    -webkit-appearance: none; appearance: none;
    display: block; width: 100%; margin-top: 1rem; padding: .7rem 1rem;
    background: none; border: 1px solid var(--line); border-radius: 10px;
    color: var(--ink-77); cursor: pointer;
    font: inherit; font-size: .72rem; font-weight: 600;
    letter-spacing: .1em; text-transform: uppercase;
    transition: border-color .2s var(--ease), color .2s var(--ease);
}
.gmore:hover { border-color: var(--ink-55); color: var(--ink); }
.gmore:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gmore[hidden] { display: none; }

/* A gallery cell now carries three things: the plate, what it is, and where.
   The badge sits ON the plate because that is where the original put it and
   it is the one place it costs no line of type. */
.gcell__f { position: relative; display: block; }
.gcell__t {
    position: absolute; right: .4rem; bottom: .4rem;
    font-size: .53rem; font-weight: 700; font-style: normal;
    letter-spacing: .09em; text-transform: uppercase;
    padding: .16rem .38rem; border-radius: 999px;
    background: color-mix(in srgb, var(--paper) 88%, transparent);
    border: 1px solid var(--line);
    color: var(--ink-77);
    backdrop-filter: blur(3px);
}
.gcell__c { font-size: .74rem; color: var(--ink); line-height: 1.35; }
.gcell__w { font-size: .68rem; color: var(--ink-55); line-height: 1.35; }

/* The plate says the rest of it. Five lines of type over a 72% scrim let the
   page underneath read through them, so the caption gets its own ground. */
.lb figcaption {
    display: grid; gap: .3rem; max-width: 46rem; margin-inline: auto; text-align: left;
    padding: .7rem .9rem; border-radius: 10px;
    background: color-mix(in srgb, var(--ink) 82%, transparent);
    backdrop-filter: blur(6px);
}
.lb figcaption b { font-size: .92rem; }
.lb__w { font-size: .72rem; opacity: .72; letter-spacing: .04em; text-transform: uppercase; }
.lb__d { font-size: .8rem; line-height: 1.5; opacity: .92; }
.lb__f { font-size: .74rem; line-height: 1.5; opacity: .72; }
.lb__f i { font-style: normal; font-weight: 700; letter-spacing: .06em;
           text-transform: uppercase; font-size: .62rem; margin-right: .35rem; }

/* ============================================================== summerfest
   Not a card grid: a festival with a stat row, a legacy panel that carries its
   own figures, a lineup that is a bag of names, and two columns of advice. All
   of it in the house's own furniture — bands, frames, tags, hairlines. */
.sfwhen {
    display: flex; flex-wrap: wrap; gap: .4rem 1.2rem;
    margin: .2rem 0 1.2rem;
    font-size: .68rem; font-weight: 600; letter-spacing: .09em;
    text-transform: uppercase; color: var(--ink-55);
}
.sfhero {
    display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: clamp(1rem, 2.4vw, 2rem); align-items: center;
    padding-bottom: clamp(1.2rem, 2.6vw, 2rem);
    border-bottom: 1px solid var(--line-soft);
}
.sfhero__b h3 { font-size: clamp(1.3rem, 2.6vw, 2rem); line-height: 1.15; margin: .2rem 0 .5rem; }
.sfhero__b p { color: var(--ink-77); line-height: 1.6; margin: 0 0 .9rem; }
.sfbtn, .sflink {
    display: inline-flex; align-items: center; gap: .35rem;
    font-size: .7rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
    color: var(--ink); text-decoration: none;
    border-bottom: 1px solid var(--accent); padding-bottom: .15rem;
}
.sfbtn:hover, .sflink:hover { color: var(--accent); }
.sfstats {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(8rem, 100%), 1fr));
    gap: .8rem; margin: clamp(1.2rem, 2.6vw, 2rem) 0;
}
.sfstat { display: flex; flex-direction: column; gap: .15rem; min-width: 0;
          padding: .8rem .9rem; border: 1px solid var(--line); border-radius: 12px; background: var(--paper); }
.sfstat b { font-size: clamp(1.3rem, 2.6vw, 1.9rem); line-height: 1; }
.sfstat span { font-size: .68rem; color: var(--ink-55); letter-spacing: .04em; }
.sfsub { margin-top: clamp(1.2rem, 2.6vw, 2rem); }
.sfh { font-size: clamp(1.15rem, 2.2vw, 1.6rem); margin: .1rem 0 1rem; }
.sfgrid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
    gap: .9rem;
}
.sfs { display: flex; flex-direction: column; gap: .5rem; min-width: 0; }
.sfs__b h4 { font-size: .88rem; margin: 0 0 .15rem; }
.sfs__b p { font-size: .74rem; color: var(--ink-55); margin: 0; line-height: 1.4; }
.sfpanels {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    gap: .9rem; margin-top: clamp(1.2rem, 2.6vw, 2rem);
}
.sfp {
    min-width: 0; padding: 1rem 1.1rem 1.1rem;
    border: 1px solid var(--line); border-radius: 12px; background: var(--paper);
}
.sfp h4 { font-size: 1rem; margin: .1rem 0 .6rem; }
.sfp p { font-size: .82rem; line-height: 1.6; color: var(--ink-77); margin: 0 0 .6rem; }
.sffigs { display: flex; flex-wrap: wrap; gap: .8rem 1.4rem; padding-top: .6rem; border-top: 1px solid var(--line-soft); }
.sffig { display: flex; flex-direction: column; }
.sffig b { font-size: 1.05rem; line-height: 1.1; }
.sffig span { font-size: .64rem; color: var(--ink-55); }
.sfchips { display: flex; flex-wrap: wrap; gap: .32rem; margin-bottom: .7rem; }
.sfnote { font-size: .72rem !important; color: var(--ink-55) !important; }
.sflist { margin: 0; padding-left: 1.05rem; display: grid; gap: .38rem; }
.sflist li { font-size: .8rem; line-height: 1.55; color: var(--ink-77); }
.sfsmall {
    margin-top: 1.1rem; padding-top: .7rem; border-top: 1px solid var(--line-soft);
    font-size: .68rem; color: var(--ink-55); line-height: 1.5;
}
@media (max-width: 760px) { .sfhero { grid-template-columns: minmax(0, 1fr); } }

/* A festival with no photograph of its own — the original's was on somebody
   else's server — should not leave half the row empty waiting for one. */
.sfhero--flat { grid-template-columns: minmax(0, 1fr); }
.sfhero--flat .sfhero__b { max-width: var(--measure, 46rem); }


/* ============================================================== city vibe */
.vgrid {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    gap: .9rem;
}
.vp {
    display: flex; flex-direction: column; gap: .5rem; min-width: 0;
    padding: 1rem 1.1rem 1.1rem;
    border: 1px solid var(--line); border-radius: 12px; background: var(--paper);
}
.vp h3 { font-size: 1.1rem; margin: 0; }
.vp__s { font-size: .7rem !important; font-weight: 600; letter-spacing: .07em;
         text-transform: uppercase; color: var(--accent); margin: 0 !important; }
.vp p { font-size: .84rem; line-height: 1.6; color: var(--ink-77); margin: 0; }
.vp__t { display: flex; flex-wrap: wrap; gap: .32rem; }
.vp .cf { margin-top: auto; }
.vstrip {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
    gap: 1rem; margin-top: .9rem; padding: 1rem 1.1rem;
    border: 1px solid var(--line); border-radius: 12px; background: var(--paper);
}
.vstrip__c { min-width: 0; }
.vstrip__l {
    font-size: .66rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
    color: var(--accent); margin: 0 0 .3rem;
}
.vstrip__c p { font-size: .8rem; line-height: 1.6; color: var(--ink-77); margin: 0; }

/* The bar's one way off the site. */
.nav__out { display: inline-flex; align-items: center; gap: .25rem; }
.nav__out i { font-style: normal; font-size: .82em; opacity: .7; }


/* ============================================================== the bands
   THE GAP BETWEEN SECTIONS. site.css sets --band to clamp(64px, 9vw, 128px),
   which is right for a page with four things on it: on a wide screen that is
   128px of air under one section and 128px over the next, a quarter of a
   laptop screen of nothing between the last card of the hotels and the word
   RESTAURANTS. These guides are catalogues — a dozen bands, hundreds of cards
   — and at that measure the reader spends the scroll in the margins. Halved
   here, and here only, so the rest of the site keeps its editorial air.

   The RULE, not the padding, is what separates them: each band already draws
   its own ground, and the tinted ones still read as a change of ground. */
.band { --band: clamp(22px, 2.2vw, 34px); }

/* Two bands of the same ground touching read as one long band, so the second
   one gets a hairline to say where it started. */
.band + .band:not(.band--tint):not(.band--deep) { border-top: 1px solid var(--line-soft); }
.band--tint + .band--tint { border-top: 1px solid var(--line-soft); }

/* ------------------------------------------------------------------- print
   A guide is a thing people print before a trip. The chrome goes, the frames
   stay, and a card is not allowed to break across a page. */
@media print {
    .nav, .menu, .sheet, .lb, .gbar, .c__go, .foot__links { display: none !important; }
    .c, .w { break-inside: avoid; border-color: #ccc; }
    .band { padding: .6rem 0 !important; }
}

@media (prefers-reduced-motion: reduce) {
    .cf img, .c, .sheet__p, .sheet__scrim { transition: none; }
}

/* =============================================================================
   THE TABLE — the NYC restaurant register
   =============================================================================

   A thousand restaurants is not a longer version of twenty-six. The card grid
   above works because a card is worth its space when there are two dozen of
   them; at a thousand the same card is four screens of scrolling per borough
   and the reader never reaches the pizza. So the register is its own object:
   a dense row, a bar of shelves above it, and a page size — the reader narrows
   first and reads second, which is the opposite way round from the guide.

   NOT ONE COLOUR IS A LITERAL, same as the rest of this sheet. Every value is a
   house token, which is what lets assets/css/dark.css repoint --ink and --paper
   and get a working dark edition without a second copy of any of this.
   ========================================================================== */

.reg { margin-top: 1rem; }

/* --------------------------------------------------------------- the shelves
   Sticky, because the whole point of a register is to change your mind about
   what you are looking for while you are looking at it. It stops under the
   navbar rather than at the top of the window. */
/* A GRID, BECAUSE A SELECT SIZES ITSELF TO ITS LONGEST OPTION.

   As a flex row with `flex: 0 1 auto` on each field, every select took the
   width of the longest line in its own menu — text nobody sees until they open
   it. Measured at 1440: 145, 238, 154 and 111 px, four unrelated widths in a
   row of four identical controls, and the 238 was Section being sized by
   "Russian & Eastern European · 78". That is the disjointed, sprawling look;
   it was never a spacing problem.

   So the four selects get ONE shared track and the search takes the rest.
   `minmax(0, …)` on the flexible track is what stops the content setting the
   width again — a bare `1fr` floors at min-content and the longest option wins
   all over again. 9.4rem holds every field's DEFAULT label, and the widest of
   those is "All five boroughs" at 139px.

   The bar is compacter too: .55rem of padding rather than .7, and the fields
   .42/.6 rather than .5/.65. Nothing lost but air. */
.reg__bar {
    position: sticky;
    top: calc(var(--nav-h, 58px) - 1px);
    z-index: 6;
    display: grid;
    grid-template-columns: minmax(0, 1fr) repeat(4, 9.4rem) auto auto;
    align-items: center;
    gap: .45rem;
    padding: .55rem 0;
    background: var(--paper);
    border-bottom: 1px solid var(--line);
}
.reg__find { min-width: 0; }
.reg__find input,
.reg__sel select {
    width: 100%;
    font: inherit;
    /* 16px on a touch screen, always: below it iOS Safari zooms the page on
       focus and carries the sticky bar off the top of the screen. */
    font-size: 16px;
    color: var(--ink);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: .42rem .6rem;
    appearance: none;
    -webkit-appearance: none;
}
@media (pointer: fine) {
    .reg__find input, .reg__sel select { font-size: .84rem; }
}
.reg__find input::placeholder { color: var(--ink-55); }
.reg__find input:focus-visible,
.reg__sel select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.reg__sel { min-width: 0; }
.reg__sel select { padding-right: 1.6rem; cursor: pointer; text-overflow: ellipsis; }

/* THE BAR FOLDS RATHER THAN SQUEEZES.

   Four 9.4rem selects, two buttons and a search box need about 1000px. Below
   that the search takes a line of its own — it is the widest thing in the bar
   and the one that suffers most from being narrow — and the six controls under
   it stay on one row of equal tracks. Below 720 they go two up, still equal.
   At no width does a field end up a different size from the one beside it,
   which was the whole complaint. */
@media (max-width: 1040px) {
    .reg__bar { grid-template-columns: repeat(4, minmax(0, 1fr)) auto auto; }
    .reg__find { grid-column: 1 / -1; }
}
@media (max-width: 760px) {
    .reg__bar { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .reg__find { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
    .reg__bar { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.reg__k {
    font: inherit;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    /* A <button> in this site's chrome needs its own reset or the browser
       renders it as a framed grey box. */
    color: var(--ink-77);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: .5rem .8rem;
    cursor: pointer;
    transition: color .16s var(--ease), border-color .16s var(--ease);
}
.reg__k:hover { color: var(--ink); border-color: var(--ink); }
.reg__k.is-on {
    color: var(--paper);
    background: var(--accent);
    border-color: var(--accent);
}

/* ------------------------------------------------------------------- chips
   The sections the reader actually arrives wanting: pizza, dessert, steak.
   They are the same filter as the section menu, kept in step by register.js. */
.reg__chips {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin: .85rem 0 .1rem;
}
.reg__chip {
    font: inherit;
    font-size: .64rem;
    font-weight: 700;
    letter-spacing: .13em;
    text-transform: uppercase;
    color: var(--ink-55);
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: .34rem .7rem;
    cursor: pointer;
    transition: color .16s var(--ease), border-color .16s var(--ease), background .16s var(--ease);
}
.reg__chip:hover { color: var(--ink); border-color: var(--ink); }
.reg__chip.is-on {
    color: var(--paper);
    background: var(--ink);
    border-color: var(--ink);
}
.reg__chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.reg__head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: .6rem;
    margin: .9rem 0 .8rem;
}
.reg__count {
    font-size: .6rem; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
    color: var(--ink-55);
}
.reg__count b { color: var(--accent); font-size: .85rem; letter-spacing: 0; }
.reg__clear {
    font: inherit; font-size: .68rem; color: var(--ink-55);
    background: none; border: 0; padding: 0; cursor: pointer;
    text-decoration: underline; text-underline-offset: 3px;
}
.reg__clear:hover { color: var(--accent); }

/* --------------------------------------------------------------- the rows
   The track floor is `min(100%, 15.5rem)` rather than a bare 15.5rem so a
   phone narrower than the floor still gets one full-width column instead of a
   row that overflows the document — and an overflowing row widens the page and
   every fixed thing on it.

   NOT `minmax(min(100%, 15.5rem), minmax(0, 1fr))`. minmax() does not nest;
   the whole declaration is invalid, the browser drops it, and the register
   silently renders as ONE column a screen and a half wide. It looked like a
   layout preference rather than a parse error, which is what made it worth a
   note. A stated floor is already immune to the min-content growth that makes
   `minmax(0, 1fr)` necessary on the card grid above. */
.reg__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 15.5rem), 1fr));
    gap: .55rem;
}
.r {
    display: grid;
    grid-template-columns: 4.6rem minmax(0, 1fr);
    gap: .7rem;
    align-items: stretch;
    padding: 0;
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 10px;
    overflow: hidden;
    cursor: pointer;
    text-align: left;
    transition: border-color .16s var(--ease), transform .16s var(--ease);
}
.r:hover { border-color: var(--ink); transform: translateY(-1px); }
.r:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.r.is-out { display: none; }
.r .cf {
    border: 0;
    border-radius: 0;
    border-right: 1px solid var(--line);
    height: 100%;
    aspect-ratio: auto;
}
.r__b {
    display: flex;
    flex-direction: column;
    gap: .12rem;
    padding: .55rem .6rem .6rem 0;
    min-width: 0;
}
.r__n {
    margin: 0;
    font-size: .87rem;
    font-weight: 600;
    letter-spacing: -.015em;
    line-height: 1.25;
    color: var(--ink);
}
.r__m {
    margin: 0;
    font-size: .66rem;
    letter-spacing: .02em;
    color: var(--ink-55);
    /* WRAPPED, not clipped. This line is cuisine + neighbourhood + borough +
       price, and on a four-across grid `white-space: nowrap` cut it at
       "Seafood / French fine dining · Midt…" — losing the neighbourhood, which
       is the one thing a reader scanning a thousand rows is actually looking
       for. Two lines, and `overflow-wrap` so a long single word breaks rather
       than widening the track. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    overflow-wrap: anywhere;
}
.r__d {
    margin: .12rem 0 0;
    font-size: .72rem;
    line-height: 1.42;
    color: var(--ink-77);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.r__h {
    margin: .2rem 0 0;
    font-size: .58rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--accent);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.r__k {
    display: inline-block;
    margin-left: .35rem;
    font-size: .54rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--ink-55);
    border: 1px solid var(--line);
    border-radius: 999px;
    padding: 0 .34rem;
    vertical-align: .1em;
}

.reg__more {
    display: block;
    width: 100%;
    margin-top: .9rem;
    font: inherit;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--ink-77);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: .8rem;
    cursor: pointer;
    transition: color .16s var(--ease), border-color .16s var(--ease);
}
.reg__more:hover { color: var(--accent); border-color: var(--ink); }

.reg__none {
    display: none;
    padding: 2.2rem 0;
    color: var(--ink-55);
    font-size: .9rem;
}
.reg.is-empty .reg__none { display: block; }
.reg.is-empty .reg__more { display: none; }

.s-credit {
    margin-top: 1rem;
    font-size: .62rem;
    letter-spacing: .04em;
    color: var(--ink-55);
}

/* ============================================================ ON A PHONE
   The register's controls are excellent on a desk and were half a screen on a
   phone: 435px of bar, chips and page size before the first restaurant, on an
   812px screen. Everything below is about getting the reader to a row.       */
@media (max-width: 620px) {
    /* NOT STICKY HERE. The bar is 200px tall once the selects wrap two-up, and
       a 200px band welded to the top of a phone is a quarter of the screen
       gone for the whole scroll. On a desk it is one short row and worth it. */
    .reg__bar {
        position: static;
        gap: .35rem;
        padding: .5rem 0 .6rem;
    }
    /* Two per row, in equal tracks — the grid does what the three `flex: 1 1
       calc(50% - .2rem)` lines used to, and does it without the arithmetic. */
    .reg__find { grid-column: 1 / -1; }

    /* THE CHIPS SCROLL RATHER THAN WRAP. Twelve of them wrap to four rows and
       push the register itself below the fold; as one swipeable row they cost
       one row's height and still reach all twelve. */
    .reg__chips {
        flex-wrap: nowrap;
        overflow-x: auto;
        overscroll-behavior-x: contain;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        scroll-snap-type: x proximity;
        margin: .7rem 0 .1rem;
        padding-bottom: .15rem;
    }
    .reg__chips::-webkit-scrollbar { display: none; }
    .reg__chip { flex: 0 0 auto; scroll-snap-align: start; }

    .reg__size { margin: .5rem 0 0; }
    .reg__head { margin: .7rem 0 .6rem; }

    /* THE STANDFIRST IS CLAMPED HERE, not rewritten. Full, it is nine lines on
       a phone — 261px of the 818px that stood between the section heading and
       the first restaurant, on an 812px screen: the register opened with no
       restaurant visible at all. The first sentence carries the counts, which
       is the part that has to be read; the rest is there for a desk, for
       print and for a search engine, all of which still get it in full. */
    #table > .wrap > .lede {
        display: -webkit-box;
        -webkit-line-clamp: 3;
        -webkit-box-orient: vertical;
        overflow: hidden;
        margin-bottom: .5rem;
    }
    #table > .wrap > .d2 { margin-bottom: .35rem; }

    /* 40px is still a comfortable target and saves a row's worth of height
       across five controls. */
    .reg__find input, .reg__sel select { padding: .42rem .6rem; }
    .reg__grid { grid-template-columns: minmax(0, 1fr); }

    /* A row is read at arm's length on a phone, not leaned into. */
    .r { grid-template-columns: 5.2rem minmax(0, 1fr); }
    .r__n { font-size: .95rem; }
    .r__m { font-size: .72rem; }
    .r__d { font-size: .78rem; -webkit-line-clamp: 3; }
    .r__h { font-size: .62rem; }
}

/* Tap targets, matched on POINTER rather than width — a narrow desktop window
   is not a phone, and a large tablet is. 28px chips and 29px segments are
   thumb-sized only by accident. */
@media (pointer: coarse) {
    .reg__chip { min-height: 40px; padding: .5rem .85rem; }
    .reg__size .seg { min-height: 40px; min-width: 46px; }
    .reg__k { min-height: 44px; }
    .reg__clear { min-height: 40px; }
    .reg__more { padding: 1rem; }

    /* The reading sheet's own controls, which the guide and the register share.
       A 32px close button is a thumb-sized target only by accident. */
    .sheet__x { width: 44px; height: 44px; }
    .sheet__b .btn { min-height: 44px; display: inline-flex; align-items: center; }
}

/* ---------------------------------------------------- how many, and a hand of 12
   A SEGMENTED PILL: exactly one segment is lit, and the lit one is the truth
   about the list underneath it. */
.reg__size {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .25rem;
    margin: .55rem 0 0;
}
.reg__size-l {
    margin-right: .3rem;
    font-size: .58rem; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
    color: var(--ink-55);
}
.reg__size .seg {
    font: inherit;
    font-size: .68rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--ink-55);
    background: transparent;
    border: 1px solid var(--line);
    border-radius: 7px;
    padding: .26rem .6rem;
    cursor: pointer;
    transition: color .16s var(--ease), border-color .16s var(--ease), background .16s var(--ease);
}
.reg__size .seg:hover { color: var(--ink); border-color: var(--ink); }
.reg__size .seg.is-on {
    color: var(--paper);
    background: var(--ink);
    border-color: var(--ink);
}
.reg__size .seg:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The deal button is not a filter, so it does not take the filter's live
   colour — it stays outlined until it has actually dealt something. */
.reg__k--deal.is-on {
    color: var(--paper);
    background: var(--ink);
    border-color: var(--ink);
}

/* ------------------------------------------------- controls that actually work
   The shelves, the chips and the page size are HIDDEN until register.js says it
   is running. A search box that swallows what you type, a chip that does not
   filter and a page size that changes nothing are worse than absent — and the
   register is complete without them, because every row is already in the
   markup.

   Note the direction: JS REVEALS what CSS hides. The reverse — CSS hiding
   something that only JS brings back — is what leaves a page permanently
   missing a section when a script fails to load. */
.reg__bar,
.reg__chips,
.reg__size,
.reg__clear { display: none; }
/* GRID, not flex — and this line is the one that decides, because it is
   (0,2,0) against the (0,1,0) of the rule that lays the bar out. The layout
   was rewritten as a grid up there and nothing changed on screen until this
   said so too. */
.reg--live .reg__bar { display: grid; }
.reg--live .reg__chips { display: flex; }
.reg--live .reg__size { display: flex; }
.reg--live .reg__clear { display: inline; }
