/* WLSC — wlscglobal.com
   Palette and type follow the brand spec. The one signature device is the
   measurement rule (.measure): a hairline with ticks, used as the section mark
   and nowhere else, so it reads as the competition's own mark rather than
   decoration. Everything around it is deliberately quiet. */

/* The display face, self-hosted rather than pulled from a font CDN: same origin,
   no third-party request, and it is in the delivery zip like everything else.
   Bodoni Moda is the open Didone — the classification Vogue, Harper's Bazaar and
   Elle have set their mastheads in for decades — and it is variable on an
   optical-size axis, which is the answer to the one real weakness of the style:
   the hairlines thicken automatically as the type gets smaller, so a 60px
   heading keeps its blade-thin strokes while a 15px year does not disappear.

   The subset is Latin, Latin Extended and Vietnamese only, 53KB. CJK, Thai and
   Myanmar glyphs fall outside the unicode-range and never trigger a download —
   they resolve to the per-locale serif set in the page head. */
/* The body face. Vogue's own split since 2015 is the model: a Didone masthead
   over a bespoke sans for the spreads — display type carries the character,
   body type gets out of the way. Instrument Sans is a variable grotesque with
   slightly narrower forms than Helvetica, which is what the old
   Helvetica/Arial stack was reaching for and never got consistently. The width
   axis is pinned at 100 and only weight is kept variable, which is what brings
   it to 31KB. */
@font-face {
  font-family: "Instrument Sans";
  src: url("/assets/fonts/instrument-sans-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-024F, U+1E00-1EFF, U+2000-206F, U+2122, U+20AB, U+2192;
}

@font-face {
  font-family: "Bodoni Moda";
  src: url("/assets/fonts/bodoni-moda-latin.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-024F, U+1E00-1EFF, U+2000-206F, U+2122, U+20AB, U+2192;
}

:root {
  --black: #0b0908;
  --ink: #261813;
  --porcelain: #f3eee8;
  --brown: #7f5b55;
  --bronze: #b8794b;
  --champagne: #e8d4b7;

  --paper: var(--black);
  --paper-2: #120d0b;
  --text: #ded6cd;
  --text-dim: #a3968b;
  --line: rgba(184, 121, 75, 0.28);
  /* The outlined section numerals; a variable so a light section can flip it. */
  --stroke: rgba(184, 121, 75, 0.6);

  /* The light half of the page. Everything a paper section needs is declared
     once here and re-pointed by .sec--paper, so a palette change is these six
     values and nothing else. */
  --ivory: #f4eade;
  --ivory-2: #ece0d0;
  --ink: #38291f;
  --ink-strong: #17110d;
  --ink-dim: #6d5b4d;
  --bronze-ink: #96602f;
  --line-ink: rgba(56, 41, 31, 0.22);
  --stroke-ink: rgba(150, 96, 47, 0.5);

  /* Overridden per locale in the page head with the matching CJK/Thai serif;
     this is only the fallback for a document that somehow has no head style. */
  --font-display: "Bodoni Moda", "Didot", "Bodoni MT", Georgia, serif;
  --font-body: "Instrument Sans", system-ui, sans-serif; /* per locale in the head */

  --wrap: 1180px;
  --narrow: 720px;
  --step: clamp(3.5rem, 7vw, 6.5rem);
}

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.7;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

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

a { color: var(--champagne); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--porcelain); }

/* The home-page header is fixed, so an in-page jump would otherwise land the
   target underneath it. */
[id] { scroll-margin-top: 124px; }
@media (max-width: 900px) { [id] { scroll-margin-top: 88px; } }

:focus-visible {
  outline: 2px solid var(--champagne);
  outline-offset: 3px;
  border-radius: 2px;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 400;
  color: var(--porcelain);
  line-height: 1.15;
  letter-spacing: 0.01em;
  margin: 0 0 0.6em;
}
h1 { font-size: clamp(2.1rem, 5vw, 3.5rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2.1rem); margin-top: 2em; }
h3 { font-size: 1.2rem; }

p { margin: 0 0 1.1em; max-width: 70ch; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--champagne); color: var(--black); padding: 0.7rem 1.2rem;
}
.skip:focus { left: 0; }

.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
.wrap--narrow { width: min(100% - 2.5rem, var(--narrow)); }

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

