/* =============================================================
   PUNTOS RURALES — stylesheet
   Sections: 1 tokens · 2 reset · 3 layout · 4 header · 5 controls
             6 cards · 7 detail · 8 admin · 9 motion · 10 print
   ============================================================= */

/* ---------- 1. Tokens ---------- */
:root {
  color-scheme: dark light;

  /* palette — warm bordeaux / ink, cream ink, brass accent */
  --ink-900: #100a0d;
  --ink-850: #171013;
  --ink-800: #1e1518;
  --ink-700: #2a1e23;
  --ink-600: #3a2b30;
  --paper:   #f4efe7;
  --paper-dim: #cdc3b8;
  --paper-mute: #9b9088;
  --wine:    #8d1c34;
  --wine-lt: #c2455f;
  --brass:   #c9a24a;
  --brass-lt:#e6c477;
  --green:   #5c8f6b;

  --bg: var(--ink-900);
  --bg-elev: var(--ink-850);
  --bg-card: var(--ink-800);
  --line: color-mix(in oklab, var(--paper) 12%, transparent);
  --line-strong: color-mix(in oklab, var(--paper) 22%, transparent);
  --fg: var(--paper);
  --fg-dim: var(--paper-dim);
  --fg-mute: var(--paper-mute);
  --accent: var(--brass);

  /* type */
  --font-display: "Playfair Display", "Iowan Old Style", "Palatino Linotype",
                  Palatino, Georgia, "Times New Roman", serif;
  /* Numerals only. Identical to --font-display MINUS Georgia, whose default
     figures are old-style: its 9 sits lower than its 8 and descends below the
     baseline. In a circular badge that reads as "the number is too low" and the
     descender collides with the PR label. Georgia exposes no `lnum` feature, so
     font-variant-numeric cannot rescue it — it has to leave the stack. Every
     face below was checked against its real glyph outlines: 9-top and 9-bottom
     match 8-top and 8-bottom to within 0.1px at 40px. */
  --font-score: "Playfair Display", "Iowan Old Style", "Palatino Linotype",
                Palatino, Charter, Baskerville, "Times New Roman", Times, serif;
  --font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Inter,
               Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-num: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;

  --step--1: clamp(0.78rem, 0.76rem + 0.1vw, 0.85rem);
  --step-0:  clamp(0.95rem, 0.92rem + 0.15vw, 1.05rem);
  --step-1:  clamp(1.15rem, 1.05rem + 0.4vw, 1.4rem);
  --step-2:  clamp(1.45rem, 1.25rem + 0.9vw, 2.1rem);
  --step-3:  clamp(1.9rem, 1.4rem + 2.2vw, 3.4rem);
  --step-4:  clamp(2.4rem, 1.5rem + 4.4vw, 5.4rem);

  /* space & shape */
  --gap: clamp(0.9rem, 0.5rem + 1.4vw, 1.6rem);
  --pad: clamp(1rem, 0.6rem + 2vw, 2.4rem);
  --r-sm: 8px;
  --r: 14px;
  --r-lg: 22px;
  --shadow-1: 0 1px 2px rgb(0 0 0 / 0.4), 0 6px 18px -8px rgb(0 0 0 / 0.55);
  --shadow-2: 0 2px 6px rgb(0 0 0 / 0.45), 0 22px 48px -18px rgb(0 0 0 / 0.7);
  --ease: cubic-bezier(0.22, 0.68, 0, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --dur: 320ms;
}

/* light theme — user toggle sets data-theme, else follows OS */
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f7f3ec;
  --bg-elev: #fffdf9;
  --bg-card: #fffdf9;
  --line: color-mix(in oklab, var(--ink-900) 12%, transparent);
  --line-strong: color-mix(in oklab, var(--ink-900) 26%, transparent);
  --fg: #1b1215;
  --fg-dim: #4c3c40;
  --fg-mute: #7a6a6d;
  --accent: #8a6a1f;
  --shadow-1: 0 1px 2px rgb(60 40 30 / 0.1), 0 6px 16px -10px rgb(60 40 30 / 0.3);
  --shadow-2: 0 2px 8px rgb(60 40 30 / 0.12), 0 24px 50px -22px rgb(60 40 30 / 0.4);
}
:root[data-theme="dark"] { color-scheme: dark; }

