/* ============================================
   2026 Hipcamp Awards — structural CSS.
   Colors come from ultralight theme tokens (--surface, --content, --muted,
   --border, --primary, --raised, --emphasis), so the whole page follows the
   light/dark toggle automatically. Typography is ultralight Geist via the
   .text-* classes applied in the components. Scoped under .story-2026-awards.
   ============================================ */

.story-2026-awards {
  --aw-accent: var(--primary);
  --aw-shadow: 0 10px 34px rgba(0, 0, 0, 0.1);
  --aw-shadow-sm: 0 4px 16px rgba(0, 0, 0, 0.08);
  /* Vertical room the stuck FilterBar covers. Every in-page anchor target
     (category sections, subdivision group headings) offsets by this so a jump
     lands the heading just below the bar instead of behind it. Mirrored in
     FilterBar.tsx as STICKY_OFFSET_PX, which also anchors the scrollspy band. */
  --aw-sticky-offset: 70px;
  background: var(--surface);
  color: var(--content);
}

/* Most of the page's interactive controls (pills, quick links, share
   buttons, the jump select, the scroll arrow, country cards, the switcher
   button) are plain elements, not ultralight's Button — which already
   handles this itself via headlessui's data-focus (only set for keyboard
   focus). These get the browser's default blue ring on every mouse click.
   Suppress it for pointer interaction only; keyboard focus still gets a
   real, token-driven indicator. Outline follows each element's own
   border-radius automatically. */
.story-2026-awards :is(a, button, select):focus:not(:focus-visible) {
  outline: none;
}

.story-2026-awards :is(a, button, select):focus-visible {
  outline: 2px solid var(--content);
  outline-offset: 2px;
}

/* ============================================
   FILTER BAR — sticky category rail. Pills are in-page anchors to the
   category sections below (see CategorySection.tsx), not routes.
   ============================================ */

.aw-filterbar {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--surface);
  border-bottom: 1px solid transparent;
  transition:
    background-color 0.15s ease-out,
    border-color 0.15s ease-out,
    box-shadow 0.15s ease-out;
}

/* Picked up: the bar has scrolled past its resting spot in the document flow
   and is now actually pinned (see the sentinel + IntersectionObserver in
   FilterBar.tsx). Only then does it visually detach from the page. */
.aw-filterbar.is-stuck {
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  border-bottom-color: var(--border);
  box-shadow: var(--aw-shadow-sm);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}

.aw-filterbar-inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 12px 20px;
}

.aw-pill-row {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}

.aw-pill-row::-webkit-scrollbar {
  display: none;
}

/* Single row, always: a wrapped second line would make the bar taller than
   --aw-sticky-offset and every anchor jump would land under it. The brand and
   the jump select hold their size; the pill row (min-width: 0) absorbs the
   squeeze by scrolling. */
.aw-filterbar-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: nowrap;
}

/* Hipcamp wordmark — the same LogoHipcamp the hero uses, hidden at rest and
   revealed once the bar is pinned (see .is-stuck below), so the chips keep a
   branding anchor after they detach from the page and lose their
   surrounding context. Width AND opacity animate together (same duration,
   same easing) so the pill row scoots over smoothly to make room rather than
   jumping — the width transition on its own used to cause a flash right at
   the sticky threshold, but that turned out to be a hysteresis problem, not
   a width-transition problem: see STUCK_HYSTERESIS_PX in FilterBar.tsx's
   useStuck, which keeps `.is-stuck` from flickering back and forth right at
   the boundary and stuttering this transition. Pointer events are off at
   rest so the collapsed slot isn't a dead-looking clickable area. */
.aw-filterbar-brand {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  width: 0;
  opacity: 0;
  overflow: hidden;
  color: var(--content);
  pointer-events: none;
  transition:
    width 0.25s ease,
    opacity 0.25s ease;
}

.aw-filterbar.is-stuck .aw-filterbar-brand {
  width: 125px;
  opacity: 1;
  pointer-events: auto;
}

.aw-filterbar-brand-icon {
  width: 125px;
  height: 20px;
  flex-shrink: 0;
}

/* Not enough room on phones for pills AND a wordmark — the bar stays
   pill-only at every scroll position, full width, still left-aligned. */