.hd {
  position: sticky; top: 0; z-index: 60;
  background: rgba(11, 9, 8, 0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
/* The header is deliberately full-bleed rather than sharing the content
   container: the wordmark sits against the left edge of the row and everything
   else against the right, which is what keeps the bar reading as a frame around
   the film rather than a centred block floating on top of it. */
.hd__in {
  position: relative; z-index: 1;
  width: 100%; max-width: none; margin-inline: 0;
  padding-inline: clamp(1rem, 2.2vw, 2.25rem);
  display: flex; align-items: center; gap: 1.5rem;
  /* Measured against the reference bar: its type sits 47px below the top of
     the page and ours sat at 29px, which is what made the row feel cramped
     under the browser chrome. At 112px with 17px type the gap lands at ~43px. */
  min-height: 112px;
}
.hd__mark img { width: 132px; height: auto; }
.hd__cb { display: none; }
.hd__burger { display: none; }

.hd__nav { margin-left: auto; display: flex; align-items: center; gap: 1.6rem; }
.hd__links {
  display: flex; align-items: center; gap: 1.75rem;
  list-style: none; margin: 0; padding: 0;
  /* 17px / 600. The reference bar measures a 15px cap height against our 11px,
     so it is running roughly 1.36x our old 0.88rem at a heavier weight. 17px
     rather than 19px because CJK glyphs are full-width: six items of four
     characters each already runs ~410px before the language picker and CTA. */
  font-size: 1.0625rem; font-weight: 600; letter-spacing: 0.01em;
}
.hd__links > li { position: relative; }
.hd__links a { color: var(--porcelain); text-decoration: none; white-space: nowrap; }
.hd__links a:hover,
.hd__links a[aria-current="page"] { color: var(--champagne); }
.hd__end { display: flex; align-items: center; gap: 1.25rem; }

/* Grouped nav item. <details> gives open/close and keyboard support with no
   script; the hover rule below is an addition on pointer devices, not the only
   way in, so it still works on touch and by keyboard. */
.drop > summary {
  list-style: none; cursor: pointer; color: var(--porcelain);
  display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap;
}
.drop > summary::-webkit-details-marker { display: none; }
.drop[open] > summary,
.drop > summary:hover { color: var(--champagne); }
.drop__caret {
  width: 0; height: 0; margin-top: 2px;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 4px solid currentColor; opacity: .7;
}
.drop[open] .drop__caret { transform: rotate(180deg); }
.drop__list {
  position: absolute; left: -1rem; top: calc(100% + .9rem); z-index: 70;
  background: var(--paper-2); border: 1px solid var(--line);
  list-style: none; margin: 0; padding: .4rem 0; min-width: 12rem;
}
.drop__list a { display: block; padding: .55rem 1.1rem; font-size: .95rem; font-weight: 400; }
.drop__list a:hover { background: rgba(184,121,75,.16); color: var(--porcelain); }
/* A hairline bridges the gap between the summary and the panel so the pointer
   can travel down without the panel closing under it. */
.drop[open] > summary::after {
  content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 1rem;
}

.lang { position: relative; font-size: 1.0625rem; font-weight: 600; }
.lang > summary {
  list-style: none; cursor: pointer; color: var(--porcelain);
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.5rem 1rem;
  border: 1px solid rgba(255, 255, 255, 0.26); border-radius: 999px;
  transition: border-color 0.22s ease, background 0.22s ease;
}
.lang > summary::-webkit-details-marker { display: none; }
.lang > summary::after {
  content: ""; width: 0; height: 0; margin-left: 0.1rem;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 4px solid currentColor; opacity: 0.65;
  transition: transform 0.22s ease;
}
.lang[open] > summary::after { transform: rotate(180deg); }
.lang > summary:hover,
.lang[open] > summary {
  border-color: rgba(255, 255, 255, 0.7);
  background: rgba(255, 255, 255, 0.08);
}
.lang__list { margin-top: 0.55rem; }
.lang__globe { color: var(--bronze); }
.lang__list {
  position: absolute; right: 0; top: 100%; z-index: 70;
  background: var(--paper-2); border: 1px solid var(--line);
  border-radius: 14px; overflow: hidden;
  list-style: none; margin: 0.55rem 0 0; padding: 0.4rem 0;
  min-width: 168px;
}
.lang__list a { display: block; padding: 0.5rem 1rem; text-decoration: none; color: var(--text); font-size: .95rem; font-weight: 400; }
.lang__list a:hover, .lang__list a[aria-current="true"] { background: rgba(184,121,75,0.16); color: var(--porcelain); }

/* Two button ranks and one motion, used everywhere.
   PRIMARY is a solid gold pill; SECONDARY is a white pill that is transparent
   apart from its hairline, which is what lets it sit over the film without
   punching a hole in the artwork. The arrow is part of the button rather than
   the label, so it is identical on every one of them and no translator has to
   remember to include it. */
.btn {
  display: inline-flex; align-items: center; gap: 0.6rem;
  padding: 0.78rem 1.65rem;
  font-size: 0.9rem; font-weight: 600; letter-spacing: 0.04em;
  text-decoration: none; border: 1px solid transparent; white-space: nowrap;
  border-radius: 999px; cursor: pointer;
  transition: background 0.22s ease, border-color 0.22s ease, color 0.22s ease;
}
.btn::after {
  content: "→";
  font-size: 0.95em; line-height: 1;
  transition: transform 0.22s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.btn:hover::after,
.btn:focus-visible::after { transform: translateX(4px); }

/* A button that goes back points back, and its arrow leans the other way. */
.btn--back::after { content: "←"; }
.btn--back:hover::after,
.btn--back:focus-visible::after { transform: translateX(-4px); }

.hd__end .btn { padding: 0.7rem 1.55rem; font-size: 0.95rem; }

/* The gradient is two stops a few percent apart — enough to read as metal
   under a highlight, not enough to look like a web gradient. */
.btn--gold {
  background: linear-gradient(180deg, #f2e2c6 0%, #ddc399 100%);
  color: #1c130c; border-color: #e8d4b7;
}
.btn--gold:hover,
.btn--gold:focus-visible {
  background: linear-gradient(180deg, #fbf0dc 0%, #e9d3ae 100%);
  color: #1c130c;
}

.btn--ghost {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.55);
  color: #fff;
}
.btn--ghost:hover,
.btn--ghost:focus-visible {
  background: rgba(255, 255, 255, 0.13);
  border-color: #fff;
  color: #fff;
}

/* ------------------------------------------------------------ hero

   Two states, one frame. The film's last frame IS the still, so `is-done`
   only has to reveal the still underneath and drop the video out — there is
   nothing to cross-fade because both show the same pixels.

   The film and the still are letterboxed to #0B0908 on phones (the pad is
   baked into the media, see tools/build-video.sh), and object-fit:cover only
   ever trims the top and bottom on desktop, never the sides, because the
   wordmark sits on the left. That is what the aspect clamp below guarantees. */

.hero {
  position: relative;
  isolation: isolate;
  background: var(--black);
  /* 56.25vw is exactly 16:9, so on any window shorter than that the film fills
     edge to edge with no crop at all. On a short window it caps at the viewport
     and cover trims top and bottom only. */
  height: min(100svh, 56.25vw);
  min-height: 440px;
}

.hero__still,
.hero__still img,
.hero__film {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
.hero__still { z-index: 0; }
.hero__film {
  z-index: 1;
  opacity: 0;
  transition: opacity .45s ease;
  background: var(--black);
}
.hero.is-playing .hero__film { opacity: 1; }
.hero.is-done .hero__film { display: none; }

/* The skip control sits against the right edge of the screen and exists only
   while the film is running. */
/* The skip control is a secondary button that happens to be pinned to the edge
   of the screen: same white transparent pill, same arrow, flattened on the side
   that meets the frame. */
.hero__skip {
  position: absolute;
  z-index: 3;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .8rem 1.4rem;
  border: 1px solid rgba(255, 255, 255, .5);
  border-right: 0;
  border-radius: 999px 0 0 999px;
  background: rgba(255, 255, 255, .06);
  backdrop-filter: blur(8px);
  color: #fff;
  font: inherit;
  font-size: .88rem;
  font-weight: 600;
  letter-spacing: .06em;
  cursor: pointer;
  transition: background .22s ease, border-color .22s ease;
}
.hero__skip span {
  display: inline-block;
  transition: transform .22s cubic-bezier(.22, .61, .36, 1);
}
.hero__skip:hover,
.hero__skip:focus-visible {
  background: rgba(255, 255, 255, .15);
  border-color: #fff;
}
.hero__skip:hover span,
.hero__skip:focus-visible span { transform: translateX(4px); }
.hero__skip[hidden] { display: none; }

/* The buttons belong to the still, so they appear with it and are absent while
   the film runs. Their position is anchored to the artwork's own type: on the
   wide cut the baked date sits at roughly 66% down and 8% in, so the buttons
   land directly beneath it. */
.hero__cta {
  position: absolute;
  z-index: 2;
  left: 8%;
  top: 78%;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .8rem;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .5s ease .15s, transform .5s ease .15s;
  pointer-events: none;
}
.hero.is-done .hero__cta,
.hero.no-film .hero__cta {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* Visually hidden, still read by assistive tech and by crawlers. */
.vh {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* On the home page the header floats over the film rather than sitting above
   it, so the media reaches the very top of the window. It gains its background
   as soon as the page scrolls. */
body.is-home .hd {
  position: fixed;
  inset-inline: 0;
  top: 0;
  background: transparent;
  border-bottom-color: transparent;
  backdrop-filter: none;
  transition: background .3s ease, border-color .3s ease, backdrop-filter .3s ease;
}
/* THE BAR NEEDS A PLATE, NOT A SHADOW.
   Measured over the live film, the nav type was running at 1.11:1 against the
   background on the Chinese page — not "hard to read", but within a couple of
   percent of the same luminance as what is behind it. A text-shadow cannot fix
   that: the background is a video whose brightness changes every frame, so any
   fixed colour is wrong for half of them.
   The fix is a scrim: a gradient that darkens the top of the frame only, sits
   behind the bar's own content, and never intercepts a click. With it, white
   type holds about 6:1 against even the brightest frame of the film — above
   WCAG AA — and the film below the gradient is untouched. */
body.is-home .hd:not(.is-stuck)::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 210px;
  background: linear-gradient(
    to bottom,
    rgba(6, 4, 4, .78) 0%,
    rgba(6, 4, 4, .50) 40%,
    rgba(6, 4, 4, .20) 72%,
    rgba(6, 4, 4, 0) 100%
  );
  pointer-events: none;
  z-index: 0;
}
body.is-home .hd:not(.is-stuck) .hd__links a,
body.is-home .hd:not(.is-stuck) .drop > summary,
body.is-home .hd:not(.is-stuck) .lang > summary {
  color: #fff;
  /* A tight shadow adds edge definition on top of the scrim. The old one was a
     12px blur, which spreads too thin to create any contrast at all. */
  text-shadow: 0 1px 2px rgba(0, 0, 0, .75);
}
body.is-home .hd:not(.is-stuck) .hd__mark img {
  filter: drop-shadow(0 2px 10px rgba(0, 0, 0, .6));
}
body.is-home .hd.is-stuck {
  background: rgba(11, 9, 8, .86);
  border-bottom-color: var(--line);
  backdrop-filter: blur(10px);
}
body.is-home .hero { margin-top: 0; }

@media (max-width: 720px) {
  /* The phone plate is its own 9:16 composition with the lockup and the date
     set into it, so nothing is laid over it: the section is a two-row grid —
     the plate, then the buttons in the black beneath it. The top padding is the
     header's own height, so the floating logo never lands on the lockup. */
  /* The hero is no longer a screen: it is a block. Nav, then the film at 16:9,
     then the two buttons, then the page continues. Nothing is 100svh, so the
     address bar collapsing cannot resize anything, and nothing is absolutely
     positioned against a frame that no longer exists.

     The plate stays as the background, but a short box cropped to its bottom
     edge means it only ever shows in the strip behind the buttons. */
  .hero {
    height: auto; min-height: 0;
    display: grid;
    grid-template-rows: auto auto;
    padding: 0;
    background:
      linear-gradient(
        180deg,
        rgba(5, 4, 3, 0) 0%,
        rgba(8, 5, 3, .28) 30%,
        rgba(5, 4, 3, .82) 100%
      ),
      url("/assets/img/hero-bg-9x16.jpg") center bottom / cover no-repeat;
    overflow: hidden;
    transition: none;
  }
  /* Both media elements share one cell so the still can take over from the film
     in place, and the cell is 16:9 — the phone cut is a 16:9 picture centred on
     a 9:16 canvas, so cover puts its baked bars exactly outside the box. */
  .hero__still,
  .hero__film {
    position: relative; inset: auto;
    grid-row: 1; grid-column: 1;
    width: 100%; height: auto; aspect-ratio: 16 / 9;
    object-fit: cover;
    z-index: 1;
  }
  .hero__still img { height: 100%; object-position: 50% 50%; }
  /* With the header in flow above it, the hero starts below the bar. */
  body.is-home .hd { position: sticky; background: rgba(11, 9, 8, .92); }
  body.is-home .hd:not(.is-stuck)::before { content: none; }

  /* Skip belongs to the film, so it lives on the film: a small translucent
     control in its bottom-right corner. */
  .hero__skip {
    position: relative;
    grid-row: 1; grid-column: 1; z-index: 3;
    justify-self: end; align-self: end;
    right: auto; top: auto; transform: none;
    margin: 0 12px 12px;
    padding: .5rem .9rem;
    border: 1px solid rgba(235, 205, 145, .3);
    border-radius: 999px;
    background: rgba(8, 6, 5, .42);
    backdrop-filter: blur(10px);
    color: rgba(246, 240, 230, .88);
    font-size: .7rem; font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  }
  .hero__skip:hover,
  .hero__skip:focus-visible {
    background: rgba(8, 6, 5, .62);
    border-color: rgba(235, 205, 145, .5);
    color: #fff;
  }

  .hero__cta {
    position: relative;
    inset: auto;
    grid-row: 2; z-index: 3;
    display: grid; gap: 10px;
    width: auto; margin: 0;
    padding: 18px 24px 14px;
    opacity: 1; transform: none; pointer-events: auto;
  }
  .hero__cta .btn {
    width: 100%; height: 54px;
    justify-content: center; gap: .8rem;
    padding: 0 1.4rem;
    border-radius: 999px;
    font-size: 16px; font-weight: 500; letter-spacing: .03em;
    transition: transform .12s ease, background .22s ease, border-color .22s ease, color .22s ease;
  }
  /* The arrow gets a ring of its own: it reads as a control rather than as
     punctuation stuck to the end of the label. */
  .hero__cta .btn::after {
    width: 28px; height: 28px; flex: none;
    display: grid; place-items: center;
    border: 1px solid currentColor;
    border-radius: 50%;
    font-size: .8em;
    opacity: .75;
  }
  .hero__cta .btn--gold {
    background: linear-gradient(110deg, #f7e8c9, #d7b46a 55%, #f3e3c2);
    border-color: transparent;
    color: #160e08;
    box-shadow: 0 12px 40px rgba(201, 151, 67, .18);
    position: relative; overflow: hidden;
  }
  .hero__cta .btn--ghost {
    background: rgba(8, 6, 5, .48);
    border: 1px solid rgba(235, 205, 145, .42);
    backdrop-filter: blur(12px);
    color: #f6f0e6;
  }
  /* 120ms, and small enough to feel like pressure rather than a bounce. */
  .hero__cta .btn:active { transform: scale(.985); }

  @media (prefers-reduced-motion: no-preference) {
    /* backwards, not both: with `both` the animation keeps owning transform
       after it ends, and an animated value outranks a normal declaration — the
       pressed state would silently do nothing. */
    .hero__cta .btn { animation: hero-rise .6s cubic-bezier(.2, .7, .2, 1) backwards; }
    .hero__cta .btn--gold { animation-delay: .8s; }
    .hero__cta .btn--ghost { animation-delay: 1s; }
    /* One pass of light every five seconds: 700ms of travel, then nothing. */
    .hero__cta .btn--gold::before {
      content: "";
      position: absolute; inset: 0; pointer-events: none;
      background: linear-gradient(105deg,
        rgba(255, 255, 255, 0) 38%,
        rgba(255, 252, 244, .5) 50%,
        rgba(255, 255, 255, 0) 62%);
      transform: translateX(-120%);
      animation: hero-sheen 5s linear 1.6s infinite;
    }
    .hero__skip { animation: hero-rise .6s cubic-bezier(.2, .7, .2, 1) backwards; }
  }
}

@keyframes hero-rise {
  from { opacity: 0; transform: translateY(16px); }
  to { opacity: 1; transform: none; }
}
@keyframes hero-sheen {
  0% { transform: translateX(-120%); }
  14% { transform: translateX(120%); }
  100% { transform: translateX(120%); }
}

@media (prefers-reduced-motion: reduce) {
  .hero__film { display: none !important; }
  .hero__skip { display: none !important; }
  .hero__cta { opacity: 1; transform: none; pointer-events: auto; }
}

/* ------------------------------------------------------------ judge page

   The judge hero borrows the home page's treatment — full-bleed plate, its own
   9:16 composition on phones, the header floating over it with the same scrim.
   The one difference is that these plates arrive text-free, so the type is real
   HTML and exists in all seven languages rather than being baked into artwork. */

.jhero {
  position: relative;
  isolation: isolate;
  background: var(--black);
  /* Full viewport, not 56.25vw: capping at the plate's own 16:9 left a band of
     background below it on a wide screen, which read as the image failing to
     fill the hero. Cover crops the top and bottom instead — see the
     object-position note below for why that is safe here. */
  height: 100svh;
  min-height: 560px;
  display: grid;
  align-items: end;
}
.jhero__bg,
.jhero__bg img {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; object-fit: cover;
  /* Anchored above centre. On a wide window cover trims the top and bottom of
     a 16:9 plate, and the subject's head sits near the top edge — centring the
     crop would clip her hairline. */
  object-position: 50% 28%;
}
.jhero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(
    92deg,
    rgba(11, 9, 8, .95) 0%,
    rgba(11, 9, 8, .86) 26%,
    rgba(11, 9, 8, .55) 46%,
    rgba(11, 9, 8, .12) 66%,
    rgba(11, 9, 8, .45) 100%
  );
}
/* Aligned to the header, not to the content container. The narrower centred
   container started the type ~370px in on a 1920 screen, which left it floating
   in the middle of the frame instead of anchored to the edge the wordmark sits
   on. Same padding value as .hd__in, so the two share an origin — then the copy
   is pushed right to where the wordmark's A ends: measured on wlsc-mark.png the
   A's serif closes at x=201 of 420, which at the 132px render width is 63px. */
.jhero__in {
  width: 100%;
  margin-inline: 0;
  padding: 0 clamp(1rem, 2.2vw, 2.25rem) clamp(3.5rem, 8vw, 6.5rem);
  padding-left: calc(clamp(1rem, 2.2vw, 2.25rem) + 63px);
  max-width: 62rem;
}
.jhero__eyebrow {
  font-size: .82rem; letter-spacing: .32em; color: var(--bronze);
  text-transform: uppercase; margin: 0 0 1.3rem;
}
.jhero__name {
  font-family: var(--font-display);
  font-size: clamp(3rem, 7.6vw, 6rem);
  line-height: 1.0; letter-spacing: .005em;
  color: var(--porcelain); margin: 0 0 1.2rem; max-width: 12ch;
}
.jhero__name span {
  display: block; font-size: .26em; letter-spacing: .18em;
  color: var(--champagne); margin-top: .9rem;
}
.jhero__lede { color: var(--text); max-width: 42ch; font-size: 1.15rem; line-height: 1.75; }

.jstats {
  list-style: none; margin: 2.4rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 3rem;
}
.jstats b {
  display: block; font-family: var(--font-display); font-weight: 400;
  font-size: clamp(2.4rem, 4.6vw, 3.6rem); color: var(--champagne); line-height: 1;
}
.jstats span {
  display: block; margin-top: .5rem;
  font-size: .9rem; letter-spacing: .04em; color: var(--text-dim);
}

.kicker {
  font-size: .74rem; letter-spacing: .28em; text-transform: uppercase;
  color: var(--bronze); margin: 0 0 .7rem;
}

/* A numbered index, not a row of pills. Six rounded capsules read as buttons —
   something to click — when the content is a list of qualifications to read.
   Two columns of hairline-separated lines is how a magazine sets the same
   thing, and it costs no words. */
.idx {
  list-style: none; padding: 0; margin: 2.2rem 0 0;
  counter-reset: idx;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(2rem, 5vw, 4.5rem);
}
.idx li {
  display: flex; gap: 1rem; align-items: baseline; min-width: 0;
  border-top: 1px solid var(--line);
  padding: .85rem 0; font-size: .98rem; line-height: 1.5; color: var(--text);
}
.idx li::before {
  content: counter(idx, decimal-leading-zero); counter-increment: idx;
  flex: none; font-family: var(--font-display);
  font-size: .78rem; letter-spacing: .1em; color: var(--bronze);
}

/* A pull quote is the one place on the page allowed to shout. Centred and set
   at 2.3rem it was neither a quote nor a display line; left-anchored at
   editorial size against the same left edge as everything else, it is. */
.pull { margin: 0; text-align: left; }
.pull p {
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 5vw, 4.25rem);
  line-height: 1.12; letter-spacing: -.01em; color: var(--porcelain);
  margin: 0 0 1.6rem; max-width: 20ch;
  /* Even lines rather than a long first line and a short second one. */
  text-wrap: balance;
}
/* A measure in `ch` is a Latin measure: `ch` is the width of a zero, about half
   an em, so 20ch holds only ten CJK glyphs and the sentence broke in the middle
   of a word — 客 on one line, 戶 on the next. Chinese, Japanese and Korean get a
   measure in em, wide enough for the whole line at a size where CJK still reads
   as display type. auto-phrase asks the browser to break at phrase boundaries
   where it can do so; browsers that don't support it fall back to balance. */
html[lang="zh-Hant"] .pull p,
html[lang="ja"] .pull p,
html[lang="ko"] .pull p {
  font-size: clamp(1.9rem, 3.2vw, 2.5rem);
  line-height: 1.4; letter-spacing: 0;
  max-width: 22em;
  word-break: auto-phrase;
}
.pull cite {
  font-style: normal; font-size: .76rem; letter-spacing: .22em;
  color: var(--bronze); text-transform: uppercase;
}

/* Editorial plate, not a product grid. Four equal columns made the gallery read
   as a catalogue; a 12-column bed with a 7/5 then 5/7 rhythm gives the same four
   pictures and captions an asymmetric magazine spread. The pattern repeats every
   four, so a judge with six pictures gets the same rhythm rather than a special
   case. */
.jgallery {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(1.2rem, 2vw, 1.6rem);
  grid-template-columns: repeat(12, minmax(0, 1fr));
}
.jgallery li { grid-column: span 6; min-width: 0; }
.jgallery li:nth-child(4n + 1),
.jgallery li:nth-child(4n) { grid-column: span 7; }
.jgallery li:nth-child(4n + 2),
.jgallery li:nth-child(4n + 3) { grid-column: span 5; }
.jgallery li:only-child { grid-column: span 12; }
/* The pictures in a row are different widths, so a fixed ratio would leave them
   ragged: one declared height per row and each image crops into it. The height
   is explicit rather than a flex minimum because `img { height: 100% }` only
   resolves against a parent whose height is already definite. */
.jgallery figure { margin: 0; }
.jgallery picture { display: block; height: clamp(240px, 24vw, 420px); }
.jgallery img { width: 100%; height: 100%; object-fit: cover; }
.jgallery figcaption { margin-top: .7rem; font-size: .82rem; color: var(--text-dim); }

/* ---------------------------------------------------------- chapter grounds

   One ground per section instead of one ground per page. A single alternation
   is still a two-colour page: the eye reads "light, dark, light, dark" and
   stops registering it after the second turn. Six grounds that rotate hue —
   warm paper, black, cool bone, wine, sage, warm sand — read as chapters, which
   is what a magazine actually does.

   Restraint is in the saturation, not the count: every light ground sits in the
   same narrow lightness band and every dark one in another, so the page changes
   temperature without changing brightness. Each class only re-points the
   variables the rest of the stylesheet already reads, so no rule below is
   written twice for light and dark. */
.sec--paper, .sec--sand, .sec--bone, .sec--sage,
.sec--ink, .sec--wine, .sec--forest { color: var(--text); }

.sec--paper {
  background: #f4eade;
  --paper: #f4eade; --paper-2: #ece0d0;
  --text: #38291f; --text-dim: #6d5b4d; --porcelain: #17110d;
  --bronze: #96602f; --champagne: #96602f;
  --line: rgba(56, 41, 31, .22); --stroke: rgba(150, 96, 47, .5);
}
.sec--sand {
  background: #e8dccb;
  --paper: #e8dccb; --paper-2: #ded0bb;
  --text: #3b3126; --text-dim: #6e6152; --porcelain: #1b150e;
  --bronze: #8a5a2b; --champagne: #8a5a2b;
  --line: rgba(59, 49, 38, .24); --stroke: rgba(138, 90, 43, .5);
}
.sec--bone {
  background: #eceae4;
  --paper: #eceae4; --paper-2: #e1dfd7;
  --text: #262524; --text-dim: #63615c; --porcelain: #131211;
  --bronze: #7b2230; --champagne: #7b2230;
  --line: rgba(38, 37, 36, .2); --stroke: rgba(123, 34, 48, .45);
}
.sec--sage {
  background: #e4e7de;
  --paper: #e4e7de; --paper-2: #d9ddd2;
  --text: #23291f; --text-dim: #5d665a; --porcelain: #11150f;
  --bronze: #3f6b57; --champagne: #3f6b57;
  --line: rgba(35, 41, 31, .2); --stroke: rgba(63, 107, 87, .5);
}
.sec--ink {
  background: #0b0908;
  --paper: #0b0908; --paper-2: #120d0b;
  --text: #ded6cd; --text-dim: #a3968b; --porcelain: #f3eee8;
  --bronze: #b8794b; --champagne: #e8d4b7;
  --line: rgba(184, 121, 75, .28); --stroke: rgba(184, 121, 75, .6);
}
.sec--wine {
  background: #170a0d;
  --paper: #170a0d; --paper-2: #1e0e12;
  --text: #e3d3d1; --text-dim: #a3908d; --porcelain: #f6eeec;
  --bronze: #c08a7e; --champagne: #e8d4b7;
  --line: rgba(192, 138, 126, .3); --stroke: rgba(192, 138, 126, .6);
}
.sec--forest {
  background: #09110e;
  --paper: #09110e; --paper-2: #0d1713;
  --text: #d5ded7; --text-dim: #8c9a92; --porcelain: #eef3ef;
  --bronze: #7fa894; --champagne: #d9c79d;
  --line: rgba(127, 168, 148, .28); --stroke: rgba(127, 168, 148, .55);
}

/* Light next to dark wants a seam, not a butt joint. */
.sec--paper + .sec--ink, .sec--paper + .sec--wine, .sec--paper + .sec--forest,
.sec--sand + .sec--ink, .sec--sand + .sec--wine, .sec--sand + .sec--forest,
.sec--bone + .sec--ink, .sec--bone + .sec--wine, .sec--bone + .sec--forest,
.sec--sage + .sec--ink, .sec--sage + .sec--wine, .sec--sage + .sec--forest {
  border-top: 1px solid rgba(0, 0, 0, .55);
}

/* ---------------------------------------------------------- judge editorial

   Everything below the hero. The problem it solves: six sections of the same
   17px paragraph in the same full-width column, which reads as documentation.
   The fixes are all structural rather than decorative — a numbered head with a
   narrow left rail, one distinct shape per section (columns, index rows,
   timeline, plate), and hairlines instead of boxes. */

.jsec__h {
  display: grid;
  grid-template-columns: minmax(0, 7.5rem) minmax(0, 1fr);
  gap: 0 clamp(1.5rem, 3vw, 3rem);
  margin-bottom: clamp(2.5rem, 4vw, 3.5rem);
}
/* Outlined, so a 3.5rem numeral sits behind the title rather than competing
   with it. */
.jsec__n {
  font-family: var(--font-display);
  font-size: clamp(2.6rem, 4vw, 3.6rem);
  line-height: .9; margin: 0;
  color: transparent;
  -webkit-text-stroke: 1px var(--stroke);
}
.jsec__t { min-width: 0; }
.jsec__t .measure { margin-bottom: 1.1rem; }
.jsec .sec__lead { margin-bottom: 0; }

/* The judging lens is an index, not a second set of cards: title in the middle
   rail, the reasoning in the wide one, a hairline per row. */
.lens { list-style: none; margin: 0; padding: 0; counter-reset: lens; }
.lens__row {
  display: grid;
  grid-template-columns: minmax(0, 3rem) minmax(0, 15rem) minmax(0, 1fr);
  gap: 0 clamp(1.5rem, 3vw, 3rem);
  align-items: baseline;
  border-top: 1px solid var(--line);
  padding: 1.6rem 0;
}
.lens__row::before {
  content: counter(lens, decimal-leading-zero); counter-increment: lens;
  font-family: var(--font-display); font-size: .95rem;
  color: var(--bronze); letter-spacing: .08em;
}
.lens__t {
  margin: 0; font-size: clamp(1.15rem, 1.7vw, 1.5rem);
  color: var(--porcelain); line-height: 1.25;
}
.lens__b { margin: 0; color: var(--text-dim); font-size: .97rem; max-width: 54ch; }

/* Years are the spine of a career section, so they get display type. */
body.is-judge .tl li {
  grid-template-columns: minmax(0, 9rem) minmax(0, 1fr);
  gap: 0 clamp(1.5rem, 3vw, 3rem);
  padding: 1.5rem 0; align-items: baseline;
}
body.is-judge .tl time {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 2.4vw, 2.1rem);
  color: var(--champagne); line-height: 1;
}
body.is-judge .tl span { color: var(--text); max-width: 60ch; display: block; }

/* The thesis of the page gets set as a statement, not as a paragraph. */
body.is-judge #standard .lede {
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.1vw, 1.85rem);
  line-height: 1.4; color: var(--porcelain); max-width: 34ch;
}

/* Rules above and below turn the quote into a spread of its own. */
.pull {
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding-block: clamp(2.5rem, 5vw, 4rem);
}

/* Sources read as a contents page: the label at reading size, the grade set
   away from it in small bronze caps. */
.srclist a { padding: 1.15rem 0; }
.srclist__label { font-size: 1.02rem; }

/* Numbered captions, straight from the grid position. */
.jgallery { counter-reset: gal; }
.jgallery figcaption::before {
  content: counter(gal, decimal-leading-zero) " · "; counter-increment: gal;
  color: var(--bronze); letter-spacing: .1em;
}
.jgallery picture { overflow: hidden; }
.jgallery img { transition: transform 1.1s cubic-bezier(.2, .7, .2, 1); }
.jgallery li:hover img { transform: scale(1.045); }

/* A hairline ties the hero figures to the same rule language as the sections. */
.jstats { border-top: 1px solid var(--line); padding-top: 1.4rem; }

/* Reveal on scroll. The class is added by script, so with JS off nothing is
   ever hidden, and the whole thing is skipped when the visitor asks for less
   motion. */
@media (prefers-reduced-motion: no-preference) {
  body.is-judge .rv {
    opacity: 0; transform: translateY(16px);
    transition: opacity .8s ease, transform .8s cubic-bezier(.2, .7, .2, 1);
  }
  body.is-judge .rv.in { opacity: 1; transform: none; }
}

/* Sources are the point of the page, so they get a real list rather than a
   footnote: label on the left, evidence grade on the right. */
.srclist { list-style: none; margin: 0 0 1.6rem; padding: 0; }
.srclist li { border-bottom: 1px solid var(--line); }
.srclist a {
  display: flex; flex-wrap: wrap; gap: .6rem 1.4rem;
  align-items: baseline; justify-content: space-between;
  padding: 1rem 0; text-decoration: none; color: var(--text);
  transition: color .2s ease;
}
.srclist a:hover { color: var(--champagne); }
.srclist__label { max-width: 46ch; }
.srclist__meta {
  font-size: .74rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--bronze); white-space: nowrap;
}

/* The judge page floats its header over the hero exactly as the home page
   does, scrim included — one rule set, two pages. */
body.is-judge .hd {
  position: fixed; inset-inline: 0; top: 0;
  background: transparent; border-bottom-color: transparent; backdrop-filter: none;
  transition: background .3s ease, border-color .3s ease, backdrop-filter .3s ease;
}
body.is-judge .hd:not(.is-stuck)::before {
  content: ""; position: absolute; inset-inline: 0; top: 0; height: 210px;
  background: linear-gradient(
    to bottom,
    rgba(6, 4, 4, .78) 0%, rgba(6, 4, 4, .50) 40%,
    rgba(6, 4, 4, .20) 72%, rgba(6, 4, 4, 0) 100%
  );
  pointer-events: none; z-index: 0;
}
body.is-judge .hd:not(.is-stuck) .hd__links a,
body.is-judge .hd:not(.is-stuck) .drop > summary,
body.is-judge .hd:not(.is-stuck) .lang > summary {
  color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, .75);
}
body.is-judge .hd:not(.is-stuck) .hd__mark img {
  filter: drop-shadow(0 2px 10px rgba(0, 0, 0, .6));
}
/* Nearly opaque and barely blurred. A heavy blur smears the portrait as it
   scrolls under the bar, which is the one thing on this page that should stay
   sharp. */