/* wine-type accents */
.t-tinto    { --type: #a52a44; }
.t-blanco   { --type: #c8a83e; }
.t-rosado   { --type: #d4718c; }
.t-espumoso { --type: #7fa88e; }
.t-dulce    { --type: #d09a3c; }

/* ---------- 2. Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--bg);
  color: var(--fg);
  font: var(--step-0)/1.6 var(--font-body);
  min-height: 100dvh;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { display: block; max-width: 100%; }
img { height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration-color: color-mix(in oklab, currentColor 40%, transparent); text-underline-offset: 3px; }
h1, h2, h3 { font-family: var(--font-display); font-weight: 600; line-height: 1.1; text-wrap: balance; }
p { text-wrap: pretty; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
::selection { background: var(--wine); color: #fff; }
[hidden] { display: none !important; }

.sr {
  position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.skip {
  position: fixed; inset-block-start: 0.5rem; inset-inline-start: 0.5rem;
  z-index: 200; padding: 0.6rem 1rem; border-radius: var(--r-sm);
  background: var(--accent); color: #1b1215; font-weight: 600;
  translate: 0 -200%; transition: translate 200ms var(--ease);
}
.skip:focus { translate: 0 0; }

/* ---------- 3. Layout ---------- */
.wrap { width: min(100% - 2 * var(--pad), 1280px); margin-inline: auto; }
.wrap--narrow { width: min(100% - 2 * var(--pad), 860px); margin-inline: auto; }
main { padding-block: clamp(1.5rem, 1rem + 2vw, 3rem) 5rem; }
.stack > * + * { margin-block-start: var(--flow, 1rem); }

/* ---------- 4. Header ---------- */
.site-head {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in oklab, var(--bg) 82%, transparent);
  border-bottom: 1px solid var(--line);
  view-transition-name: head;
}
@supports (backdrop-filter: blur(1px)) {
  .site-head { backdrop-filter: blur(14px) saturate(1.3); }
}
.site-head__in {
  display: flex; align-items: center; gap: clamp(0.6rem, 2vw, 1.4rem);
  padding-block: 0.7rem;
}
.brand { display: flex; align-items: center; gap: 0.7rem; text-decoration: none; flex: 0 0 auto; }
.brand__mark {
  display: grid; place-items: center;
  width: 2.35rem; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, var(--wine-lt), var(--wine) 55%, #5c101f);
  color: #fff; font: 700 0.8rem/1 var(--font-num); letter-spacing: 0.02em;
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.18), var(--shadow-1);
}
.brand__txt { display: grid; }
.brand__name { font-family: var(--font-display); font-size: 1.06rem; font-weight: 600; letter-spacing: 0.01em; }
.brand__sub { font-size: 0.7rem; color: var(--fg-mute); letter-spacing: 0.08em; text-transform: uppercase; }

.nav { display: flex; gap: 0.15rem; margin-inline-start: auto; align-items: center; }
.nav__links { display: flex; gap: 0.15rem; align-items: center; }
/* Links must refuse to shrink, otherwise they compress instead of overflowing
   and the fit measurement in app.js can never detect the overflow. */
.nav__links > .nav__link { flex: 0 0 auto; white-space: nowrap; }
.nav__link {
  padding: 0.45rem 0.75rem; border-radius: 999px; text-decoration: none;
  font-size: var(--step--1); color: var(--fg-dim); white-space: nowrap;
  transition: background var(--dur) var(--ease-soft), color var(--dur) var(--ease-soft);
}
.nav__link:hover { background: color-mix(in oklab, var(--fg) 8%, transparent); color: var(--fg); }
.nav__link[aria-current="page"] { color: var(--fg); background: color-mix(in oklab, var(--accent) 18%, transparent); }
.icon-btn {
  display: grid; place-items: center; width: 2.2rem; aspect-ratio: 1;
  border-radius: 50%; color: var(--fg-dim);
  transition: background var(--dur) var(--ease-soft), color var(--dur) var(--ease-soft), rotate 400ms var(--ease);
}
.icon-btn:hover { background: color-mix(in oklab, var(--fg) 10%, transparent); color: var(--fg); }
.icon-btn svg { width: 1.15rem; }
.lang-btn { width: auto; padding-inline: 0.6rem; border-radius: 999px; font: 600 0.72rem/1 var(--font-num); letter-spacing: 0.06em; }

/* ---- nav overflow: measured, not guessed ----
   app.js measures whether the links fit and sets .is-compact on the header.
   Everything below hangs off that class, so the burger appears exactly when
   the links do not fit and never otherwise. This rule must come after
   .icon-btn { display: grid } to win on equal specificity. */
.nav__burger { display: none; }
.is-compact .nav__burger { display: grid; }

.is-compact .nav__links {
  position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + 0.5rem);
  min-width: 12rem;
  flex-direction: column; align-items: stretch; gap: 0.1rem;
  padding: 0.4rem; border-radius: var(--r-lg);
  background: var(--bg-elev); border: 1px solid var(--line);
  box-shadow: var(--shadow-2);
  visibility: hidden; opacity: 0; translate: 0 -0.5rem;
  transition: opacity 180ms var(--ease-soft), translate 180ms var(--ease-soft),
              visibility 180ms;
}
.is-compact .nav__links.is-open { visibility: visible; opacity: 1; translate: 0 0; }
.is-compact .nav__link { padding-block: 0.7rem; font-size: var(--step-0); }
/* the panel is positioned against the nav */
.nav { position: relative; }

/* While measuring, the links are laid out inline but must not be seen. */
.is-measuring .nav__links {
  position: absolute !important; visibility: hidden !important;
  inset-block-start: -9999px; flex-direction: row !important;
}


/* ---------- 4b. Narrow screens ----------
   There was no mobile breakpoint before, which is why the header overflowed on
   a phone: brand + three nav labels + two buttons need ~570px, and an iPhone
   gives ~343px of content width. The excess made the page horizontally
   scrollable, so vertical swipes dragged it sideways.

   Fix has two parts: collapse the nav into a menu, and stop the document
   scrolling sideways at all so a stray wide child can never do this again. */

/* Belt and braces: nothing may cause horizontal scrolling of the document. */
html { overflow-x: hidden; }
body { overflow-x: clip; max-width: 100%; }

@media (max-width: 46rem) {
  /* Nav collapsing is NOT handled here — it is measured in app.js, because a
     width guess is wrong in at least three ways: the labels differ in length
     per language, the user's font size is unknown, and 46rem is arbitrary.
     What remains here is genuinely width-dependent. */

  /* brand: drop the subtitle, it is the least useful thing in a tight row */
  .brand__sub { display: none; }
  .brand__name { font-size: 1rem; }

  /* touch targets */
  .icon-btn { width: 2.5rem; }

  /* the hero heading at --step-4 is 2.4rem minimum, which is a lot on a phone */
  .hero h1 { font-size: clamp(1.9rem, 1.2rem + 5vw, 2.6rem); }
  .hero__lede { font-size: var(--step-0); }
  .hero__stats { gap: 1.1rem 1.6rem; margin-block-start: 1.4rem; }

  /* controls row: let the search take a full line rather than squeezing.
     .controls is itself the flex row (there is no inner wrapper). */
  .search { flex: 1 1 100%; }
  .controls { top: 3.2rem; }
}

@media (max-width: 30rem) {
  /* the score badge shrinks slightly so it does not dominate a small card,
     but stays well above its old desktop size */
  .pts { width: 3.9rem; }
  .pts__n { font-size: 1.84rem; }
  .pts--wide .pts__n { font-size: 1.59rem; }
}

/* ---------- 5. Hero + controls ---------- */
.hero { padding-block: clamp(1.6rem, 1rem + 4vw, 4.5rem) clamp(1rem, 2vw, 2rem); position: relative; }
.hero::before {
  content: ""; position: absolute; inset: -30% -20% auto; height: 60vh; z-index: -1;
  background: radial-gradient(60% 60% at 50% 0%, color-mix(in oklab, var(--wine) 34%, transparent), transparent 70%);
  filter: blur(30px); pointer-events: none;
}
.hero__eyebrow {
  font: 500 var(--step--1)/1 var(--font-body); letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--accent);
}
.hero h1 { font-size: var(--step-4); margin-block: 0.4em 0.3em; letter-spacing: -0.02em; }
.hero h1 em { font-style: italic; color: var(--accent); }
.hero__lede { font-size: var(--step-1); color: var(--fg-dim); max-width: 46ch; }
.hero__stats { display: flex; flex-wrap: wrap; gap: clamp(1rem, 3vw, 2.6rem); margin-block-start: 2rem; }
.stat__n { font: 600 var(--step-2)/1 var(--font-display); color: var(--fg); }
.stat__l { font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-mute); }