@media (max-width: 560px) {
  .aw-filterbar-brand {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .aw-filterbar-brand {
    transition: none;
  }
}

/* Left-aligned, not centered: pills start at the row's own edge and the row
   itself shifts right as the brand slot expands on .is-stuck, which reads as
   the row "making room" for the wordmark rather than the whole set
   re-centering under it. */
.aw-pill-row--categories {
  flex: 1;
  min-width: 0;
  justify-content: flex-start;
  /* Gradient falloff so pills ease out at the scrollable edges rather than
     clipping hard under the jump select. Masking the row itself (rather than
     an overlay) means it reads correctly against both the resting surface
     background and the translucent blurred .is-stuck background. Right edge
     always fades (it never reaches the true end of the row, since the jump
     select sits after it); left edge only fades once actually scrolled (see
     .is-scrolled, toggled from scroll position in FilterBar.tsx) so the first
     pill isn't clipped at rest. */
  -webkit-mask-image: linear-gradient(to right, black calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(to right, black calc(100% - 28px), transparent 100%);
}

.aw-pill-row--categories.is-scrolled {
  -webkit-mask-image: linear-gradient(
    to right,
    transparent 0,
    black 28px,
    black calc(100% - 28px),
    transparent 100%
  );
  mask-image: linear-gradient(
    to right,
    transparent 0,
    black 28px,
    black calc(100% - 28px),
    transparent 100%
  );
}

.aw-pill {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  border-radius: 9999px;
  border: 1px solid var(--border);
  background: var(--raised);
  color: var(--content);
  padding: 6px 14px;
  font-weight: 600;
  font-size: 0.85rem;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background-color 0.15s ease-out,
    color 0.15s ease-out,
    border-color 0.15s ease-out;
}

.aw-pill:hover {
  background: var(--surface);
}

.aw-pill.is-active {
  background: var(--emphasis);
  color: var(--surface);
  border-color: transparent;
}

/* Explicit height rather than padding + line-height: the jump select has to
   match this exactly (see .aw-jump-select) and browsers disagree about how a
   <select>'s internal line box is sized. */
.aw-pill--small {
  height: 28px;
  padding: 0 11px;
  font-size: 0.78rem;
}

.aw-jump {
  flex-shrink: 0;
}

/* Same system as .aw-pill--small — identical height, radius, weight, size and
   left padding, with the extra right padding the caret needs. */
.aw-jump-select {
  appearance: none;
  -webkit-appearance: none;
  height: 28px;
  border-radius: 9999px;
  border: 1px solid var(--border);
  background: var(--raised);
  color: var(--content);
  padding: 0 26px 0 11px;
  font-family: inherit;
  font-weight: 600;
  font-size: 0.78rem;
  cursor: pointer;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3e%3cpath fill='none' stroke='%23888888' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M1 1.5L6 6.5L11 1.5'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 9px 6px;
}

.aw-jump-select:hover {
  background-color: var(--surface);
}

/* ============================================
   CATEGORY MASTHEAD — split hero (NYT-style): a calm, centered text column
   plus a full-bleed photo collage of the country's winners. Owns the entire
   first viewport (no page header above it — see AwardsFooter/FilterBar for
   the page's remaining chrome). Stacked (collage band above the text) through
   phone and tablet; side-by-side only from 1200px, where the split has real
   room to breathe.
   ============================================ */

.aw-masthead {
  display: grid;
  grid-template-areas: 'collage' 'text';
  /* Fixed (not minmax) — the collage band can never grow past 54svh. Tiles
     crop to their grid cell (see .aw-masthead-collage-tile) so image bytes
     have zero influence on this row's height. Reclaimed from the old 42svh:
     tighter text-stack spacing below frees up the room, and the collage gets
     it instead of leaving a void between the copy and the scroll cue. */
  grid-template-rows: 54svh 1fr;
  min-height: 100vh;
  min-height: 100svh;
}

/* Two-column split only from 1200px up. Below that — including tablet — the
   stacked layout (collage band above the text) holds: at narrower widths a
   50/50 split leaves each column too thin for the 4-col mosaic, producing
   uncomfortably skinny tile slivers rather than a real collage. */
@media (min-width: 1200px) {
  .aw-masthead {
    grid-template-areas: 'text collage';
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: 1fr;
    /* Hard viewport lock: exactly one screen tall, never 1.5x from tiles
       sizing to their own images. `overflow: hidden` is the backstop in case
       anything (a tile, a border) still nudges past the edge. */
    height: 100vh;
    height: 100svh;
    overflow: hidden;
  }

  /* The landing page reuses this exact masthead (see .aw-masthead--landing
     in pages/stories/2026-awards/index.tsx), but its left column carries a
     lot more content than a fixed hero ever does — four country cards plus
     the footer folded in at the bottom — so it can't take the country
     hero's hard one-screen lock without clipping. Let it grow with content
     instead; the mosaic column stretches to match via the shared 1fr row. */
  .aw-masthead.aw-masthead--landing {
    height: auto;
    overflow: visible;
  }
}

/* Safety valve: below this height the text column (logo + heading + copy +
   scroll cue) can't fit inside a hard-locked 100svh without clipping, so trade
   the lock for the old grow-with-content behavior. Applies at any width — a
   short desktop browser window hits the same problem as a landscape phone. */
@media (max-height: 640px) {
  .aw-masthead {
    min-height: 100svh;
    height: auto;
    overflow: visible;
  }
}

/* Full-height flex column: the logo pins to its own row near the top and the
   text stack (heading, copy, the share/view-the-list action row) vertically
   centers in the remaining space — see .aw-masthead-logo-row /
   .aw-masthead-content / .aw-hero-actions. */
.aw-masthead-text {
  grid-area: text;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  max-width: 560px;
  /* Always auto, never overridden per breakpoint: this is a grid item sized
     by max-width inside its own column (single full-width column while
     stacked, the left half of a 50/50 split once the two-column layout
     kicks in — see the 1200px breakpoint below). Without margin: auto here
     the box sits flush against the column's start edge instead of centered
     in it — exactly the "hugs the left" bug at desktop widths. */
  margin: 0 auto;
  padding: 28px 24px 20px;
}

@media (min-width: 768px) {
  .aw-masthead-text {
    padding: 48px 56px 36px;
  }
}

.aw-masthead-logo-row {
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  width: 100%;
}

/* Hipcamp wordmark — the only branding left now that AwardsHeader is gone.
   Shared by the country masthead (AwardsHero) and the landing masthead
   (pages/stories/2026-awards/index.tsx) — same markup, same class. */
.aw-masthead-logo {
  display: inline-flex;
}

.aw-masthead-logo-icon {
  height: 26px;
  width: auto;
}

/* Vertically centered in the flex column's remaining space once the logo row
   and scroll row above/below claim their own height. */
.aw-masthead-content {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  width: 100%;
}

/* Geist is a variable font loaded across its full 100–900 range (see
   ultralight/fonts.ts), so 900 is a real master, not a synthesized bold. The
   tighter tracking keeps the extra weight from reading as wide. */
.aw-masthead-title {
  font-size: clamp(3rem, 6.5vw, 5.2rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  line-height: 1.05;
  color: var(--content);
  margin: 0 0 16px;
}

/* Inline country-switcher control living inside the h1 — inherits the
   heading's color/weight/size exactly so it reads as part of the sentence;
   the chevron (rotating open) is the only affordance. */
.aw-masthead-switch-wrap {
  position: relative;
  display: inline-block;
}

.aw-masthead-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  font: inherit;
  font-weight: inherit;
  color: inherit;
  background: none;
  border: none;
  padding: 0 2px 2px;
  margin: 0;
  cursor: pointer;
  line-height: 1;
  transition: opacity 0.15s ease-out;
}

.aw-masthead-switch:hover {
  opacity: 0.7;
}

/* Hung outside the button box rather than laid out inside it: the h1 is
   optically centered on "Best in {Country}", and a caret taking real width
   would shove the whole line left of centre by half its size. */
.aw-masthead-switch-icon {
  position: absolute;
  left: 100%;
  top: 50%;
  transform: translateY(-50%);
  width: 0.6em;
  height: 0.6em;
  flex-shrink: 0;
  transition: transform 0.15s ease-out;
}

.aw-masthead-switch-wrap[data-open] .aw-masthead-switch-icon {
  transform: translateY(-50%) rotate(180deg);
}

.aw-masthead-switch-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 30;
  min-width: 210px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--aw-shadow);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  /* headlessui focuses this panel programmatically on open — never a real
     keyboard-navigation focus event, so a ring around the whole card is
     never meaningful. Individual items still get their own focus-visible
     styling via the shared rule above. */
  outline: none;
}