body.is-judge .hd.is-stuck {
  background: rgba(11, 9, 8, .93);
  border-bottom-color: var(--line);
  backdrop-filter: blur(3px);
}

@media (max-width: 720px) {
  /* 100svh and nothing else. The 780px floor was taller than the visible area
     on a phone whose browser shows both bars — the hero ran past the fold and
     took the three figures with it, so the first screen ended mid-sentence.
     svh is by definition the height with that chrome expanded, so the stack
     always lands above the fold. */
  .jhero { height: auto; min-height: 100svh; }
  .jhero__in { width: calc(100% - 40px); margin-inline: auto; padding: 0 0 1.5rem; max-width: none; }
  /* The phone plate is its own 9:16 composition, so it needs no crop bias. */
  .jhero__bg img { object-position: 50% 50%; }
  /* The desktop scrim runs left-to-right, which on a phone darkens the side of
     the frame rather than the band the type sits in. Vertical instead: a light
     touch at the top for the floating header, clear glass across the portrait,
     solid from the eyebrow down — the eyebrow is bronze on a white sleeve, so
     it needs the dark to have arrived before it, not under it. */
  .jhero::after {
    background: linear-gradient(
      180deg,
      rgba(11, 9, 8, .62) 0%,
      rgba(11, 9, 8, .05) 16%,
      rgba(11, 9, 8, .05) 38%,
      rgba(11, 9, 8, .80) 60%,
      rgba(11, 9, 8, .98) 76%,
      rgba(11, 9, 8, 1) 100%
    );
  }
  .jhero__eyebrow { font-size: .66rem; letter-spacing: .26em; margin-bottom: .7rem; }
  .jhero__name {
    font-size: clamp(2.1rem, 10.5vw, 2.75rem);
    line-height: .92; max-width: 8ch; margin-bottom: .8rem;
  }
  .jhero__lede { font-size: .875rem; line-height: 1.5; max-width: 34ch; margin-bottom: 0; }
  /* Three across, not a wrapping flex row that stranded the third figure on a
     line of its own. The label is sized to the longest of them — "established
     Bell LLC" — so it sits on one line inside a third of a phone screen. */
  .jstats {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .6rem; margin-top: 1.1rem;
  }
  .jstats b { font-size: 1.55rem; }
  .jstats span { font-size: .62rem; letter-spacing: 0; line-height: 1.3; margin-top: .25rem; }
  /* On one column the CJK quote has no room for the desktop measure. */
  html[lang="zh-Hant"] .pull p,
  html[lang="ja"] .pull p,
  html[lang="ko"] .pull p { font-size: 1.6rem; max-width: none; }

  .idx { grid-template-columns: minmax(0, 1fr); }
  .jgallery { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  .jgallery li:nth-child(n) { grid-column: auto; }
  /* One column, so nothing has to line up across a row: the pictures keep their
     own ratio instead of cropping into a declared height. */
  .jgallery picture { height: auto; }
  .jgallery img { height: auto; aspect-ratio: 4 / 3; }
  .pull p { font-size: 2.25rem; }
  /* The rails are a desktop device: on one column the numeral sits above the
     title and the index rows stack. */
  .jsec__h { grid-template-columns: minmax(0, 1fr); gap: .6rem; margin-bottom: 2rem; }
  .jsec__n { font-size: 2.25rem; }
  .lens__row { grid-template-columns: minmax(0, 1fr); gap: .5rem; padding: 1.3rem 0; }
  .lens__b { font-size: .92rem; }
  body.is-judge .tl li { grid-template-columns: minmax(0, 1fr); gap: .35rem; padding: 1.2rem 0; }
  body.is-judge #standard .lede { max-width: none; }
  .pull { padding-block: 2.5rem; }
  .srclist a { justify-content: flex-start; }
}

/* ------------------------------------------------------------ facts bar */

/* ------------------------------------------------------------ event details

   Four facts as a magazine contents page. The previous pass numbered them
   01–04 and gave each its own rule, which put the numbering in competition with
   the figures themselves and made four items of equal weight read as a
   statement of account. Here the figure is the item: large, high-contrast
   serif, with the qualifying word set small underneath. Two columns, one
   hairline between them and one between the rows — no rule per item. */
.edetails {
  background:
    radial-gradient(circle at 50% 0%, rgba(119, 70, 32, .16), transparent 48%),
    #090604;
  border-block: 1px solid rgba(207, 158, 82, .18);
}
.edetails__in {
  width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto;
  padding: 1.6rem 0 2rem;
}
.edetails__t {
  margin: 0 0 18px;
  color: rgba(218, 177, 105, .68);
  font-size: 10px; font-weight: 500; letter-spacing: .28em; text-transform: uppercase;
}
.edetails__grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
}
.edetail {
  display: flex; flex-direction: column; justify-content: center;
  padding: 4px 20px; min-width: 0;
  border-left: 1px solid rgba(207, 158, 82, .18);
}
.edetail:first-child { border-left: 0; padding-left: 0; }
.edetail__v {
  font-family: var(--font-display);
  font-weight: 400; font-size: 48px; line-height: .9;
  color: #f4e9d8;
}
/* A word carries more strokes than a figure, so it sits a size down. */
.edetail__v--word { font-size: 35px; letter-spacing: .01em; }
.edetail__l {
  margin-top: 12px;
  color: rgba(218, 177, 105, .72);
  font-size: 10px; font-weight: 500; line-height: 1.45;
  letter-spacing: .18em; text-transform: uppercase;
}
/* Once, on arrival — nothing here loops. */
@media (prefers-reduced-motion: no-preference) {
  .edetails__t,
  .edetail { animation: hero-rise .7s cubic-bezier(.2, .7, .2, 1) backwards; }
  .edetail:nth-child(1) { animation-delay: .06s; }
  .edetail:nth-child(2) { animation-delay: .12s; }
  .edetail:nth-child(3) { animation-delay: .18s; }
  .edetail:nth-child(4) { animation-delay: .24s; }
}