.controls {
  position: sticky; top: 3.6rem; z-index: 40;
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  padding-block: 0.7rem; margin-block-end: var(--gap);
  background: color-mix(in oklab, var(--bg) 88%, transparent);
  border-block: 1px solid var(--line);
}
@supports (backdrop-filter: blur(1px)) { .controls { backdrop-filter: blur(12px); } }
.search {
  display: flex; align-items: center; gap: 0.5rem; flex: 1 1 12rem; min-width: 0;
  padding: 0.45rem 0.8rem; border-radius: 999px;
  background: color-mix(in oklab, var(--fg) 7%, transparent);
  border: 1px solid transparent; transition: border-color var(--dur) var(--ease-soft);
}
.search:focus-within { border-color: var(--line-strong); }
.search svg { width: 1rem; flex: 0 0 auto; color: var(--fg-mute); }
.search input { flex: 1; min-width: 0; background: none; border: 0; outline: none; }
.search input::placeholder { color: var(--fg-mute); }

.chips { display: flex; gap: 0.35rem; flex-wrap: wrap; }
.chip {
  padding: 0.38rem 0.8rem; border-radius: 999px; font-size: var(--step--1);
  border: 1px solid var(--line); color: var(--fg-dim); white-space: nowrap;
  transition: border-color var(--dur) var(--ease-soft), background var(--dur) var(--ease-soft),
              color var(--dur) var(--ease-soft);
}
.chip:hover { border-color: var(--line-strong); color: var(--fg); }
.chip[aria-pressed="true"] {
  background: color-mix(in oklab, var(--type, var(--accent)) 24%, transparent);
  border-color: color-mix(in oklab, var(--type, var(--accent)) 60%, transparent);
  color: var(--fg);
}
.select {
  padding: 0.4rem 0.7rem; border-radius: 999px; font-size: var(--step--1);
  background: color-mix(in oklab, var(--fg) 7%, transparent);
  border: 1px solid var(--line); color: var(--fg-dim);
}
.view-toggle { display: flex; gap: 0.15rem; padding: 0.15rem; border-radius: 999px; border: 1px solid var(--line); }
.view-toggle button { padding: 0.3rem 0.55rem; border-radius: 999px; color: var(--fg-mute); display: grid; place-items: center; }
.view-toggle button svg { width: 1rem; }
.view-toggle button[aria-pressed="true"] { background: color-mix(in oklab, var(--fg) 12%, transparent); color: var(--fg); }
.count { font-size: var(--step--1); color: var(--fg-mute); margin-inline-start: auto; font-variant-numeric: tabular-nums; }