/* Own, non-inherited type: this menu lives inside the h1 (see AwardsHero.tsx),
   so without explicit resets it inherits the heading's huge size, 900 weight
   and tight tracking — fine for one line of "Best in Australia", crushing for
   a stacked list of country names in a narrow panel. */
.aw-masthead-switch-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 12px 20px;
  border-radius: 10px;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: normal;
  line-height: 1.2;
  color: var(--content);
  text-decoration: none;
  text-align: left;
  transition: background-color 0.15s ease-out;
}

.aw-masthead-switch-item:hover,
.aw-masthead-switch-item[data-focus] {
  background: var(--raised);
}

.aw-masthead-switch-item-flag {
  font-size: 1.1em;
  line-height: 1;
}

/* Quiet row of all four countries — the current one included, as a plain
   non-link span, so the row's width and item order never change between
   countries and nothing reflows on switch. Text-label styling (mono,
   uppercase, tracked, muted) matches .aw-card-loc. */
.aw-masthead-quicklinks {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px 20px;
  margin: 0 0 16px;
}

/* Tighter than .aw-hero-eyebrow's/.aw-hero-sub's own margins (below, in the
   LANDING HERO section) — scoped so the density fix here doesn't also
   compress the landing page, which still reuses .aw-hero-sub (the eyebrow is
   country-hero-only now — see AwardsHero.tsx). Frees up vertical room in the
   stacked layout so the text stack isn't floating in a sea of whitespace
   above/below it (see grid-template-rows above, which hands that reclaimed
   room to the collage instead). */
.aw-masthead-content .aw-hero-eyebrow {
  margin: 0 0 14px;
}