/* On a phone the four facts become a 2x2 index: one vertical hairline between
   the columns, one horizontal between the rows, and nothing else.

   The sizes are cut to a height budget rather than chosen. Everything above the
   fold has to fit inside one small viewport — call it 660px: header 76, the
   16:9 band 219, the two buttons 150. That leaves about 215 for this block, and
   at 48px figures with 112px rows it needs 300. So the figure runs at 38px and
   the rows are sized by their content. */
@media (max-width: 720px) {
  .edetails__in { width: auto; padding: 14px 24px 18px; }
  .edetails__t { margin-bottom: 12px; }
  .edetails__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .edetail {
    min-height: 0;
    padding: 10px 0;
    border-left: 0;
  }
  .edetail__v { font-size: 38px; }
  .edetail__v--word { font-size: 28px; }
  .edetail__l { margin-top: 8px; }
  .edetail:nth-child(odd) { padding-right: 20px; }
  .edetail:nth-child(even) {
    padding-left: 20px;
    border-left: 1px solid rgba(207, 158, 82, .18);
  }
  .edetail:nth-child(n + 3) { border-top: 1px solid rgba(207, 158, 82, .18); }
}

/* ------------------------------------------------------------ sections */

.sec { padding-block: var(--step); }
.sec--dark { background: var(--paper-2); }
.sec--head { padding-bottom: 0; }
.sec--page { padding-top: 2.6rem; }