/* ---------- 6. Cards ---------- */
.grid {
  display: grid; gap: var(--gap);
  grid-template-columns: repeat(auto-fill, minmax(min(15.5rem, 100%), 1fr));
}
.grid--wide { grid-template-columns: repeat(auto-fill, minmax(min(21rem, 100%), 1fr)); }
.grid--list { grid-template-columns: 1fr; gap: 0.7rem; }

.card {
  container-type: inline-size;
  position: relative; isolation: isolate;
  border-radius: var(--r-lg); overflow: clip;
  background: var(--bg-card);
  box-shadow: var(--shadow-1);
  transition: translate var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.card:hover { translate: 0 -4px; box-shadow: var(--shadow-2); }
.card:has(a:focus-visible) { outline: 2px solid var(--accent); outline-offset: 3px; }
.card__link { position: absolute; inset: 0; z-index: 5; }
.card__link:focus-visible { outline: none; }

.card__media {
  position: relative; aspect-ratio: 4 / 5; overflow: clip;
  background: linear-gradient(160deg, var(--ink-700), var(--ink-900));
}
.card__img {
  width: 100%; height: 100%; object-fit: cover;
  transition: scale 700ms var(--ease), filter 700ms var(--ease);
}
.card:hover .card__img { scale: 1.05; }
.card__media::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgb(8 5 7 / 0.92) 4%, rgb(8 5 7 / 0.55) 26%, transparent 58%);
}

/* points badge overlaid on the photo */
/* --track = unfilled part of the ring, kept visible so the filled arc reads as
   a proportion rather than a floating sliver. --ring-w = ring thickness. */