.aw-masthead-content .aw-hero-sub {
  margin: 0 auto 14px;
}

.aw-quicklink {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  font-family: var(--font-mono), ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s ease-out;
}

a.aw-quicklink:hover {
  color: var(--content);
}

/* The country you're on: full-contrast and heavier, but still a text link's
   shape — no pill, nothing that reads as a button you could press. */
.aw-quicklink.is-current {
  color: var(--content);
  font-weight: 700;
  cursor: default;
}

/* Flags render at their own metrics; nudge them up to sit on the caps line of
   the uppercase label beside them. */
.aw-quicklink-flag {
  font-size: 1.05em;
  line-height: 1;
  letter-spacing: 0;
}

/* One action row under the hero copy: share + copy-link + "View the list",
   all the same quiet-pill species. The wrapper owns the top margin so
   .aw-share's own (used bare elsewhere) is zeroed inside it. */
.aw-hero-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.aw-hero-actions .aw-share {
  margin-top: 0;
}

/* Same quiet-pill treatment as .aw-share-btn — a call to action, not a
   flashy one. No animation, no icon. */
.aw-masthead-scroll {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--raised);
  border: 1px solid var(--border);
  color: var(--content);
  font-size: 0.82rem;
  font-weight: 600;
  padding: 9px 18px;
  border-radius: 9999px;
  cursor: pointer;
  transition: transform 0.15s ease-out;
}

.aw-masthead-scroll:hover {
  transform: scale(1.06);
}

.aw-masthead-scroll:active {
  transform: scale(0.98);
}

/* Top-on-phone/tablet, right-column-on-desktop photo mosaic, framed with an
   inset margin off the hero's outer edges. A fixed, fully-explicit
   grid-template-areas mosaic — no auto-placed masonry span, no implicit
   tracks — so TILE_COUNT tiles (see AwardsHero.tsx) always fill every cell
   exactly, with no dead space and no overflow. No background here: the
   container itself is never visible once tiles fill it — see
   .aw-masthead-collage-tile-skeleton for the per-tile loading state instead.
   Phone: 3 cols x 4 rows, 7 tiles (b1..b7) — b1 a 2x2 anchor, b5/b6 2x1
   landscapes, b2/b3/b4/b7 1x1s:
     b1 b1 b2
     b1 b1 b3
     b4 b5 b5
     b6 b6 b7 */
.aw-masthead-collage {
  grid-area: collage;
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(4, 1fr);
  grid-template-areas:
    'b1 b1 b2'
    'b1 b1 b3'
    'b4 b5 b5'
    'b6 b6 b7';
  gap: 8px;
  overflow: hidden;
  margin: 20px 20px 0 20px;
  background: transparent;
  transition: opacity 0.2s ease-out;
}

/* Tablet and desktop share the same 4 cols x 6 rows, 12-tile pattern
   (a1..a12) — a1 a 2x2 anchor, a2-a4 a landscape pair plus a 1x1 each, a5/a8
   landscape, a6/a7 portrait pair, a9/a11 portrait, a10 landscape, a12
   landscape:
     a1 a1 a2 a2
     a1 a1 a3 a4
     a5 a5 a6 a7
     a8 a8 a6 a7
     a9 a10 a10 a11
     a9 a12 a12 a11
   From 768px the layout is still stacked (see the 1200px breakpoint above),
   so the collage sits full-width above the text — more columns and tiles
   than phone gets, at a comfortable band height rather than a half-width
   sliver. Margin is symmetric, matching the phone band's framing. */
@media (min-width: 768px) {
  .aw-masthead-collage {
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: repeat(6, 1fr);
    grid-template-areas:
      'a1 a1 a2 a2'
      'a1 a1 a3 a4'
      'a5 a5 a6 a7'
      'a8 a8 a6 a7'
      'a9 a10 a10 a11'
      'a9 a12 a12 a11';
    gap: 10px;
    margin: 28px 28px 0 28px;
  }
}

/* Desktop split: the collage becomes its own full-height column beside the
   text (see the 1200px breakpoint above), so it only needs to clear the
   outer edges — no bottom margin (it fills the row) and no left margin (it
   sits flush against the text column's own padding). */
@media (min-width: 1200px) {
  .aw-masthead-collage {
    margin: 28px 28px 28px 0;
  }
}

/* Dimmed while a country navigation is in flight (see isNavigating in
   [country]/index.tsx) — a small, cheap signal that something's happening
   while the sections area shows its own skeleton. */
.aw-masthead-collage.is-navigating {
  opacity: 0.55;
}

/* Tile shell: crops to whatever grid-area it's assigned (below), never sizes
   to its image. The grid template alone drives layout. */
.aw-masthead-collage-tile {
  position: relative;
  overflow: hidden;
  border-radius: 14px;
}

.aw-masthead-collage-tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 0.4s ease-out;
}