.measure {
  display: flex; align-items: flex-end; gap: 9px; height: 14px;
  margin-bottom: 1.6rem;
  border-bottom: 1px solid var(--line); width: 108px;
}
.measure i { display: block; width: 1px; background: var(--bronze); height: 6px; }
.measure i:nth-child(3) { height: 13px; }

.sec__h { margin-top: 0; }
/* The judge page is a feature, not a list page: its section titles carry the
   rhythm, so they run at display size rather than the 2.1rem the utility pages
   use. Scoped, so nothing else on the site moves. */
body.is-judge .sec__h {
  font-size: clamp(2.875rem, 4.2vw, 3.75rem);
  line-height: 1.02; letter-spacing: -.015em; margin-bottom: .45em;
}
.sec__lead { color: var(--text-dim); max-width: 60ch; }
/* A standfirst, not a second paragraph: display face, one step down from the
   heading, its own short measure. It is the line that decides whether the
   section gets read. */
body.is-judge .sec__lead {
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.6vw, 1.4rem);
  line-height: 1.5; color: var(--text); max-width: 40ch;
}
.lede { font-size: 1.08rem; color: var(--text); }
.empty { color: var(--text-dim); font-style: italic; }
.cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 1.4rem; }

.lnk {
  display: inline-block; font-size: 0.85rem; letter-spacing: 0.06em;
  border-bottom: 1px solid var(--bronze); text-decoration: none; padding-bottom: 2px;
}