.pts {
  position: absolute; inset-block-start: 0.7rem; inset-inline-end: 0.7rem; z-index: 3;
  /* The numeral and label are cap boxes in normal flow (see .pts__n), so
     centring this column centres the INK — which centring absolute boxes did
     not do. The ring is an absolutely-positioned sibling and stays out of it. */
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center;
  width: 4.4rem; aspect-ratio: 1; border-radius: 50%;
  /* stroke width in viewBox units (40x40), so it scales with the badge */
  --ring-w: 3.1;
  --track: rgb(255 255 255 / 0.17);
  --disc: rgb(10 6 8 / 0.9);
  /* plain solid disc — the ring is a separate SVG layer above it, so there is
     no gradient sizing to get wrong */
  background: var(--disc);
  box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.1), 0 5px 16px rgb(0 0 0 / 0.55);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}

/* ---- the score ring, as an SVG stroke arc ---- */
.pts__ring {
  position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0;
  /* the arc is authored from 3 o'clock; rotate so it starts at 12 */
  rotate: -90deg;
  pointer-events: none;
}
.pts__ring circle { fill: none; stroke-width: var(--ring-w); }
.pts__track { stroke: var(--track); }
.pts__arc {
  stroke: var(--type, var(--accent));
  stroke-linecap: round;
  /* dashoffset is set inline per wine; the transition makes it sweep in on
     first paint without depending on @property or a registered custom prop */
  transition: stroke-dashoffset 900ms var(--ease);
}
@media (prefers-reduced-motion: reduce) { .pts__arc { transition: none; } }
/* Numeral and label are BOTH taken out of the flow.
   Why: .pts is a centred grid, so with two in-flow children the *stack* gets
   centred and the number itself sits above the circle's centre — measurably
   6.4px high on a card, 7.7px on the detail badge. Taking the label out of the
   flow puts the number on the true centre and frees the ~1.1rem of badge width
   the label was reserving, so the numeral can also grow ~22%.
   Sizes below are solved against the real Iowan Old Style Bold digit metrics
   (0.594em advance, 0.712em cap) so the glyphs clear the ring's inner circle. */
.pts__n {
  /* above the ring (which is an absolutely-positioned sibling) */
  position: relative; z-index: 1;
  /* line-height 0.712 approximates a cap box, so the line box is close to the
     ink box and centring the column roughly centres the digits. It is only an
     approximation: cap/em is 0.712 for Iowan but 0.662 for Times and 0.666 for
     Baskerville, a 1.7px box error at this size. @supports below replaces it
     with an exact trim wherever the browser can do it. */
  font: 600 2.1rem/0.712 var(--font-score); color: #fff;
  /* lining-nums forces cap-height digits even if a fallback defaults to
     old-style; the stack is already lining-only, so this is belt and braces. */
  font-variant-numeric: lining-nums tabular-nums; letter-spacing: -0.03em;
  text-shadow: 0 1px 3px rgb(0 0 0 / 0.55);
}
.pts__l {
  position: relative; z-index: 1;
  /* also a cap box (0.705 == SF's cap height), so the flow column below holds
     exactly ink + gap + ink and nothing else. Percentage insets are gone: they
     resolved against the badge, not the text, so the two never stayed centred
     together across sizes. */
  font-size: 0.52rem; line-height: 0.705;   /* approx cap box; trimmed exactly below */
  margin-block-start: 0.34em;      /* gap between the two cap boxes */
  letter-spacing: 0.14em; text-transform: uppercase;
  color: rgb(255 255 255 / 0.6);
}

/* Exact cap-box trimming, where supported (Chrome/Edge 133+, Safari 18.2+).
   `trim-both cap alphabetic` makes the box edges the cap height and the
   baseline, so the box IS the ink — no per-font line-height guess, and the
   centred column is centred on real ink in every font. Browsers without it
   keep the line-height approximation above, which is within ~1px. */
@supports (text-box: trim-both cap alphabetic) {
  .pts__n, .pts__l { line-height: 1; text-box: trim-both cap alphabetic; }
}

.pts--wide .pts__n { font-size: 1.59rem; letter-spacing: -0.05em; }

.pts--big { width: 7rem; --ring-w: 2.8; }   /* viewBox units: thinner-looking on a bigger circle */
.pts--big .pts__n { font-size: 3.3rem; }
.pts--big .pts__l { font-size: 0.72rem; }
.pts--big.pts--wide .pts__n { font-size: 2.66rem; }

/* A perfect score gets its own treatment: gold ring, gold-tinted number and a
   soft outer glow, so it is distinguishable from a 99 at a glance. */