.aw-masthead-collage-tile img.is-loaded {
  opacity: 1;
}

/* Per-tile loading placeholder (see CollageTile in AwardsHero.tsx) — same
   pulse idiom as .aw-card-photo-skeleton, faded out once that tile's image
   fires its load event. Replaces the old flat grey backing slab on the
   container: each tile now owns its own loading state instead. */
.aw-masthead-collage-tile-skeleton {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: 14px;
  background-color: var(--raised);
  animation: aw-cover-pulse 1.8s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .aw-masthead-collage-tile-skeleton {
    animation: none;
  }
}

/* The DOM always renders all TILE_COUNT (12) tiles; nth-child assigns each
   to its mosaic area per breakpoint (b1..b7 phone, a1..a12 tablet/desktop —
   see grid-template-areas above), and only the first 7 are shown below
   768px so the 3x4 phone grid never has empty cells (see cyclePhotos in
   AwardsHero.tsx). */
.aw-masthead-collage-tile:nth-child(1) {
  grid-area: b1;
}
.aw-masthead-collage-tile:nth-child(2) {
  grid-area: b2;
}
.aw-masthead-collage-tile:nth-child(3) {
  grid-area: b3;
}
.aw-masthead-collage-tile:nth-child(4) {
  grid-area: b4;
}
.aw-masthead-collage-tile:nth-child(5) {
  grid-area: b5;
}
.aw-masthead-collage-tile:nth-child(6) {
  grid-area: b6;
}
.aw-masthead-collage-tile:nth-child(7) {
  grid-area: b7;
}
.aw-masthead-collage-tile:nth-child(n + 8) {
  display: none;
}

@media (min-width: 768px) {
  .aw-masthead-collage-tile:nth-child(1) {
    grid-area: a1;
  }
  .aw-masthead-collage-tile:nth-child(2) {
    grid-area: a2;
  }
  .aw-masthead-collage-tile:nth-child(3) {
    grid-area: a3;
  }
  .aw-masthead-collage-tile:nth-child(4) {
    grid-area: a4;
  }
  .aw-masthead-collage-tile:nth-child(5) {
    grid-area: a5;
  }
  .aw-masthead-collage-tile:nth-child(6) {
    grid-area: a6;
  }
  .aw-masthead-collage-tile:nth-child(7) {
    grid-area: a7;
  }
  .aw-masthead-collage-tile:nth-child(8) {
    grid-area: a8;
  }
  .aw-masthead-collage-tile:nth-child(9) {
    grid-area: a9;
  }
  .aw-masthead-collage-tile:nth-child(10) {
    grid-area: a10;
  }
  .aw-masthead-collage-tile:nth-child(11) {
    grid-area: a11;
  }
  .aw-masthead-collage-tile:nth-child(12) {
    grid-area: a12;
  }
  .aw-masthead-collage-tile:nth-child(n + 8) {
    display: block;
  }
}

.aw-masthead-collage-empty {
  grid-column: 1 / -1;
  grid-row: 1 / -1;
  border-radius: 14px;
  background: linear-gradient(
    135deg,
    var(--raised),
    color-mix(in srgb, var(--raised) 70%, var(--border))
  );
}

/* ============================================
   EDITORIAL INTRO — short reading-width intro between the masthead and
   FilterBar. Part of the persistent page shell (rendered once in
   [country]/index.tsx, outside the isNavigating-swapped sections area), so it
   never flickers during a country switch.
   ============================================ */

.aw-editorial {
  max-width: 640px;
  margin: 0 auto;
  padding: 56px 24px;
}

@media (min-width: 768px) {
  .aw-editorial {
    padding: 72px 56px;
  }
}

.aw-editorial-p {
  font-size: clamp(1.05rem, 1.5vw, 1.15rem);
  line-height: 1.7;
  color: var(--content);
  margin: 0 0 20px;
}

.aw-editorial-p:last-child {
  margin-bottom: 0;
}

/* Static hairline into the FilterBar — part of the page's normal flow
   (rendered as EditorialIntro's last element), never sticky, unlike the bar
   itself right below it. Same 72rem max-width as .aw-filterbar-inner so the
   rule lines up with the bar's own content width. */
.aw-editorial-divider {
  max-width: 72rem;
  margin: 0 auto;
  border-top: 1px solid var(--border);
}

/* ============================================
   SHARE ACTIONS — centered, scale-only hover
   ============================================ */

.aw-share {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.aw-share-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  background: var(--raised);
  border: 1px solid var(--border);
  color: var(--content);
  font-size: 0.82rem;
  font-weight: 600;
  padding: 9px 16px;
  border-radius: 9999px;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s ease-out;
}

/* Icon-only variant (Copy link). Square box at the labelled buttons' exact
   height — 16px glyph + 9px padding + 1px border each side — so the row reads
   as two pills and a coin rather than three mismatched shapes. */