.badge {
  display: inline-block; padding: 0.32rem 0.85rem;
  font-size: 0.76rem; letter-spacing: 0.08em;
  border: 1px solid var(--line); color: var(--champagne);
}
.badge--open { border-color: #6f8f6a; color: #b6d4ac; }
.badge--closing { border-color: #a8813c; color: var(--champagne); }
.badge--closed { border-color: #6d5b56; color: var(--text-dim); }

/* ------------------------------------------------------------ cards */

.cards { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.6rem; }
.cards--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); }

/* The judge page's own column set. auto-fit put four items into 3 + 1, which is
   the shape of a dashboard, and the boxes around them finished the impression.
   A fixed 2x2 with a rule over each column reads as a magazine section instead,
   with the same words inside. */
.cards--mag {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 3.6vw, 3rem) clamp(2.5rem, 5vw, 4rem);
}
.mcard { border: 0; border-top: 1px solid var(--line); padding: 1.5rem 0 .5rem; min-width: 0; }
.mcard h3 { margin: 0 0 .6rem; font-size: clamp(1.15rem, 1.6vw, 1.45rem); }
.mcard p { margin: 0; font-size: .97rem; color: var(--text-dim); }

.card { border: 1px solid var(--line); padding: 1.6rem; min-width: 0; }
.card h2, .card h3 { margin-top: 0; }
.card__link { text-decoration: none; }
.card__link:hover h2, .card__link:hover h3 { color: var(--champagne); }
.card__lead { color: var(--text-dim); font-size: 0.95rem; }
.card time { display: block; font-size: 0.8rem; color: var(--bronze); margin-bottom: 0.5rem; }