.pts--perfect {
  --type: var(--brass-lt);
  --track: color-mix(in oklab, var(--brass-lt) 32%, transparent);
  box-shadow:
    inset 0 0 0 1px color-mix(in oklab, var(--brass-lt) 55%, transparent),
    0 0 0 2px color-mix(in oklab, var(--brass-lt) 26%, transparent),
    0 6px 20px rgb(0 0 0 / 0.55);
}
.pts--perfect .pts__n { color: color-mix(in oklab, var(--brass-lt) 30%, #fff); }
.pts--perfect .pts__l { color: color-mix(in oklab, var(--brass-lt) 55%, #fff); }
.fav {
  position: absolute; inset-block-start: 0.85rem; inset-inline-start: 0.85rem; z-index: 3;
  color: var(--brass-lt); filter: drop-shadow(0 2px 4px rgb(0 0 0 / 0.6));
}
.fav svg { width: 1.15rem; }

.card__body {
  position: absolute; inset-inline: 0; inset-block-end: 0; z-index: 2;
  padding: 0.9rem 1rem 1rem; display: grid; gap: 0.35rem;
}
.card__abbr {
  font: 600 0.66rem/1 var(--font-num); letter-spacing: 0.16em;
  color: color-mix(in oklab, var(--type, var(--accent)) 72%, white);
}
.card__name {
  font-family: var(--font-display); font-size: 1.02rem; font-weight: 600; line-height: 1.22;
  color: #fff; text-wrap: balance;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.card__meta {
  display: flex; flex-wrap: wrap; gap: 0.3rem 0.6rem; align-items: center;
  font-size: 0.74rem; color: rgb(255 255 255 / 0.66);
}
.card__meta .dot { width: 3px; aspect-ratio: 1; border-radius: 50%; background: currentColor; opacity: 0.5; }
.card__icons { display: flex; gap: 0.3rem; margin-block-start: 0.15rem; }
.card__icons svg { width: 1.05rem; color: rgb(255 255 255 / 0.78); }
@container (max-width: 13rem) { .card__icons { display: none; } }

/* list layout */
.grid--list .card { border-radius: var(--r); }
.grid--list .card__media { display: none; }
.grid--list .card__body {
  position: static; display: grid; grid-template-columns: auto 1fr auto;
  align-items: center; gap: 0.4rem 1rem; padding: 0.75rem 1rem;
}
.grid--list .card__name { color: var(--fg); grid-column: 2; -webkit-line-clamp: 1; }
.grid--list .card__abbr { grid-row: span 2; align-self: center; }
.grid--list .card__meta { grid-column: 2; color: var(--fg-mute); }
.grid--list .card__icons { display: none; }
.grid--list .pts {
  /* relative, not static: the ring SVG is absolutely positioned and would
     otherwise escape to the nearest positioned ancestor */
  position: relative; grid-column: 3; grid-row: span 2; width: 3.4rem;
  /* ring-w is in viewBox units (40x40), so it is unitless and scales */
  --ring-w: 3.3;
  --track: color-mix(in oklab, var(--fg) 14%, transparent);
  /* the disc behind the number has to follow the theme in list view */
  --disc: var(--bg-card);
}
/* no label in list view, so the numeral owns the full inner circle */
.grid--list .pts__n { font-size: 1.66rem; color: var(--fg); text-shadow: none; }
.grid--list .pts--wide .pts__n { font-size: 1.30rem; }
.grid--list .pts__l { display: none; }
.grid--list .pts--perfect .pts__n { color: color-mix(in oklab, var(--brass-lt) 45%, var(--fg)); }
.grid--list .fav { position: static; grid-row: span 2; }

.empty { padding: 4rem 1rem; text-align: center; color: var(--fg-mute); }
.empty svg { width: 2.6rem; margin: 0 auto 1rem; opacity: 0.5; }

/* section heads */
.sec-head { display: flex; align-items: baseline; gap: 1rem; margin-block: 2.6rem 1.1rem; }
.sec-head h2 { font-size: var(--step-2); }
.sec-head__line { flex: 1; height: 1px; background: var(--line); }
.sec-head a { font-size: var(--step--1); color: var(--fg-mute); text-decoration: none; white-space: nowrap; }
.sec-head a:hover { color: var(--fg); }

/* ---------- 7. Detail view ---------- */
.detail { padding-block-start: 1rem; }
.back {
  display: inline-flex; align-items: center; gap: 0.4rem; margin-block-end: 1.4rem;
  font-size: var(--step--1); color: var(--fg-mute); text-decoration: none;
}
.back:hover { color: var(--fg); }
.back svg { width: 0.9rem; }

.detail__top {
  display: grid; gap: clamp(1.4rem, 4vw, 3.4rem);
  grid-template-columns: 1fr;
}
@media (min-width: 56rem) { .detail__top { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr); align-items: start; } }

.detail__figure {
  position: relative; border-radius: var(--r-lg); overflow: clip;
  background: linear-gradient(160deg, var(--ink-700), var(--ink-900));
  box-shadow: var(--shadow-2);
}
.detail__figure img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
@media (min-width: 56rem) { .detail__figure { position: sticky; top: 5rem; } }

.detail h1 { font-size: var(--step-3); letter-spacing: -0.02em; }
.detail__sub { font-size: var(--step-1); color: var(--fg-dim); margin-block-start: 0.4rem; }
.tag-row { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-block-start: 1rem; }
.tag {
  padding: 0.28rem 0.7rem; border-radius: 999px; font-size: 0.74rem;
  border: 1px solid color-mix(in oklab, var(--type, var(--accent)) 40%, transparent);
  color: color-mix(in oklab, var(--type, var(--accent)) 55%, var(--fg));
  background: color-mix(in oklab, var(--type, var(--accent)) 10%, transparent);
}

.facts {
  display: grid; gap: 1px; margin-block-start: 1.8rem;
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  background: var(--line); border: 1px solid var(--line); border-radius: var(--r);
  overflow: clip;
}
.fact { background: var(--bg); padding: 0.85rem 1rem; }
.fact dt { font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-mute); }
.fact dd { font: 500 1.02rem/1.3 var(--font-body); margin-block-start: 0.2rem; font-variant-numeric: tabular-nums; }

.notes { font-size: var(--step-1); line-height: 1.7; color: var(--fg-dim); white-space: pre-line; }
.notes::first-line { color: var(--fg); }

/* structure bars */
.bars { display: grid; gap: 0.7rem; }
.bar { display: grid; grid-template-columns: 6.5rem 1fr; gap: 0.8rem; align-items: center; font-size: var(--step--1); }
.bar__track { display: flex; gap: 0.25rem; }
.bar__seg {
  height: 0.42rem; flex: 1; border-radius: 999px;
  background: color-mix(in oklab, var(--fg) 12%, transparent);
}
.bar__seg[data-on] { background: var(--type, var(--accent)); }

/* icon legend */
.legend { display: grid; gap: 0.55rem; grid-template-columns: repeat(auto-fill, minmax(10.5rem, 1fr)); }
.legend__item { display: flex; align-items: center; gap: 0.6rem; font-size: var(--step--1); color: var(--fg-dim); }
.legend__item svg { width: 1.35rem; flex: 0 0 auto; color: var(--type, var(--accent)); }
.icon-group { margin-block-start: 1.2rem; }
.icon-group__h { font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--fg-mute); margin-block-end: 0.5rem; }

.buy { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.buy a, .buy span {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.45rem 0.9rem; border-radius: 999px; font-size: var(--step--1);
  border: 1px solid var(--line-strong); text-decoration: none; color: var(--fg-dim);
  transition: background var(--dur) var(--ease-soft), color var(--dur) var(--ease-soft);
}
.buy a:hover { background: color-mix(in oklab, var(--accent) 20%, transparent); color: var(--fg); }
.buy svg { width: 0.85rem; }

.prevnext { display: flex; justify-content: space-between; gap: 1rem; margin-block-start: 3.5rem; padding-block-start: 1.5rem; border-top: 1px solid var(--line); }
.prevnext a { display: grid; gap: 0.2rem; text-decoration: none; font-size: var(--step--1); max-width: 45%; }
.prevnext a:last-child { text-align: right; }
.prevnext .k { color: var(--fg-mute); font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; }
.prevnext .v { font-family: var(--font-display); font-size: 1rem; color: var(--fg); }

/* ---------- 8. About / admin ---------- */
.prose { max-width: 62ch; }
.prose > * + * { margin-block-start: 1rem; }
.prose h2 { font-size: var(--step-2); margin-block-start: 2.2rem; }
.prose h3 { font-size: var(--step-1); margin-block-start: 1.6rem; }
.prose code { font: 0.88em var(--font-num); background: color-mix(in oklab, var(--fg) 9%, transparent); padding: 0.12em 0.4em; border-radius: 5px; }
.prose ul, .prose ol { padding-inline-start: 1.3rem; }
.prose li + li { margin-block-start: 0.3rem; }

.panel { background: var(--bg-elev); border: 1px solid var(--line); border-radius: var(--r); padding: var(--pad); }
.field { display: grid; gap: 0.35rem; margin-block-end: 1rem; }
.field label { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-mute); }
.field input, .field select, .field textarea {
  padding: 0.6rem 0.75rem; border-radius: var(--r-sm);
  background: color-mix(in oklab, var(--fg) 6%, transparent);
  border: 1px solid var(--line); outline: none;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); }