.aw-share-btn--icon {
  width: 36px;
  height: 36px;
  padding: 0;
  gap: 0;
  justify-content: center;
}

.aw-share-btn:hover {
  transform: scale(1.06);
}

.aw-share-btn:active {
  transform: scale(0.98);
}

/* ============================================
   LISTING / GRID CARD MEDIA (shared)
   ============================================ */

.aw-card-photo {
  position: relative;
  width: 100%;
  overflow: hidden;
  background: var(--raised);
}

.aw-card-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition:
    opacity 0.4s ease-out,
    transform 0.4s ease-out;
}

.aw-card-photo img.is-loaded {
  opacity: 1;
}

.aw-card-photo-empty {
  width: 100%;
  height: 100%;
  background: linear-gradient(
    135deg,
    var(--raised),
    color-mix(in srgb, var(--raised) 70%, var(--border))
  );
}

/* Pulsing placeholder shown until a cover photo finishes loading (see
   CoverImage). Pulses the fill between --raised and a distinctly grayer
   --muted mix so the "loading" beat is clearly visible. */
.aw-card-photo-skeleton {
  position: absolute;
  inset: 0;
  z-index: 1;
  background-color: var(--raised);
  animation: aw-cover-pulse 1.8s ease-in-out infinite;
}

@keyframes aw-cover-pulse {
  0%,
  100% {
    background-color: var(--raised);
  }
  50% {
    background-color: color-mix(in srgb, var(--raised) 90%, var(--muted));
  }
}

@media (prefers-reduced-motion: reduce) {
  .aw-card-photo-skeleton {
    animation: none;
  }
}

/* ============================================
   FULL LIST GRID
   ============================================ */

/* ============================================
   CATEGORY SECTIONS — every category of a country stacked down one page as
   deep-linkable anchor sections (see CategorySection.tsx). The section id is
   the category slug, so /stories/2026-awards/usa#van-overland lands here and
   the legacy /usa/van-overland route redirects to it.
   ============================================ */

.aw-category {
  /* Clear the stuck FilterBar on an anchor jump — pill clicks, the URL hash on
     first paint, and the legacy-route redirect all land through this. */
  scroll-margin-top: var(--aw-sticky-offset);
}

/* Separation is carried entirely on the *trailing* edge — bottom padding and
   a bottom rule — never the leading one. Top padding would sit between the
   section's box edge and its heading, and scroll-margin-top offsets from the
   box edge, so every anchor jump would land the heading that far below the
   bar. This way the box top is the heading top and the jump is exact. */
.aw-category:not(:last-child) {
  padding-bottom: 88px;
  border-bottom: 1px solid var(--border);
}

.aw-category + .aw-category {
  margin-top: 88px;
}

@media (min-width: 768px) {
  .aw-category:not(:last-child) {
    padding-bottom: 112px;
  }

  .aw-category + .aw-category {
    margin-top: 112px;
  }
}

/* Editorial header: title, then a one-line tagline. */
.aw-category-header {
  margin-bottom: 40px;
}

.aw-category-heading {
  font-size: clamp(1.9rem, 3.6vw, 2.8rem);
  font-weight: 900;
  letter-spacing: -0.025em;
  line-height: 1.1;
  color: var(--content);
  margin: 0 0 12px;
}

.aw-category-tagline {
  max-width: 640px;
  color: var(--content);
  font-size: 1.05rem;
  line-height: 1.55;
  margin: 0;
}

.aw-grid-group {
  margin-bottom: 64px;
  /* Perf: the /usa page's Best in State section alone renders 151 winner
     cards across ~50 state groups plus ~400 runner-up links, and now sits on
     the same page as every other category. Off-screen groups skip layout
     and paint entirely until they're scrolled near — the browser reserves
     contain-intrinsic-size as a placeholder height so the page doesn't jump
     once a group renders for real. Jump-nav anchors still work: scrolling to
     an id forces the browser to render that target's content first. */
  content-visibility: auto;
  contain-intrinsic-size: auto 1200px;
}

@media (min-width: 768px) {
  .aw-grid-group {
    margin-bottom: 88px;
  }
}

.aw-grid-group:last-child {
  margin-bottom: 0;
}

/* No rule below the heading — the size/weight contrast with the body text
   and the generous margin above (this group's distance from the previous
   one) already separate it; a border here was doing little a bit more air
   above and a plain, close-set count don't already do. */
.aw-grid-group-heading {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 26px;
  /* Jump-nav anchor target: clear the sticky filter bar on scroll. */
  scroll-margin-top: var(--aw-sticky-offset);
}

/* Substantial editorial size — these read as their own headings ("New South
   Wales", "California"), not list labels — but clearly a step below the
   category h2 (.aw-category-heading, clamp 1.9–2.8rem/900) and clearly above
   card titles. Overrides ultralight's shared .text-subheading utility (fixed
   1.5rem/900) rather than editing it, since that class is used elsewhere. */