.facts { display: grid; gap: 0.5rem 1.4rem; margin: 1.2rem 0 0; }
.facts > div { display: grid; grid-template-columns: minmax(0, 10rem) minmax(0, 1fr); gap: 0.8rem; }
.facts dt { color: var(--text-dim); font-size: 0.85rem; }
.facts dd { margin: 0; font-size: 0.92rem; color: var(--text); }

.jgrid {
  list-style: none; margin: 0; padding: 0; display: grid; gap: 1.6rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr));
}
.jcard a { text-decoration: none; }
.jcard h2, .jcard h3 { font-size: 1.05rem; margin: 0.7rem 0 0.2rem; }
/* Two forms of one name, not two names: the Latin line reads first, the local
   one sits under it a size down. Set as a block rather than run together on one
   line, which wrapped mid-name in the narrow column. */
.jcard__n span {
  display: block;
  margin-top: .15rem;
  font-size: .92em;
  color: var(--text);
}
.jcard p { font-size: 0.85rem; color: var(--text-dim); margin: 0; }
.jcard__ph { display: block; aspect-ratio: 4 / 5; background: var(--paper-2); border: 1px solid var(--line); }
/* The card, not the file, decides the shape. Two judges whose posters were cut
   to different ratios left the grid stepped, with one name sitting lower than
   the other; the ratio is declared here so a future judge cannot do it again. */
.jcard img {
  display: block; width: 100%; aspect-ratio: 4 / 5; object-fit: cover;
  background: var(--paper-2);
}
.portrait { width: min(100%, 320px); margin-bottom: 1.6rem; }
.work { margin: 1.6rem 0; }

.tl { list-style: none; margin: 0; padding: 0; }
.tl li {
  display: grid; grid-template-columns: minmax(0, 12rem) minmax(0, 1fr);
  gap: 1rem; padding: 0.9rem 0; border-bottom: 1px solid var(--line);
}
.tl time { color: var(--bronze); font-size: 0.9rem; }

.nlist, .wlist, .plain { list-style: none; margin: 0; padding: 0; }
.nlist li, .wlist li { padding: 0.85rem 0; border-bottom: 1px solid var(--line); }
.nlist time { display: block; font-size: 0.8rem; color: var(--bronze); }
.plain li { padding: 1.4rem 0; border-bottom: 1px solid var(--line); }

.spon { list-style: none; display: flex; flex-wrap: wrap; gap: 1.6rem; padding: 0; margin: 0; }

.bullets { padding-left: 1.15rem; margin: 0 0 1.4rem; }
.bullets li { margin-bottom: 0.5rem; max-width: 70ch; }
.steps { padding-left: 1.3rem; }
.steps li { margin-bottom: 0.5rem; }

.qa { border-bottom: 1px solid var(--line); padding: 1rem 0; }
.qa summary {
  cursor: pointer; color: var(--porcelain); font-family: var(--font-display);
  font-size: 1.08rem; list-style: none;
}
.qa summary::-webkit-details-marker { display: none; }
.qa summary::before { content: "＋"; color: var(--bronze); margin-right: 0.6rem; }
.qa[open] summary::before { content: "－"; }
.qa p { margin: 0.8rem 0 0.2rem; color: var(--text-dim); }

.note {
  border-left: 2px solid var(--bronze); padding: 0.6rem 0 0.6rem 1.1rem;
  color: var(--text-dim); font-size: 0.92rem; margin: 1.4rem 0;
}
.upd { font-size: 0.82rem; color: var(--text-dim); }
.prose h2 { font-size: 1.35rem; }
.film { display: flex; flex-wrap: wrap; gap: 0.9rem; }

.crumb { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 1.4rem; }
.crumb ol { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0; padding: 0; }
.crumb li + li::before { content: "/"; color: var(--bronze); margin-right: 0.5rem; }
.crumb a { text-decoration: none; color: var(--text-dim); }

/* ------------------------------------------------------------ forms */

.form { max-width: 34rem; margin-top: 1.6rem; }
.field { display: grid; gap: 0.4rem; margin-bottom: 1.1rem; }
.field label { font-size: 0.85rem; color: var(--text-dim); }
.field input, .field select, .field textarea {
  background: var(--paper-2); border: 1px solid var(--line); color: var(--text);
  padding: 0.7rem 0.85rem; font: inherit; font-size: 0.95rem; width: 100%;
  border-radius: 0;
}
.field textarea { resize: vertical; }
.hp { position: absolute; left: -9999px; }

/* ------------------------------------------------------------ language hint */

/* A tag in the corner, not a bar across the page. Full width it cut the reading
   column in half at the bottom of every screen; the offer is the same, it just
   no longer interrupts. */
.langhint {
  position: fixed; inset-inline: auto 1rem; bottom: 1rem; z-index: 90;
  display: inline-flex; align-items: center; gap: .55rem;
  background: rgba(18, 13, 11, .92); backdrop-filter: blur(6px);
  border: 1px solid var(--line); border-radius: 999px;
  padding: .45rem .55rem .45rem 1rem; font-size: .85rem;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .45);
}
.langhint a { text-decoration: none; white-space: nowrap; }
.langhint button {
  background: none; border: 0; color: var(--text-dim);
  padding: .2rem .35rem; cursor: pointer; font: inherit; font-size: .8rem; line-height: 1;
}
.langhint button:hover { color: var(--porcelain); }

/* ------------------------------------------------------------ footer */

.ft { border-top: 1px solid var(--line); background: var(--paper-2); padding-top: 3.5rem; }
.ft__in {
  width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto;
  display: grid; gap: 2.4rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
}
.ft__brand img { width: 190px; }
.ft__tag { color: var(--text-dim); font-size: 0.9rem; margin-top: 1rem; }
.ft__org { font-size: 0.85rem; color: var(--text-dim); }
.ft__h { font-size: 0.85rem; letter-spacing: 0.1em; color: var(--bronze); font-family: var(--font-body); margin: 0 0 0.9rem; }
.ft__col ul { list-style: none; margin: 0; padding: 0; font-size: 0.9rem; }
.ft__col li { margin-bottom: 0.5rem; }
.ft__col a { color: var(--text-dim); text-decoration: none; }
.ft__col a:hover { color: var(--champagne); }
.ft__legal {
  width: min(100% - 2.5rem, var(--wrap)); margin: 3rem auto 0;
  padding: 1.2rem 0 2rem; border-top: 1px solid var(--line);
  font-size: 0.8rem; color: var(--text-dim);
}

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

@media (max-width: 1180px) {
  .hd__in { min-height: 96px; }
  .hd__links { gap: 1.1rem; font-size: 0.98rem; }
  .lang { font-size: 0.98rem; }
}

/* The rest of the judge page's phone rules. They sit here rather than with the
   hero block above because the sections and columns they override are declared
   further down the file, and at equal specificity the later rule wins. */