.field textarea { min-height: 7rem; resize: vertical; line-height: 1.6; }
.field small { color: var(--fg-mute); font-size: 0.72rem; }
.row { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); }
.btn {
  display: inline-flex; align-items: center; gap: 0.45rem; justify-content: center;
  padding: 0.6rem 1.1rem; border-radius: 999px; font-weight: 600; font-size: var(--step--1);
  background: var(--accent); color: #17100c;
  transition: filter var(--dur) var(--ease-soft), translate var(--dur) var(--ease);
}
.btn:hover { filter: brightness(1.1); translate: 0 -1px; }
.btn--ghost { background: none; border: 1px solid var(--line-strong); color: var(--fg-dim); }
.btn--ghost:hover { color: var(--fg); background: color-mix(in oklab, var(--fg) 8%, transparent); }
.btn svg { width: 1rem; }
.pickers { display: grid; gap: 0.4rem; grid-template-columns: repeat(auto-fill, minmax(9.5rem, 1fr)); }
.picker {
  display: flex; align-items: center; gap: 0.5rem; padding: 0.4rem 0.6rem;
  border: 1px solid var(--line); border-radius: var(--r-sm); font-size: 0.78rem; cursor: pointer;
  color: var(--fg-dim);
}
.picker:hover { border-color: var(--line-strong); }
.picker svg { width: 1.2rem; flex: 0 0 auto; }
.picker input { accent-color: var(--accent); }
.picker:has(input:checked) { border-color: var(--accent); background: color-mix(in oklab, var(--accent) 12%, transparent); color: var(--fg); }
.code-out {
  font: 0.78rem/1.55 var(--font-num); white-space: pre; overflow: auto;
  max-height: 22rem; padding: 1rem; border-radius: var(--r-sm);
  background: var(--ink-900); color: #cfe3d0; border: 1px solid var(--line);
}
:root[data-theme="light"] .code-out { background: #241b1e; }

/* footer */
.site-foot {
  border-top: 1px solid var(--line); padding-block: 2.5rem 3.5rem;
  color: var(--fg-mute); font-size: var(--step--1);
}
.site-foot__in { display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center; justify-content: space-between; }

/* ---------- 9. Motion ---------- */
/* scroll-driven reveal where supported, otherwise just visible */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: reveal-in linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 26%;
    }
    @keyframes reveal-in {
      from { opacity: 0; translate: 0 22px; scale: 0.985; }
      to   { opacity: 1; translate: 0 0; scale: 1; }
    }
  }
}
/* fade-in for the routed panel (View Transitions do the heavy lifting) */
.route-in { animation: fade-up 380ms var(--ease) both; }
@keyframes fade-up { from { opacity: 0; translate: 0 10px; } to { opacity: 1; translate: 0 0; } }

::view-transition-old(root), ::view-transition-new(root) { animation-duration: 260ms; }
::view-transition-group(*) { animation-timing-function: var(--ease); }
::view-transition-old(head), ::view-transition-new(head) { animation: none; mix-blend-mode: normal; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important; scroll-behavior: auto !important;
  }
  .card:hover { translate: none; }
  .card:hover .card__img { scale: 1; }
  ::view-transition-group(*) { animation: none !important; }
}

/* ---------- 10. Print ---------- */
@media print {
  :root { --bg: #fff; --fg: #000; --fg-dim: #333; --fg-mute: #666; }
  .site-head, .controls, .nav, .nav__links, .nav__burger, .prevnext, .site-foot, .back { display: none !important; }
  body { background: #fff; color: #000; }
  .card, .panel, .detail__figure { box-shadow: none; border: 1px solid #bbb; }
  .card__media::after { display: none; }
}
