  /* ---- fonts, self-hosted -------------------------------------------------
     These were a stylesheet on fonts.googleapis.com, and Lighthouse measured it
     costing 898 ms of RENDER-BLOCKING time on a mobile connection -- not because
     the fonts are large, but because of the chain. A stylesheet in <head> blocks
     rendering; that one sat on a new origin needing its own DNS lookup and TLS
     handshake, and the CSS it returned named files on a SECOND new origin. Three
     serial round trips on two cold connections before any text could paint.

     The shared-cache argument for using Google's CDN is long dead: browsers
     partition the HTTP cache per site to close a privacy hole, so a font fetched
     on another site is never reused here. There is no upside left.

     Subset to Latin, Latin-1 Supplement and Latin Extended-A -- archer names
     carry Spanish and Filipino diacritics, so this cannot be trimmed to ASCII --
     plus the typographic characters this page prints. 80,844 bytes for four
     files against the 82,000 Google served, and now on our own origin with no
     stylesheet in front of them.

     The url() placeholders below are rewritten by each build: hashed asset URLs
     by web/build.mjs, data: URIs by ianseo/build_dashboard.py. Both REFUSE to
     emit a page with a placeholder left in it -- a missed substitution must fail
     loudly rather than render in Arial and look like a design choice. (And this
     comment deliberately does not spell the placeholder token out: the guard
     looks for it anywhere in the output, so writing it here made the build
     reject its own explanation. It did, on the first run.) */
  @font-face{font-family:"Hanken Grotesk";font-style:normal;font-weight:300 600;
    font-display:swap;src:url("/assets/hanken-grotesk-latin-wght-normal.c1ec3835.woff2") format("woff2")}
  @font-face{font-family:"Big Shoulders";font-style:normal;font-weight:500 700;
    font-display:swap;src:url("/assets/big-shoulders-latin-wght-normal.dad41855.woff2") format("woff2")}
  @font-face{font-family:"IBM Plex Mono";font-style:normal;font-weight:400;
    font-display:swap;src:url("/assets/ibm-plex-mono-latin-400-normal.08e39c9c.woff2") format("woff2")}
  @font-face{font-family:"IBM Plex Mono";font-style:normal;font-weight:500;
    font-display:swap;src:url("/assets/ibm-plex-mono-latin-500-normal.39453259.woff2") format("woff2")}

  :root{
    --bg:oklch(0.985 0.004 250); --panel:#ffffff; --panel-2:oklch(0.96 0.012 250);
    --ink:#15171d; --ink-2:#4a5160; --ink-3:#737d8f;
    --rule:#dde4ee; --rule-2:#c2cddd;
    --accent:#e0a008;
    --s1:#e4342b; --s2:#e0a008; --s3:#19b5e6; --s4:#2e9f21;
    --good:#2e9f21; --warn:#e4342b; --gold:#ffcf2e;
  }
  @media (prefers-color-scheme:dark){ :root:not([data-theme="light"]){
    --bg:oklch(0.18 0.05 263); --panel:oklch(0.23 0.055 263); --panel-2:oklch(0.26 0.052 263);
    --ink:#f4f5f7; --ink-2:#b4bdd0; --ink-3:#7d879b;
    --rule:oklch(0.31 0.045 263); --rule-2:oklch(0.38 0.04 263);
    --accent:#ffcf2e;
    --s1:#e03a30; --s2:#c08a08; --s3:#1b9ec9; --s4:#35a627;
    --good:#35a627; --warn:#e03a30; --gold:#ffcf2e;
  }}
  :root[data-theme="dark"]{
    --bg:oklch(0.18 0.05 263); --panel:oklch(0.23 0.055 263); --panel-2:oklch(0.26 0.052 263);
    --ink:#f4f5f7; --ink-2:#b4bdd0; --ink-3:#7d879b;
    --rule:oklch(0.31 0.045 263); --rule-2:oklch(0.38 0.04 263);
    --accent:#ffcf2e;
    --s1:#e03a30; --s2:#c08a08; --s3:#1b9ec9; --s4:#35a627;
    --good:#35a627; --warn:#e03a30; --gold:#ffcf2e;
  }
  /* An explicit choice by the viewer. Kept on its own attribute rather than
     reusing data-theme, because the host page stamps that one to carry the
     reader's claude.ai setting — overwriting it would mean "auto" could never
     hand control back. Absent attribute = follow the app and the OS. */
  :root[data-force="light"]{
    --bg:oklch(0.985 0.004 250); --panel:#ffffff; --panel-2:oklch(0.96 0.012 250);
    --ink:#15171d; --ink-2:#4a5160; --ink-3:#737d8f;
    --rule:#dde4ee; --rule-2:#c2cddd;
    --accent:#e0a008;
    --s1:#e4342b; --s2:#e0a008; --s3:#19b5e6; --s4:#2e9f21;
    --good:#2e9f21; --warn:#e4342b; --gold:#ffcf2e;
  }
  :root[data-force="dark"]{
    --bg:oklch(0.18 0.05 263); --panel:oklch(0.23 0.055 263); --panel-2:oklch(0.26 0.052 263);
    --ink:#f4f5f7; --ink-2:#b4bdd0; --ink-3:#7d879b;
    --rule:oklch(0.31 0.045 263); --rule-2:oklch(0.38 0.04 263);
    --accent:#ffcf2e;
    --s1:#e03a30; --s2:#c08a08; --s3:#1b9ec9; --s4:#35a627;
    --good:#35a627; --warn:#e03a30; --gold:#ffcf2e;
  }
  /* Big Shoulders is condensed display -- it carries headings and the brand
     wordmark, never body copy or table text. The site scopes it the same way. */
  h1,h2,.brand{font-family:"Big Shoulders","Arial Narrow",ui-sans-serif,system-ui,sans-serif;
    font-weight:600;letter-spacing:.01em}
  h1{font-size:30px}
  /* Published standings show the full field as IANSEO published it -- that is
     how you check we read an event correctly. But at the Asian Games a
     Philippine archer sits among 149 names, so the field can be narrowed on
     request. Off by default: the unfiltered table is the one that proves the
     parse. */
  .ph-only{display:inline-flex;align-items:center;gap:7px;margin:0 0 10px;
    font-size:12.5px;color:var(--ink-2);cursor:pointer;user-select:none}
  .ph-only input{accent-color:var(--accent);cursor:pointer}
  .ph-n{font-family:"IBM Plex Mono",monospace;font-size:11px;color:var(--ink-3)}
  *{box-sizing:border-box}
  body{margin:0;background:var(--bg)}
  /* Hidden until the first render finishes, then revealed once. Lighthouse
     measured a cumulative layout shift of 0.955 against a 0.1 threshold, and it
     was ONE shift: the browser laid out an empty skeleton, then the header grew
     when the competition chip and the scope note filled with text, pushing a
     13,801px <main> down by 250px. Almost the whole visible page moved.

     Reserving heights for those two elements would be guessing at text that
     changes with the reader's selection. Not laying out an empty page at all
     removes the shift instead of budgeting for it: an element with display:none
     has no layout box, so there is no first position for anything to move from.

     The reveal happens in a `finally`, so a render that throws still shows a
     partial page rather than a blank one. */
  .app{display:none}
  .app{background:var(--bg);color:var(--ink);
    font-family:"Hanken Grotesk",ui-sans-serif,system-ui,-apple-system,sans-serif;
    font-weight:300;font-size:15px;line-height:1.55}
  .mono{font-family:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace}

  /* ---- chrome ---- */
  header{position:sticky;top:0;z-index:20;background:var(--bg);
    border-bottom:1px solid var(--rule)}
  .bar{max-width:1320px;margin:0 auto;padding:16px 28px 0;
    display:flex;align-items:baseline;gap:20px;flex-wrap:wrap}
  .brand{font-size:15px;font-weight:500;letter-spacing:-.01em;white-space:nowrap}
  .brand span{color:var(--ink-3);font-weight:300}
  .chip{font-family:"IBM Plex Mono",monospace;font-size:10.5px;letter-spacing:.1em;
    text-transform:uppercase;border:1px solid var(--rule-2);color:var(--ink-3);
    padding:2px 7px;white-space:nowrap}
  .chip.warn{border-color:var(--warn);color:var(--warn)}
  .spacer{flex:1}
  nav{max-width:1320px;margin:0 auto;padding:0 28px;display:flex;gap:2px;
    overflow-x:auto;scrollbar-width:none}
  nav::-webkit-scrollbar{display:none}
  #inc-panel{position:fixed;z-index:70;width:330px;background:var(--bg);
    border:1px solid var(--rule-2);box-shadow:0 10px 34px rgba(0,0,0,.20);
    padding:16px 18px 14px;font-weight:300}
  #inc-panel h4{margin:0 0 4px;font-size:14px;font-weight:500}
  .inc-note{font-size:12px;color:var(--ink-3);margin:0 0 12px;line-height:1.5}
  .inc-h{font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.14em;
    text-transform:uppercase;color:var(--ink-3);display:block;margin:12px 0 6px}
  #inc-panel label{display:flex;gap:8px;align-items:flex-start;padding:4px 0;
    font-size:13.5px;cursor:pointer;line-height:1.45}
  #inc-panel label:hover{color:var(--accent)}
  #inc-panel input{margin:3px 0 0;accent-color:var(--accent);flex:none}
  #inc-panel label small{display:block;color:var(--ink-3);font-size:11.5px}
  .inc-presets{display:flex;flex-wrap:wrap;gap:6px}
  .inc-presets button{font-family:"IBM Plex Mono",monospace;font-size:9px;
    letter-spacing:.1em;text-transform:uppercase;padding:4px 7px;cursor:pointer;
    background:none;color:var(--ink-3);border:1px solid var(--rule-2)}
  .inc-presets button:hover{color:var(--ink);border-color:var(--ink-3)}
  .inc-presets button.on{color:var(--bg);background:var(--ink);border-color:var(--ink)}
  .inc-sum{margin-top:12px;padding-top:10px;border-top:1px solid var(--rule);
    font-size:12px;color:var(--ink-3);line-height:1.5}
  /* This is a control and the one beside it is not, so it cannot look the same.
     It did: both were .chip, and the only difference was cursor:pointer, which
     you can only discover with the mouse already on it. Mel could not find it,
     and said the thing worth saying -- if he cannot, nobody can. */
  .chip-btn{font-family:"IBM Plex Mono",monospace;background:var(--chip-btn-bg,transparent);
    cursor:pointer;letter-spacing:.1em;color:var(--ink-2);border-color:var(--ink-3)}
  .chip-btn::after{content:" \25BE";opacity:.8}
  .chip-btn:hover,.chip-btn[aria-expanded="true"]{color:var(--ink);border-color:var(--ink)}
  nav button{font-family:inherit;font-size:13.5px;font-weight:300;color:var(--ink-3);
    background:none;border:none;border-bottom:2px solid transparent;
    padding:14px 14px 11px;cursor:pointer;white-space:nowrap}
  nav button:hover{color:var(--ink)}
  nav button[aria-selected="true"]{color:var(--ink);border-bottom-color:var(--accent);font-weight:500}
  nav button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

  main{max-width:1320px;margin:0 auto;padding:34px 28px 100px}
  .panel{display:none}
  .panel.on{display:block}

  h1{font-size:26px;font-weight:400;letter-spacing:-.015em;margin:0 0 8px;text-wrap:balance}
  h2{font-size:17px;font-weight:500;margin:38px 0 4px;letter-spacing:-.005em}
  h2:first-child{margin-top:0}
  h3{font-size:14px;font-weight:500;margin:0 0 4px}
  p{margin:0 0 14px;color:var(--ink-2);max-width:74ch}
  p.tight{margin-bottom:8px}
  .note{font-size:13px;color:var(--ink-3);max-width:78ch}
  strong{color:var(--ink);font-weight:500}
  .lede{font-size:16px;color:var(--ink-2);max-width:76ch;margin:0 0 4px}

  /* ---- stat rail ---- */
  .rail{display:grid;grid-template-columns:repeat(auto-fit,minmax(132px,1fr));
    gap:1px;background:var(--rule);border:1px solid var(--rule);margin:22px 0 6px}
  .rail>div{background:var(--bg);padding:15px 16px}
  .rail .v{font-family:"IBM Plex Mono",monospace;font-size:26px;line-height:1;
    font-variant-numeric:tabular-nums}
  .rail .k{font-family:"IBM Plex Mono",monospace;font-size:9.5px;letter-spacing:.14em;
    text-transform:uppercase;color:var(--ink-3);margin-top:8px}

  /* ---- tables ---- */
  .scroll{overflow-x:auto}
  table{border-collapse:collapse;width:100%;font-size:14px;margin-top:14px;
    color:inherit;font:inherit;font-size:14px}
  th,td{text-align:left;padding:9px 14px 9px 0;border-bottom:1px solid var(--rule);
    vertical-align:top}
  th{font-family:"IBM Plex Mono",monospace;font-size:9.5px;letter-spacing:.13em;
    text-transform:uppercase;color:var(--ink-3);font-weight:400;
    border-bottom:1px solid var(--rule-2);white-space:nowrap}
  td.n,th.n{text-align:right;font-variant-numeric:tabular-nums;padding-right:20px}
  tbody tr:hover{background:var(--panel)}
  .nowrap{white-space:nowrap}
  .medal{font-weight:500}
  .win{color:var(--good);font-weight:500}
  .warnv{color:var(--warn);font-weight:500}
  .loss{color:var(--ink-3)}
  .dim{color:var(--ink-3)}
  a{color:inherit;text-decoration:none;border-bottom:1px solid var(--rule-2);
    padding-bottom:1px}
  a:hover{color:var(--accent);border-bottom-color:var(--accent)}
  .prov{font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.1em;
    color:var(--ink-3);border:1px solid var(--rule-2);padding:1px 4px;margin-left:6px}

  /* ---- controls ---- */
  .controls{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end;margin:18px 0 2px}
  .ctl{display:flex;flex-direction:column;gap:5px}
  .ctl label{font-family:"IBM Plex Mono",monospace;font-size:9.5px;letter-spacing:.14em;
    text-transform:uppercase;color:var(--ink-3)}
  select,input[type=search]{font-family:inherit;font-size:14px;font-weight:300;color:var(--ink);
    background:var(--bg);border:1px solid var(--rule-2);border-radius:0;padding:9px 12px}
  select{padding-right:28px;appearance:none;min-width:210px;max-width:min(430px,86vw);
    background-image:linear-gradient(45deg,transparent 50%,var(--ink-3) 50%),
      linear-gradient(135deg,var(--ink-3) 50%,transparent 50%);
    background-position:calc(100% - 14px) 50%,calc(100% - 9px) 50%;
    background-size:5px 5px,5px 5px;background-repeat:no-repeat}
  select:focus,input:focus{outline:2px solid var(--accent);outline-offset:1px}
  input[type=search]{width:100%;font-size:15px;padding:11px 13px}

  /* ---- archer picker ---- */
  .searchbox{max-width:460px}
  .matches{border:1px solid var(--rule);border-top:none;max-height:270px;overflow-y:auto;
    max-width:460px}
  .matches button{display:block;width:100%;text-align:left;font-family:inherit;font-size:14px;
    font-weight:300;color:var(--ink);background:var(--bg);border:none;
    border-bottom:1px solid var(--rule);padding:10px 13px;cursor:pointer}
  .matches button:last-child{border-bottom:none}
  .matches button:hover,.matches button:focus{background:var(--panel);outline:none}
  .matches .sub{color:var(--ink-3);font-size:12px;margin-left:8px}

  /* ---- profile ---- */
  .who{margin-top:26px;padding-top:20px;border-top:1px solid var(--rule-2)}
  .who h1{margin-bottom:4px}
  .who .meta{font-size:13.5px;color:var(--ink-2)}
  .cols{display:grid;grid-template-columns:1fr 1fr;gap:34px;margin-top:22px}
  @media (max-width:900px){.cols{grid-template-columns:1fr;gap:26px}}
  .card{border:1px solid var(--rule);padding:18px 20px;background:var(--panel)}
  .card h3{margin-bottom:10px}
  .kv{display:flex;justify-content:space-between;gap:16px;padding:5px 0;font-size:13.5px}
  .kv+.kv{border-top:1px solid var(--rule)}
  .kv .k{color:var(--ink-3)}
  .kv .v{font-family:"IBM Plex Mono",monospace;font-variant-numeric:tabular-nums}

  /* ---- charts ---- */
  .chart{margin:14px 0 0}
  .chart svg{width:100%;height:auto;display:block;overflow:visible}
  .ax{stroke:var(--rule);stroke-width:1}
  .grid{stroke:var(--rule);stroke-width:1;stroke-dasharray:2 3}
  .atick{fill:var(--ink-3);font-family:"IBM Plex Mono",monospace;font-size:9.5px;
    letter-spacing:.06em}
  .aname{fill:var(--ink-3);font-family:"IBM Plex Mono",monospace;font-size:9px;
    letter-spacing:.14em;text-transform:uppercase}
  .ln{fill:none;stroke-width:1.75;stroke-linejoin:round;stroke-linecap:round}
  .dot{stroke:var(--bg);stroke-width:1.5}
  .c0{stroke:var(--ink-3)} .f0{fill:var(--ink-3)}
  .c1{stroke:var(--s1)} .c2{stroke:var(--s2)} .c3{stroke:var(--s3)} .c4{stroke:var(--s4)}
  .f1{fill:var(--s1)} .f2{fill:var(--s2)} .f3{fill:var(--s3)} .f4{fill:var(--s4)}
  .refln{stroke:var(--ink-3);stroke-width:1;stroke-dasharray:4 3}
  .reflab{fill:var(--ink-3);font-family:"IBM Plex Mono",monospace;font-size:9px}
  .colw{fill:var(--good)} .coll{fill:var(--ink-3)}
  .chart .empty{padding:12px 0}

  /* ---- bars ---- */
  .bars{margin-top:12px}
  .brow{display:grid;grid-template-columns:190px 1fr;align-items:center;gap:16px;padding:8px 0}
  .brow+.brow{border-top:1px solid var(--rule)}
  .blab{font-family:"IBM Plex Mono",monospace;font-size:12px;color:var(--ink-2)}
  .blines{display:flex;flex-direction:column;gap:3px;min-width:0}
  .bline{display:grid;grid-template-columns:1fr 46px;align-items:center;gap:12px}
  .btrack{height:10px;background:var(--panel-2)}
  .bfill{height:10px;background:var(--s1);display:block}
  .bfill.b2{background:var(--s2)}
  .bfill.b3{background:var(--s3)}
  .bval{font-family:"IBM Plex Mono",monospace;font-size:12.5px;text-align:right;
    font-variant-numeric:tabular-nums}
  .legend{display:flex;gap:18px;flex-wrap:wrap;margin:12px 0 0;font-size:12.5px;color:var(--ink-2)}
  .legend i{display:inline-block;width:9px;height:9px;margin-right:6px;vertical-align:-1px}

  .callout{border:1px solid var(--rule);border-left:3px solid var(--accent);
    background:var(--panel);padding:14px 16px;font-size:13.5px;color:var(--ink-2);margin:16px 0}
  .callout.warn{border-left-color:var(--warn)}
  /* A STILL-LOADING notice is transient, so it must not take space in the flow:
     inserting it and removing it again moved the whole section. Measured
     2026-10-07 on the Olympic round tab -- removing a 51px notice above the rail
     dragged the rail up 75px, and that one move was 0.07314 of a 0.0768 CLS,
     95% of the page's layout shift. `position:fixed` has no layout box in the
     flow at all, so it can appear and vanish without displacing a pixel.
     A COULD-NOT-LOAD notice is NOT transient -- it is a standing fact about the
     page -- so it stays a `.callout` in the flow where a reader will find it
     next to the section it concerns. */
  #load-toast{position:fixed;left:50%;transform:translateX(-50%);bottom:18px;
    z-index:75;max-width:min(520px,calc(100vw - 32px));background:var(--panel);
    border:1px solid var(--rule);border-left:3px solid var(--accent);
    padding:11px 15px;font-size:12.5px;color:var(--ink-2);
    box-shadow:0 6px 24px rgba(0,0,0,.18)}
  #load-toast b{color:var(--ink);font-weight:500}
  #load-toast[hidden]{display:none}
  .callout b{color:var(--ink);font-weight:500}
  .gaps li{list-style:none;border-top:1px solid var(--rule);padding:14px 0}
  .gaps{padding:0;margin:14px 0 0}
  .gaps li:last-child{border-bottom:1px solid var(--rule)}
  .gaps p{font-size:13.5px;margin:0}
  /* The three verdicts a reader has to tell apart at a glance: a gap that
     changes the answer, a gap that only needs context, and one we have dealt
     with. Color alone is never the signal -- the word is always printed. */
  .gaps .tag{font-family:"IBM Plex Mono",monospace;font-size:9px;letter-spacing:.1em;
    text-transform:uppercase;margin:0 0 6px;color:var(--ink-3)}
  .gaps .tag.lim{color:var(--warn)}
  .gaps .tag.ok{color:var(--good)}
  .gaps li h3{font-size:14.5px;font-weight:500;margin:0 0 4px}
  .gaps p.note{color:var(--ink-3);margin-top:6px}
  h3.sub{font-family:"IBM Plex Mono",monospace;font-size:10px;letter-spacing:.14em;
    text-transform:uppercase;color:var(--ink-3);font-weight:400;margin:16px 0 0}
  abbr.hint{text-decoration:none;border-bottom:1px dotted var(--ink-3);cursor:help;
    outline:none}
  abbr.hint:hover,abbr.hint:focus,abbr.hint.open{color:var(--accent);
    border-bottom-color:var(--accent)}
  /* Appended to <body>, outside .app — so it has to be told the typeface, or
     it renders in the browser's default serif. */
  #tip{font-family:"Hanken Grotesk",ui-sans-serif,system-ui,-apple-system,sans-serif;
    position:fixed;z-index:60;max-width:330px;background:var(--bg);
    border:1px solid var(--rule-2);box-shadow:0 6px 24px rgba(0,0,0,.18);
    padding:10px 12px;font-size:13px;line-height:1.5;color:var(--ink-2);
    pointer-events:none;opacity:0;transition:opacity .09s;font-weight:300}
  #tip.on{opacity:1}
  #tip b{color:var(--ink);font-weight:500;display:block;margin-bottom:3px;
    font-family:"IBM Plex Mono",monospace;font-size:9.5px;letter-spacing:.13em;
    text-transform:uppercase}
  .vs{color:var(--ink-3);font-weight:300}
  .empty{color:var(--ink-3);font-size:14px;padding:22px 0}
  footer{border-top:1px solid var(--rule);margin-top:60px;padding-top:18px;
    font-family:"IBM Plex Mono",monospace;font-size:11px;letter-spacing:.05em;color:var(--ink-3)}
  /* The mark inherits currentColor, so it reads in both themes without a second
     asset and without a hard-coded hex that would go wrong in one of them. */
  .by{display:flex;align-items:center;gap:8px;margin-top:14px;color:var(--ink-3)}
  .by .lbl{font-family:"IBM Plex Mono",monospace;font-size:10px;letter-spacing:.14em;
    text-transform:uppercase}
  .by svg.dx10{height:14px;width:auto;display:block;opacity:.85}
th.sortable{cursor:pointer;user-select:none}
th.sortable:hover{background:var(--hov,rgba(127,127,127,.10))}
th.sortable:focus-visible{outline:2px solid currentColor;outline-offset:-2px}
.sarrow{font-size:.75em;margin-left:.35em;opacity:.85}
.sarrow.dim{opacity:.25}