.aw-grid-group-heading .text-subheading {
  font-size: clamp(1.5rem, 2.5vw, 2rem);
  font-weight: 800;
  letter-spacing: -0.01em;
}

/* Tighten the heading's own margin when a tagline follows it — the tagline
   then owns the group's bottom air instead of stacking two gaps. A touch more
   than before since the bigger heading needs a bit more room to breathe. */
.aw-grid-group-heading:has(+ .aw-grid-group-tagline) {
  margin-bottom: 10px;
}

.aw-grid-group-tagline {
  max-width: 560px;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.5;
  margin: 0 0 22px;
}

.aw-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: 20px;
}

@media (min-width: 560px) {
  .aw-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 960px) {
  .aw-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
  }
}

/* Card shell */
.aw-card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  text-decoration: none;
  color: inherit;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 10px;
  box-shadow: var(--aw-shadow-sm);
  transition:
    transform 0.18s ease-out,
    box-shadow 0.18s ease-out;
}

.aw-grid-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--aw-shadow);
}

.aw-grid-card:hover .aw-card-photo img {
  transform: scale(1.04);
}

.aw-card .aw-card-photo {
  aspect-ratio: 4 / 3;
  border-radius: 14px;
}

.aw-card-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 12px 6px 6px;
  flex: 1;
}

.aw-card-loc {
  font-family: var(--font-mono), ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 0.6rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Curators' editorial write-up (or, failing that, the pulled review line).
   Same muted register as .aw-grid-group-tagline so the page's secondary voice
   reads consistently from group intro down to card body.

   Clamped to 5 lines: the blurbs run 200-285 characters, which is ~5 lines at
   a desktop card's ~336px of text width, so the clamp leaves the great
   majority intact and only catches the long tail — while still capping the
   worst case at the narrow 2-column breakpoint, where the same text would
   otherwise run 7+ lines and drag every card in the row taller with it.

   flex: 1 makes the blurb absorb the card body's spare vertical space rather
   than leaving it below the button. Grid rows stretch every card to the
   tallest in the row, so without this a 4-line blurb would float its CTA a
   line higher than its 5-line neighbour's. Growing the text box instead keeps
   .aw-card-cta's own 12px margin-top as a guaranteed minimum gap, which
   margin-top: auto on the button would have collapsed to zero. */
.aw-card-blurb {
  flex: 1 1 auto;
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.5;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 5;
  line-clamp: 5;
  overflow: hidden;
}

/* The CTA button sits above the cover-link overlay. */
.aw-card-cta {
  margin-top: 12px;
  width: 100%;
  position: relative;
  z-index: 2;
}

/* Stretched cover link makes the whole card clickable while the CTA button
   stays a separate, real <a href>. */
.aw-card-cover {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}

/* ============================================
   RUNNERS-UP — compact text links + small thumbs below the winner cards
   (light-green sheet rows are the lower tier, so no card treatment).
   ============================================ */

.aw-runners {
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
}

/* Same mono/uppercase/muted label treatment as .aw-card-loc and
   .aw-runner-loc, sized a step up since this one stands alone as a heading
   rather than sitting beside a card title. */
.aw-runners-label {
  font-family: var(--font-mono), ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 14px;
}

.aw-runner-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

@media (min-width: 768px) {
  .aw-runner-list {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 4px 20px;
  }
}

.aw-runner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 0;
  /* Hit target hugs the thumb + text — a full-width anchor turns the empty
     right half of every row into misclick surface. */
  width: fit-content;
  max-width: 100%;
  text-decoration: none;
  color: var(--content);
}

.aw-runner:hover .aw-runner-name {
  text-decoration: underline;
}

.aw-runner-thumb,
.aw-runner-thumb-empty {
  width: 64px;
  height: 64px;
  flex-shrink: 0;
  border-radius: 10px;
  background: var(--raised);
}

.aw-runner-thumb {
  object-fit: cover;
  display: block;
}

.aw-runner-thumb-empty {
  background: linear-gradient(
    135deg,
    var(--raised),
    color-mix(in srgb, var(--raised) 70%, var(--border))
  );
}