@media (max-width: 720px) {
  body.is-judge .sec { padding-block: 4rem; }
  body.is-judge .sec__h { font-size: clamp(2.25rem, 11vw, 2.75rem); }
  .cards--mag { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
}

@media (max-width: 900px) {
  .hd__burger {
    display: block; margin-left: auto; width: 44px; height: 44px;
    cursor: pointer; padding: 12px 9px;
  }
  .hd__burger span { display: block; height: 1px; background: var(--porcelain); margin: 5px 0; }
  .hd__in { min-height: 76px; }
  .hd__nav {
    position: fixed; inset: 76px 0 auto; z-index: 55;
    background: var(--paper); border-bottom: 1px solid var(--line);
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 1rem 1.25rem 1.6rem; margin-left: 0;
    display: none;
  }
  .hd__cb:checked ~ .hd__nav { display: flex; }
  /* The drawer draws its own opaque panel, so the scrim would only muddy it. */
  body.is-home .hd:not(.is-stuck)::before { height: 150px; }
  .hd__links { flex-direction: column; align-items: stretch; gap: 0; font-size: 1.0625rem; }
  .hd__links > li { border-bottom: 1px solid var(--line); }
  .hd__links a { display: block; padding: 0.85rem 0; }
  .drop > summary { padding: 0.85rem 0; justify-content: space-between; }
  .drop__list {
    position: static; border: 0; background: none; padding: 0 0 .6rem 1rem;
    min-width: 0;
  }
  .drop__list a { padding: 0.6rem 0; color: var(--text-dim); }
  .drop[open] > summary::after { content: none; }
  .hd__end { margin-top: 1.2rem; justify-content: space-between; }
  .lang__list { right: auto; left: 0; bottom: 100%; top: auto; }
  .facts-bar ul { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.1rem 1.4rem; }
  .facts > div { grid-template-columns: minmax(0, 1fr); gap: 0.1rem; }
  .tl li { grid-template-columns: minmax(0, 1fr); gap: 0.2rem; }
}

@media (max-width: 560px) {
  body { font-size: 16px; }
  .cards--2 { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
}

@media print {
  .hd, .ft, .hero__film, .hero__skip, .langhint { display: none !important; }
  body { background: #fff; color: #000; }
}

/* Winner record: the placement poster and the contestant poster side by side,
   each at its own ratio. */
.work-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .75rem; margin: 2rem 0; }
.work-pair .work { width: 100%; height: auto; margin: 0; }

/* On a wide screen the group opened for the current page (details[open]) must
   not sit over the page as a permanent panel: it shows while pointed at or
   focused, like any menu. In the phone drawer it stays expanded as before. */
@media (min-width: 901px) {
  .drop[open]:not(:hover):not(:focus-within) > .drop__list { display: none; }
}

/* 901–1100px: the full bar (mark, six links and the group, language, CTA)
   did not fit in Thai, Vietnamese or Myanmar and pushed the page 20–95px
   sideways. Tighten it here. */
.hd__nav { min-width: 0; }
@media (min-width: 901px) and (max-width: 1100px) {
  .hd__in { gap: 1rem; }
  .hd__mark img { width: 104px; }
  .hd__nav { gap: 1rem; }
  .hd__links { gap: .85rem; font-size: .9rem; }
  .hd__end { gap: .75rem; }
  .hd__end .btn { padding: .55rem 1rem; font-size: .85rem; }
  .lang { font-size: .9rem; }
}
/* Up to 1300px any language whose links still do not fit wraps them onto a
   second row (Thai, Vietnamese, Myanmar, and Japanese at the narrow end);
   where they fit, nothing changes. */
@media (min-width: 901px) and (max-width: 1300px) {
  .hd__links { flex-wrap: wrap; row-gap: .15rem; justify-content: flex-end; }
  .hd__end { flex: 0 0 auto; }
}

/* ------------------------------------------------------------ footer (v2)
   The client's footer design (2026-09-11): brand block · gold rule · four
   columns under gold headings with a short underline, over a faint gold wave;
   a bottom bar with the copyright left and language + Cookies right. */
.ft { position: relative; overflow: hidden; background: #0d0a08; border-top: 1px solid rgba(216, 180, 121, .35); padding-top: 3.2rem; }
/* The wave is 7:1; `cover` across the whole footer had to enlarge it until
   the streaks crossed the link columns. It sits along the bottom at its own
   proportions (width 100%, height auto) and fades out upwards, so it reads as
   a glow under the columns rather than a picture behind them. */
.ft::before {
  content: ""; position: absolute; inset: auto 0 0; height: min(38%, 210px);
  background: url("/assets/img/scoring/2026/10-footer-cta-background.webp") center bottom / 100% auto no-repeat;
  opacity: .5; pointer-events: none;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 55%);
  mask-image: linear-gradient(180deg, transparent, #000 55%);
}
.ft__in { position: relative; width: min(100% - 4rem, 1400px); display: grid; grid-template-columns: minmax(0, 1.6fr) auto repeat(4, minmax(0, 1fr)); gap: 0 clamp(1.4rem, 3vw, 3.4rem); align-items: start; padding-bottom: 3.2rem; }
.ft__in::after { content: ""; grid-column: 2; grid-row: 1; width: 1px; align-self: stretch; background: rgba(216, 180, 121, .45); }
.ft__brand { grid-column: 1; grid-row: 1; }
.ft__col { grid-row: 1; }
.ft__c1 { grid-column: 3; }
.ft__c2 { grid-column: 4; }
.ft__c3 { grid-column: 5; }
.ft__c4 { grid-column: 6; }
.ft__brand img { width: 240px; }
.ft__tag { margin-top: 1.1rem; font-size: 1rem; letter-spacing: .08em; color: var(--porcelain); }
@media (min-width: 1101px) { html:lang(zh-Hant) .ft__tag { white-space: nowrap; } }
.ft__tag::after { content: ""; display: block; width: 30px; height: 1px; margin-top: 1rem; background: var(--champagne); }
.ft__org { margin-top: .9rem; font-size: .9rem; color: var(--porcelain); }
.ft__org a { margin-left: .4rem; font-size: 1.12rem; color: var(--champagne); text-decoration: none; border-bottom: 1px solid currentColor; }
.ft__h { margin: 0 0 1.2rem; font: 600 1.35rem/1.2 var(--font-display); letter-spacing: .12em; color: var(--champagne); }
.ft__h::after { content: ""; display: block; width: 30px; height: 1px; margin-top: .9rem; background: var(--champagne); }
.ft__h a { color: inherit; text-decoration: none; }
.ft__col ul { font-size: 1.02rem; }
.ft__col li { margin-bottom: .75rem; }
.ft__col a { color: var(--porcelain); }
.ft__bar { position: relative; display: flex; align-items: center; justify-content: space-between; gap: 1rem; width: min(100% - 4rem, 1560px); margin-inline: auto; padding: 1.2rem 0 1.6rem; border-top: 1px solid rgba(216, 180, 121, .35); }
.ft__legal { width: auto; margin: 0; padding: 0; border: 0; font-size: .9rem; color: var(--porcelain); }
.ft__tools { display: flex; align-items: center; }
.ft__tools > * { padding: .2rem 2.2rem; border-left: 1px solid rgba(216, 180, 121, .45); }
.ft__tools a { font-size: .92rem; color: var(--porcelain); text-decoration: none; }
.ft__tools .lang { font-size: .92rem; font-weight: 400; }
.ft__tools .lang > summary { border: 0; padding: 0; background: none; }
.ft__tools .lang__globe { display: none; }
.ft .lang__list { top: auto; bottom: 100%; right: auto; left: 1.4rem; margin: 0 0 .5rem; }
@media (max-width: 1100px) {
  .ft__in { grid-template-columns: repeat(4, minmax(0, 1fr)); row-gap: 2rem; }
  .ft__in::after { display: none; }
  .ft__brand { grid-column: 1 / -1; }
  .ft__in > .ft__col { grid-row: 2; grid-column: auto; }
}
@media (max-width: 760px) {
  .ft { padding-top: 2.2rem; }
  .ft__in, .ft__bar { width: min(100% - 2.5rem, 1400px); }
  .ft__in { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ft__in > .ft__col { grid-row: auto; }
  .ft__brand img { width: 190px; }
  .ft__h { font-size: 1.1rem; margin-bottom: .8rem; }
  .ft__col ul { font-size: .92rem; }
  .ft__bar { flex-direction: column; align-items: flex-start; }
  .ft__tools > * { padding: .2rem 1.2rem; }
  .ft__tools > :first-child { padding-left: 0; border-left: 0; }
  .ft .lang__list { left: 0; }
}