.aw-runner-body {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.aw-runner-name {
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.aw-runner-loc {
  font-family: var(--font-mono), ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 0.65rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ============================================
   METHODOLOGY — the "how winners were chosen" note at the very bottom of
   the country page, after the last category section and before the footer
   (see MethodologyNote.tsx). Reading-width like .aw-editorial, with a
   hairline above it to separate it from the last category's own bottom
   border rather than stacking two rules together.
   ============================================ */

.aw-methodology {
  max-width: 640px;
  margin: 0 auto;
  /* Bottom padding keeps the last item clear of the footer's top hairline. */
  padding: 72px 24px 72px;
  border-top: 1px solid var(--border);
}

@media (min-width: 768px) {
  .aw-methodology {
    padding: 96px 56px 96px;
  }
}

.aw-methodology-heading {
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  font-weight: 900;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--content);
  margin: 0 0 28px;
}

.aw-methodology-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.aw-methodology-item {
  font-size: clamp(1rem, 1.4vw, 1.05rem);
  line-height: 1.7;
  color: var(--muted);
  margin: 0;
}

.aw-methodology-item strong {
  color: var(--content);
  font-weight: 700;
}

/* ============================================
   LANDING HERO — the country cards + folded-in footer that live in the
   landing masthead's text column (see .aw-masthead--landing above and
   pages/stories/2026-awards/index.tsx). .aw-hero-eyebrow/.aw-hero-sub are
   shared with the country hero (AwardsHero.tsx); the rest here is landing-
   only.
   ============================================ */

.aw-hero-eyebrow {
  font-family: var(--font-mono), ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--primary);
  margin: 0 0 20px;
}

/* On country pages the eyebrow links back to the awards lander — quiet at
   rest, shifting to the content color on hover. */
.aw-hero-eyebrow-link {
  color: inherit;
  text-decoration: none;
  transition: color 0.15s ease;
}

.aw-hero-eyebrow-link:hover {
  color: var(--content);
}

.aw-hero-sub {
  max-width: 620px;
  margin: 0 auto 20px;
  color: var(--muted);
  line-height: 1.6;
}

/* Stacked column of country links — the landing page's real navigation, not
   a decorative grid, so each row is full-width with room for a flag, the
   label, and the award count. */
.aw-country-grid {
  list-style: none;
  padding: 0;
  margin: 0 0 20px;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.aw-country-card {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  text-align: left;
  text-decoration: none;
  color: inherit;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 16px 20px;
  box-shadow: var(--aw-shadow-sm);
  transition:
    transform 0.18s ease-out,
    box-shadow 0.18s ease-out,
    background-color 0.15s ease-out;
}

.aw-country-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--aw-shadow);
  background: var(--raised);
}

.aw-country-card-flag {
  font-size: 1.4rem;
  line-height: 1;
  flex-shrink: 0;
}

.aw-country-card-label {
  flex: 1;
  min-width: 0;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--content);
}

.aw-country-card-count {
  flex-shrink: 0;
  font-family: var(--font-mono), ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Bottom of the landing hero's text column, in place of a separate
   <AwardsFooter> band below the page — see AwardsFooterLinks. Structurally
   identical to .aw-masthead-scroll-row on the country hero: a flex-shrink: 0
   sibling after the flex: 1 .aw-masthead-content, in the same full-height
   .aw-masthead-text column. That's what actually pins it to the column's
   bottom edge (at any content length, in both the stacked and the ≥1200px
   split layout — .aw-masthead-text's height: 100% and flex column behavior
   are shared across both already), not any margin-auto override. */
.aw-masthead-footer-row {
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  width: 100%;
  padding-top: 20px;
}

/* ============================================
   ROUTE-TRANSITION SKELETON — sections-area placeholder shown while a
   same-shell country navigation is in flight (isNavigating in
   [country]/index.tsx). The masthead + FilterBar stay mounted and
   interactive; this is scoped to just the sections region.
   ============================================ */

.aw-skeleton-group {
  margin-bottom: 64px;
}

@media (min-width: 768px) {
  .aw-skeleton-group {
    margin-bottom: 88px;
  }
}

.aw-skeleton-group:last-child {
  margin-bottom: 0;
}

.aw-skeleton-heading {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 22px;
}

.aw-skeleton-bar {
  display: block;
  border-radius: 6px;
  background-color: var(--raised);
  animation: aw-cover-pulse 1.8s ease-in-out infinite;
}

.aw-skeleton-bar--heading {
  width: 160px;
  height: 22px;
}

.aw-skeleton-bar--count {
  width: 70px;
  height: 14px;
  margin-left: auto;
}

.aw-skeleton-bar--title {
  width: 70%;
  height: 14px;
  margin-top: 14px;
}

.aw-skeleton-bar--loc {
  width: 40%;
  height: 10px;
  margin-top: 8px;
}

.aw-skeleton-grid {
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: 20px;
}

@media (min-width: 560px) {
  .aw-skeleton-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 960px) {
  .aw-skeleton-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 24px;
  }
}

.aw-skeleton-card {
  display: flex;
  flex-direction: column;
}

.aw-skeleton-photo {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: 14px;
  background-color: var(--raised);
  animation: aw-cover-pulse 1.8s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .aw-skeleton-bar,
  .aw-skeleton-photo {
    animation: none;
  }
}

/* Winners content eases in (fade + tiny rise) once it replaces the skeleton,
   rather than popping. */
.aw-grid-enter {
  animation: aw-grid-enter 0.3s ease-out;
}

@keyframes aw-grid-enter {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .aw-grid-enter {
    animation: none;
  }
}
