/* THE RADIAL -- Detroit, checked weekly.
   Built to ~/.claude/DESIGN_SYSTEM.md v1.0.

   TYPE. A news site's reflex is a serif display, and that reflex is the §12
   fingerprint, so it was tested against and rejected. Archivo is a grotesque
   with real width in it: it sets a headline that behaves like a broadsheet
   without borrowing a broadsheet's face. Source Serif 4 carries the reading,
   which is the job a serif is actually good at. Both open license.

   EXPRESSIVE CHANNEL (eleventh in the series): THE MEASURE. Line length is the
   variable, not size or weight. A deck runs to 26 characters, a standfirst to
   44, body to 66, a data note to 90 -- and the reader can tell what kind of
   reading each is before reading a word. It is how a broadsheet builds
   hierarchy while barely changing size. Previously used: width, weight
   extremes, the numeral, alignment, case, a closed size set, optical size,
   the oblique, type-as-image, the rounded terminal.

   INTERACTION SIGNATURE (eleventh): IT INKS. Accent floods UP from the
   baseline and the text flips to paper. Ink soaking into newsprint, not a
   highlight sliding across. Resolves on :active and :focus-visible so touch
   and keyboard both get it.

   TEXTURAL SIGNATURE (twelfth): MISREGISTRATION. The second plate lands a
   hair off, the way cheap offset printing does. It is decoration ONLY: the
   ghost is aria-hidden and sits behind live text that keeps its full
   contrast, so nothing legible depends on it.

   COLOR. One palette per section, from the four Detroit teams. Each color
   exists twice -- `hue` to sit on and print the ghost in, `ink` to write and
   act in -- because Tigers orange measures 3.53:1 on paper and cannot hold
   body text at any size. That is the Tulip Street lesson restated: a bright
   is a ground, not a text color. No team mark or logo appears anywhere.
*/

/* ---------- tokens ---------- */
:root{
  --paper:#F7F8FA;          /* cool, deliberately NOT the warm cream of §12 */
  --card:#FDFDFE;
  --ink:#14181D;            /* never #000 */
  --ink-2:#4A545E;
  /* 5.67:1 on bare paper, and still 4.61:1 at the strongest point of the page
     wash -- the tint sits OVER the paper, so the real background behind small
     text is darker than background-color reports. #5F6870 passed on paper and
     measured 4.34 under the Pistons and Wings tint. */
  --ink-3:#5B646C;
  --rule:#D3D8DE;
  --rule-2:#E4E8ED;

  /* default section palette: Lions. Overridden per page on <html data-team>. */
  --hue:#0076B6;
  --hue-ink:#02598A;
  --second:#B0B7BC;
  --wash:#E8F1F7;

  --s1:.25rem; --s2:.5rem;  --s3:.75rem; --s4:1rem;
  --s5:1.5rem; --s6:2rem;   --s7:3rem;   --s8:4.5rem; --s9:7rem;

  /* a closed size set, but the MEASURE is what varies -- see below */
  --t-mega:clamp(2.9rem,7.2vw,5.6rem);
  --t-lead:clamp(2rem,4.4vw,3.4rem);
  --t-1:clamp(1.6rem,3vw,2.3rem);
  --t-2:clamp(1.25rem,2vw,1.55rem);
  --t-3:1.08rem;
  --t-0:1.02rem;
  --t-s:.86rem;
  --t-xs:.76rem;

  --f-d:'Archivo','Archivo Narrow',system-ui,-apple-system,'Segoe UI',sans-serif;
  --f-b:'Source Serif 4',Georgia,'Times New Roman',serif;

  /* THE MEASURE -- the channel. Each is a different kind of reading. */
  --m-deck:26ch;
  --m-stand:44ch;
  --m-body:66ch;
  --m-note:90ch;

  --ease:cubic-bezier(.2,.7,.3,1);
  --fast:.15s; --land:.24s;
  --shadow:0 1px 2px rgba(20,24,29,.07), 0 6px 18px -6px rgba(20,24,29,.14);
}

html[data-team="lions"]  {--hue:#0076B6;--hue-ink:#02598A;--second:#B0B7BC;--wash:#E8F1F7}
html[data-team="tigers"] {--hue:#FA4616;--hue-ink:#B8380F;--second:#0C2340;--wash:#FCEDE7}
html[data-team="pistons"]{--hue:#C8102E;--hue-ink:#A80D26;--second:#1D42BA;--wash:#FAE9EC}
html[data-team="wings"]  {--hue:#CE1126;--hue-ink:#AB0E1F;--second:#6E7479;--wash:#FBE9EB}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--paper);color:var(--ink);
     font-family:var(--f-b);font-size:var(--t-0);line-height:1.62;
     font-synthesis-weight:none}
img{max-width:100%;height:auto}          /* §5.5: height:auto or the attr wins */
h1,h2,h3,h4,p,figure,ul,ol{margin:0}
ul,ol{padding:0;list-style:none}
a{color:var(--hue-ink);text-underline-offset:.18em;text-decoration-thickness:from-font}
a:hover{color:var(--ink)}
:focus-visible{outline:3px solid var(--hue-ink);outline-offset:3px;border-radius:2px}
::selection{background:var(--hue-ink);color:var(--paper)}
:root{accent-color:var(--hue-ink)}

.shell{width:min(1240px,100% - 2.5rem);margin-inline:auto}
.shell--wide{width:min(1480px,100% - 2.5rem)}
.skip{position:absolute;left:-9999px}
.skip:focus{left:var(--s4);top:var(--s4);z-index:99;background:var(--ink);color:var(--paper);
            padding:0 var(--s5);border-radius:3px;
            display:inline-flex;align-items:center;min-height:44px}

/* ---------- display type + THE MEASURE ---------- */
.d{font-family:var(--f-d);font-weight:800;line-height:.98;letter-spacing:-.022em;
   text-wrap:balance}
.d--mega{font-size:var(--t-mega)}
.d--lead{font-size:var(--t-lead)}
.d--1{font-size:var(--t-1);line-height:1.06}
.d--2{font-size:var(--t-2);line-height:1.14;letter-spacing:-.012em}
.d--3{font-family:var(--f-d);font-weight:700;font-size:var(--t-3);letter-spacing:-.005em}

.m-deck {max-width:var(--m-deck)}
.m-stand{max-width:var(--m-stand)}
.m-body {max-width:var(--m-body)}
.m-note {max-width:var(--m-note)}

.stand{font-size:clamp(1.1rem,1.7vw,1.32rem);line-height:1.5;color:var(--ink-2)}
.note{font-family:var(--f-d);font-size:var(--t-s);color:var(--ink-2);line-height:1.55}
.tiny{font-family:var(--f-d);font-size:var(--t-xs);color:var(--ink-3);line-height:1.5}

/* ---------- MISREGISTRATION: the second plate, a hair off ---------- */
/* The ghost was once content:attr(data-ghost) on ::before. It had to become a
   real element: Chrome exposes CSS generated content to the accessibility
   tree, so every headline was being announced TWICE -- "A city with the
   scaffolding still up A city with the scaffolding still up". A decorative
   layer that a screen reader reads aloud is not decorative. aria-hidden on a
   real span is the only version that is actually silent. */
.mis{position:relative;isolation:isolate}
.mis__g{
  position:absolute;inset:0;z-index:-1;
  color:var(--hue);opacity:.52;
  transform:translate(3px,2px);
  pointer-events:none;
  font:inherit;letter-spacing:inherit;line-height:inherit;
}
@media (max-width:600px){.mis__g{transform:translate(2px,1px)}}
@media (forced-colors:active){.mis__g{display:none}}

/* ---------- masthead ---------- */
.mast{background:var(--card);border-bottom:2px solid var(--ink)}
.mast__in{display:flex;align-items:flex-end;gap:var(--s5);padding-block:var(--s4) var(--s3);
          flex-wrap:wrap}
.brand{display:inline-flex;align-items:center;gap:var(--s3);
       text-decoration:none;color:var(--ink)}
.brand__mark{width:46px;height:46px;flex:none;border-radius:7px;display:block}
.brand__n{font-family:var(--f-d);font-weight:800;font-size:clamp(1.7rem,3.4vw,2.5rem);
          line-height:.9;letter-spacing:-.035em;display:block}
.brand__l{font-family:var(--f-d);font-size:var(--t-xs);color:var(--ink-2);
          letter-spacing:.1em;text-transform:uppercase;display:block;margin-top:.35em}
.mast__meta{margin-left:auto;text-align:right}

.nav{border-bottom:1px solid var(--rule);background:var(--card)}
.nav__in{display:flex;gap:0;overflow-x:auto;scrollbar-width:thin}
.nav a{font-family:var(--f-d);font-weight:600;font-size:var(--t-s);letter-spacing:.02em;
       text-decoration:none;color:var(--ink);white-space:nowrap;
       display:inline-flex;align-items:center;min-height:46px;padding:0 var(--s4);
       border-bottom:3px solid transparent}
.nav a[aria-current=page]{border-bottom-color:var(--hue);color:var(--hue-ink)}

/* ---------- submission form ---------- */
.subform{display:flex;flex-direction:column;gap:var(--s4);
         border:1px solid var(--rule);border-radius:3px;padding:var(--s5);
         background:var(--card)}
.subform .fld{gap:.4em}
.subform label{font-family:var(--f-d);font-weight:700;font-size:var(--t-xs);
               letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}
.subform input,.subform select,.subform textarea{
  font-family:var(--f-d);font-size:var(--t-0);min-height:44px;width:100%;
  padding:.55em .7em;border:1px solid var(--rule);border-radius:3px;
  background:var(--paper);color:var(--ink)}
.subform textarea{min-height:7rem;line-height:1.5;resize:vertical}
.subform input:focus,.subform select:focus,.subform textarea:focus{border-color:var(--hue)}
.subform input[aria-invalid="true"],.subform select[aria-invalid="true"]{
  border-color:var(--hue-ink);border-width:2px}
.subform .btn{width:100%}
.fld .err{font-family:var(--f-d);font-size:var(--t-xs);color:var(--hue-ink);font-weight:600}

.wxweek{display:grid;gap:var(--s3);grid-template-columns:repeat(auto-fit,minmax(8.5rem,1fr))}
.wxd{background:var(--card);border:1px solid var(--rule);border-radius:3px;
     padding:var(--s4);display:flex;flex-direction:column;gap:.25em;
     border-top:3px solid var(--rule)}
.wxd--wet{border-top-color:var(--hue)}
.wxd b{font-family:var(--f-d);font-size:var(--t-xs);letter-spacing:.1em;
       text-transform:uppercase;color:var(--ink-2)}
.wxd__t{font-family:var(--f-d);font-weight:800;font-size:1.7rem;line-height:1;color:var(--ink)}
.wxd__s{font-family:var(--f-d);font-size:var(--t-xs);color:var(--ink-2);line-height:1.35}
.wxd__p{font-family:var(--f-d);font-size:var(--t-xs);font-weight:700;color:var(--hue-ink)}
@media (forced-colors:active){.wxd--wet{border-top-color:Highlight}}

.wx{display:inline-flex;flex-wrap:wrap;align-items:baseline;gap:.5em;
     font-family:var(--f-d);font-size:var(--t-s);color:var(--ink-2);
     margin-top:1rem;padding:.55em .9em;border-radius:3px;
     border-left:3px solid var(--hue);background:var(--card)}
.wx b{color:var(--ink);font-weight:700;font-size:var(--t-xs);letter-spacing:.06em;
      text-transform:uppercase}
.wx .tiny{flex-basis:100%}
@media (forced-colors:active){.wx{border-left-color:CanvasText}}

/* ---------- filters ---------- */
.filters{display:flex;flex-wrap:wrap;gap:var(--s4) var(--s5);align-items:flex-end;
         padding:var(--s4);border:1px solid var(--rule);border-radius:3px;
         background:var(--card)}
.fld{display:flex;flex-direction:column;gap:.35em}
.fld label{font-family:var(--f-d);font-weight:700;font-size:var(--t-xs);
           letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}
.fld select{font-family:var(--f-d);font-size:var(--t-s);min-height:44px;
            padding:0 2em 0 .7em;border:1px solid var(--rule);border-radius:3px;
            background:var(--paper);color:var(--ink);min-width:11rem}
.fld select:focus{border-color:var(--hue)}
tbody tr[hidden]{display:none}
/* An author rule with a class beats the browser's own [hidden]{display:none},
   so any element given display: by a class ignores the attribute. .fld is
   display:flex, which meant the genre control was marked hidden and shown
   anyway -- the JS had been hiding it correctly since it was written. */
[hidden]{display:none !important}

/* ---------- search ----------
   The first version was a 9.5rem box with the placeholder "Search" and no icon,
   which read as a stray text field rather than as search. It is now labelled,
   carries a magnifier, and is wide enough to show what it is for. */
.find{margin-left:auto;display:flex;align-items:center;gap:var(--s3);
      padding-left:var(--s4)}
.find > label{font-family:var(--f-d);font-weight:700;font-size:var(--t-xs);
              letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2)}
.find__box{position:relative;display:flex;align-items:center}
.find__ico{position:absolute;left:.7em;width:17px;height:17px;color:var(--ink-3);
           pointer-events:none}
.find input{font-family:var(--f-d);font-size:var(--t-s);min-height:44px;
            width:15rem;padding:0 .8em 0 2.4em;
            border:1px solid var(--rule);border-radius:22px;
            background:var(--paper);color:var(--ink);
            transition:width var(--land) var(--ease),
                       border-color var(--land) var(--ease),
                       box-shadow var(--land) var(--ease)}
.find input::placeholder{color:var(--ink-3)}
.find input:focus{width:19rem;border-color:var(--hue);outline:none;
                  box-shadow:0 0 0 3px color-mix(in srgb, var(--hue) 22%, transparent)}
.find input:focus + .find__ico,.find__box:focus-within .find__ico{color:var(--hue-ink)}

.found{border-top:1px solid var(--rule);padding:var(--s3) 0 var(--s4)}
.found li{border-bottom:1px solid var(--rule-2)}
.found a{display:block;padding:.7em 0;text-decoration:none;color:var(--ink);min-height:44px}
.found a:hover,.found a:focus-visible{color:var(--hue-ink)}
.found b{font-family:var(--f-d);font-size:1rem;display:block}
.found span{font-family:var(--f-d);font-size:var(--t-xs);color:var(--ink-2)}
.found .none{padding:.8em 0;font-family:var(--f-d);font-size:var(--t-s);color:var(--ink-2)}

@media (max-width:900px){
  .find{width:100%;padding:0 0 var(--s3);margin-left:0}
  .find input,.find input:focus{width:100%}
}
@media (prefers-reduced-motion:reduce){.find input{transition:none}}
@supports not (background: color-mix(in srgb, red 10%, transparent)){
  .find input:focus{box-shadow:0 0 0 3px var(--wash)}
}

/* ---------- IT INKS ---------- */
.inks{
  background-image:linear-gradient(var(--hue-ink),var(--hue-ink));
  background-size:100% 0;background-position:0 100%;background-repeat:no-repeat;
  transition:background-size var(--land) var(--ease), color var(--land) var(--ease);
  padding:.06em .18em;margin-inline:-.18em;border-radius:1px;
  text-decoration:none;
}
.inks:hover,.inks:focus-visible,.inks:active{background-size:100% 100%;color:var(--paper)}
.nav a.inks{border-radius:0;margin-inline:0}
@media (prefers-reduced-motion:reduce){.inks{transition:none}}

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.5em;
     min-height:46px;padding:0 var(--s5);
     font-family:var(--f-d);font-weight:700;font-size:var(--t-s);letter-spacing:.02em;
     text-decoration:none;border:2px solid var(--hue-ink);border-radius:2px;cursor:pointer;
     background:var(--hue-ink);color:var(--paper);
     transition:transform var(--fast) var(--ease),box-shadow var(--fast) var(--ease)}
.btn:hover{color:var(--paper);box-shadow:var(--shadow);transform:translateY(-1px)}
.btn:active{transform:translateY(0)}
.btn--ghost{background:transparent;color:var(--hue-ink)}
.btn--ghost:hover{background:var(--hue-ink);color:var(--paper)}
@media (prefers-reduced-motion:reduce){.btn{transition:none}.btn:hover{transform:none}}

/* ---------- bands: the ground-change division channel ---------- */
.band{padding-block:var(--s8)}
.band--tight{padding-block:var(--s7)}
.band--wash{background:var(--wash)}
.band--card{background:var(--card)}
.band--dark{background:var(--ink);color:var(--paper)}
.band--dark .note,.band--dark .tiny{color:#B6BFC8}
.band--dark a{color:#EAF2F8}
.band--hue{background:var(--hue-ink);color:var(--paper)}
.band--hue .note,.band--hue .tiny{color:rgba(255,255,255,.86)}

.rule{height:2px;background:var(--ink);border:0;margin:0}
.rule--thin{height:1px;background:var(--rule)}

/* ---------- the lead ---------- */
.lead{display:grid;gap:var(--s6);align-items:end}
@media (min-width:900px){.lead{grid-template-columns:1.05fr .95fr;gap:var(--s7)}}
.lead__fig{margin:0}
.lead__fig img{width:100%;aspect-ratio:16/10;object-fit:cover;border-radius:2px;display:block}
.kicker{font-family:var(--f-d);font-weight:700;font-size:var(--t-xs);letter-spacing:.14em;
        text-transform:uppercase;color:var(--hue-ink);display:block;margin-bottom:var(--s3)}
/* a standalone link in the kicker is a nav target, not an in-sentence one,
   so it has to clear the minimum height on its own */
.kicker a{display:inline-flex;align-items:center;min-height:44px;color:inherit}

/* ---------- index strip ---------- */
.index{display:grid;gap:0;border-top:2px solid var(--ink)}
@media (min-width:760px){.index{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1080px){.index{grid-template-columns:repeat(3,1fr)}}
.index__i{border-bottom:1px solid var(--rule);padding:var(--s5) var(--s5) var(--s5) 0}
@media (min-width:760px){.index__i:nth-child(odd){padding-right:var(--s6)}}
.index__i a{text-decoration:none;color:var(--ink)}
.index__n{font-family:var(--f-d);font-weight:800;font-size:var(--t-2);display:block;
          letter-spacing:-.012em}

/* ---------- cards ---------- */
.cards{display:grid;gap:var(--s5)}
@media (min-width:720px){.cards{grid-template-columns:repeat(2,1fr)}}
@media (min-width:1080px){.cards--3{grid-template-columns:repeat(3,1fr)}}
.card{background:var(--card);border:1px solid var(--rule);border-radius:3px;
      padding:var(--s5);display:flex;flex-direction:column;gap:var(--s3)}
.card--flat{background:transparent;border:0;border-top:2px solid var(--ink);
            border-radius:0;padding:var(--s5) 0 0}
.card__img{width:100%;aspect-ratio:3/2;object-fit:cover;display:block;border-radius:2px}

.tag{display:inline-flex;align-items:center;align-self:flex-start;
     font-family:var(--f-d);font-weight:700;font-size:var(--t-xs);letter-spacing:.08em;
     text-transform:uppercase;padding:.3em .6em;border-radius:2px;
     /* the true team color, not the darkened one: measured on white, Lions
        4.95:1, Pistons 5.88:1, Wings 5.63:1 -- all clear 4.5. Tigers orange
        is 3.53:1 and is the single exception, so it flips to dark text
        (5.07:1) rather than giving up the actual orange. */
     background:var(--hue);color:var(--paper)}
html[data-team="tigers"] .tag{color:var(--ink)}
.tag--q{background:transparent;color:var(--ink-2);border:1px solid var(--rule);padding:.25em .5em}

/* ---------- feature rows: alternating, the alignment channel ---------- */
.rows{display:flex;flex-direction:column;gap:var(--s8)}
.row{display:grid;gap:var(--s5);align-items:center}
/* A grid item's default min-width:auto is its content's min-content width, so
   the wide details table inside .tw stretched the column past the viewport and
   took the whole page with it -- .tw's own overflow-x:auto never got the chance
   to scroll. min-width:0 lets the track shrink and the table scroll in place. */
.row > *{min-width:0}
@media (min-width:880px){
  .row{grid-template-columns:1fr 1fr;gap:var(--s7)}
  .row:nth-child(even) .row__fig{order:2}
}
.row__fig{margin:0}
.row__fig img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;border-radius:2px}
figcaption{margin-top:var(--s2)}

/* ---------- tables ---------- */
.tw{overflow-x:auto;border:1px solid var(--rule);border-radius:3px;background:var(--card)}
table{border-collapse:collapse;width:100%;min-width:460px;font-family:var(--f-d);
      font-size:var(--t-s)}
caption{text-align:left;padding:var(--s4) var(--s4) var(--s2);font-weight:700;
        font-family:var(--f-d)}
th,td{text-align:left;padding:.7em var(--s4);border-bottom:1px solid var(--rule-2)}
thead th{font-size:var(--t-xs);letter-spacing:.08em;text-transform:uppercase;
         color:var(--ink-2);border-bottom:2px solid var(--ink)}
tbody tr:last-child td{border-bottom:0}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
tr[data-det="1"]{background:var(--wash)}
tr[data-det="1"] td{font-weight:700}

.stale{color:var(--ink);background:#FFF2CC;border:1px solid #E3C86B;
        padding:.05em .4em;border-radius:2px;font-weight:600}
@media (forced-colors:active){.stale{border:1px solid CanvasText;background:Canvas}}

/* ---------- freshness stamp ---------- */
.fresh{font-family:var(--f-d);font-size:var(--t-xs);display:inline-flex;align-items:center;
       gap:.45em;padding:.25em .6em;border-radius:2px;border:1px solid var(--rule);
       background:var(--card);color:var(--ink-2)}
.fresh::before{content:"";width:.5em;height:.5em;border-radius:50%;background:var(--ink-3)}
.fresh[data-live="1"]::before{background:#1B7F3B}
@media (forced-colors:active){.fresh::before{background:CanvasText}}

/* ---------- article body ---------- */
/* On a section page the measure hangs left against figures and tables. On a
   post there is nothing beside it, so left-aligned prose just reads as 60% of
   an empty page -- it centers instead. */
.prose,.prose + .card--flat{margin-inline:auto}
.prose > * + *{margin-top:1.15em}
.prose p{font-size:1.09rem;line-height:1.72}
.prose h2{margin-top:2.4em}
.prose h3{margin-top:1.8em}
.prose blockquote{border-left:4px solid var(--hue);padding:.2em 0 .2em 1.1em;margin-left:0;
                  font-size:1.16rem;line-height:1.5}
.prose blockquote p{font-size:inherit}
.prose code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.92em;
            background:var(--wash);padding:.1em .3em;border-radius:2px}
.srclist li{padding:.5em 0;border-bottom:1px solid var(--rule-2)}
.srclist li:last-child{border-bottom:0}
/* A card title is the card's target. A one-line title is only 27px, so it
   carries its own floor -- multi-line ones already clear it and are unchanged. */
a.plain{color:inherit;text-decoration:none;display:block;min-height:44px}
a.plain:hover,.card:hover a.plain{color:var(--hue-ink)}

/* ---------- source line: every claim points somewhere ---------- */
.src{font-family:var(--f-d);font-size:var(--t-xs);color:var(--ink-3);
     margin-top:var(--s3);display:block}
.src a{color:var(--ink-3)}
.src a:hover{color:var(--hue-ink)}

/* ---------- figures (generated SVG) ---------- */
.fig{margin:0}
.fig svg{width:100%;height:auto;display:block}

.fixtures{display:flex;flex-direction:column;gap:.35em;margin-bottom:1.1rem;
          padding:.7em .9em;border-left:3px solid var(--hue);background:var(--card);
          border-radius:0 3px 3px 0}
.fx{font-family:var(--f-d);font-size:var(--t-s);color:var(--ink-2);line-height:1.45}
.fx b{color:var(--ink);font-weight:700;letter-spacing:.04em;text-transform:uppercase;
      font-size:var(--t-xs);margin-right:.4em}
@media (forced-colors:active){.fixtures{border-left-color:CanvasText}}

/* ---------- team blocks on the sports page ---------- */
.team{padding-block:var(--s7);border-top:2px solid var(--ink)}
.team .row{align-items:start}
.team__head{display:flex;flex-wrap:wrap;gap:var(--s3) var(--s5);align-items:baseline;
            margin-bottom:var(--s5)}
.swatch{display:inline-flex;gap:4px;align-items:center}
.swatch i{width:16px;height:16px;border-radius:2px;display:block;border:1px solid rgba(0,0,0,.18)}

.bullets{display:flex;flex-direction:column;gap:var(--s3)}
.bullets li{padding-left:1.1em;position:relative}
.bullets li::before{content:"";position:absolute;left:0;top:.62em;width:.5em;height:.5em;
                    background:var(--hue);border-radius:1px}

/* ---------- disclosure ---------- */
.disclaim{border:2px solid var(--ink);background:var(--card);padding:var(--s5);
          border-radius:3px}

/* ---------- footer ---------- */
.foot{background:var(--ink);color:var(--paper);padding-block:var(--s7);margin-top:var(--s8)}
.foot a{color:#DCE6EF}
/* .band--dark's overrides never applied here: the footer is .foot and does not
   carry that class, so its grays were left on a near-black ground at 2.31:1. */
.foot .note,.foot .tiny{color:#AEB8C2}
.foot .src,.foot .src a{color:#C3CCD6}
/* the maker's credit: present, legible, and quieter than the masthead */
.colophon{display:flex;flex-wrap:wrap;gap:var(--s5) var(--s6);align-items:flex-start}
.byid{display:inline-flex;align-items:center;gap:var(--s3);text-decoration:none;
      color:var(--paper);flex:none;min-height:44px}
.byid img{width:40px;height:40px;border-radius:6px;display:block;
          opacity:.82;transition:opacity var(--land) var(--ease)}
.byid:hover img,.byid:focus-visible img{opacity:1}
.byid strong{font-family:var(--f-d);font-size:.95rem;display:block;line-height:1.15}
.byid .tiny{display:block;color:#AEB8C2}
.colophon__legal{flex:1 1 30rem;max-width:62ch;margin:0}
@media (prefers-reduced-motion:reduce){.byid img{transition:none}}

.foot__g{display:grid;gap:var(--s5)}
@media (min-width:820px){.foot__g{grid-template-columns:repeat(3,1fr);gap:var(--s6)}}

/* ---------- forced colors: anything whose meaning lived in a background ---------- */
@media (forced-colors:active){
  .tag,.btn{border:1px solid CanvasText}
  .card,.tw,.disclaim{border:1px solid CanvasText}
  .nav a[aria-current=page]{border-bottom:3px solid Highlight}
  tr[data-det="1"] td{border-left:3px solid Highlight}
  .inks:hover,.inks:focus-visible{background:Highlight;color:HighlightText}
  .bullets li::before{background:CanvasText}
}

/* ============================================================================
   MOTION IDENTITY: IT REGISTERS
   ----------------------------------------------------------------------------
   The site's texture is misregistration -- a second color plate landing a
   hair off. So the hover is not a borrowed lift or glow: touching a thing
   PULLS IT INTO REGISTER. The offset plate slides home, the shadow tightens,
   and the element resolves. Leaving lets it drift back out.

   That gives every hover on the site one meaning instead of five, and the
   meaning comes from the press metaphor the design already committed to.
   A card, a photograph and a table row all do the same thing at different
   volumes.

   Everything resolves on :focus-visible and :active too, because touch has no
   hover and a keyboard user should see the same answer.
   ========================================================================= */

/* ---- cards: the plate slides home ---- */
/* Drawn with box-shadow, not a ::after. The first attempt used an offset
   pseudo-element at z-index:-1, but `isolation:isolate` on the card trapped it
   in the card's own stacking context, so it painted OVER the card background
   and tinted the whole thing orange. A hard-edged box-shadow is the same
   picture with none of the stacking problems -- and it leaves overflow:hidden
   free to clip the photograph. */
.card{position:relative;
      box-shadow:7px 7px 0 0 var(--hue);
      transition:transform var(--land) var(--ease),
                 border-color var(--land) var(--ease),
                 box-shadow var(--land) var(--ease)}
.card:hover,.card:focus-within{
  border-color:var(--hue);
  transform:translate(3px,3px);          /* the sheet moves onto the plate */
  box-shadow:0 0 0 0 var(--hue)}

/* flat cards have no box to offset, so the rule above them does the moving */
.card--flat{box-shadow:none;border-top-color:var(--rule);
            transition:border-top-color var(--land) var(--ease)}
.card--flat:hover,.card--flat:focus-within{transform:none;box-shadow:none;
                                           border-top-color:var(--hue)}

/* ---- photographs: they come into focus, not into a zoom ---- */
.card__img,.row__fig img,.lead__fig img{
  transition:transform .5s var(--ease), filter .5s var(--ease);
  will-change:transform}
.card,.row__fig,.lead__fig{overflow:hidden;border-radius:3px}
.card:hover .card__img,
.row__fig:hover img,.lead__fig:hover img{transform:scale(1.028)}

/* ---- index rows: the ink fills, and a mark walks in ---- */
.index__i{transition:background-color var(--land) var(--ease)}
.index__i a{display:block;position:relative;padding-right:1.6em}
.index__n{transition:color var(--land) var(--ease)}
.index__i a::after{
  content:"";position:absolute;right:.3em;top:.62em;
  width:.52em;height:.52em;border-right:2px solid var(--hue);
  border-bottom:2px solid var(--hue);transform:rotate(-45deg) translate(-4px,-4px);
  opacity:0;transition:opacity var(--land) var(--ease), transform var(--land) var(--ease);
}
.index__i:hover,.index__i:focus-within{background:var(--wash)}
.index__i:hover .index__n,.index__i:focus-within .index__n{color:var(--hue-ink)}
.index__i:hover a::after,.index__i:focus-within a::after{
  opacity:1;transform:rotate(-45deg) translate(0,0)}

/* ---- table rows ---- */
tbody tr{transition:background-color var(--fast) var(--ease)}
tbody tr:hover{background:var(--wash)}
/* A link in a table cell is a standalone target, not an in-sentence one, so it
   has to carry its own height rather than relying on the row's padding. */
.tw td a{display:inline-flex;align-items:center;min-height:44px}

/* ---- the masthead mark registers too ---- */
.brand__n{position:relative;display:inline-block}
.brand:hover .brand__n{color:var(--hue-ink)}
.brand__n{transition:color var(--land) var(--ease)}

/* ---- headline plate: settles into register as you arrive ---- */
.mis__g{transition:transform .55s var(--ease), opacity .55s var(--ease)}
.mis:hover .mis__g{transform:translate(0,0);opacity:.3}

/* ---- figures animate in once, on first sight ---- */
.fig [data-grow]{transform-origin:left center;
                 transition:transform .8s var(--ease)}
.fig:not(.seen) [data-grow]{transform:scaleX(0)}
.fig.seen [data-grow]{transform:scaleX(1)}
.fig [data-rise]{transform-origin:center bottom;transition:transform .7s var(--ease)}
.fig:not(.seen) [data-rise]{transform:scaleY(0)}
.fig.seen [data-rise]{transform:scaleY(1)}

/* ---- the whole motion identity switches off on request ---- */
@media (prefers-reduced-motion:reduce){
  .card,.card__img,.row__fig img,.lead__fig img,.index__i,
  .index__i a::after,.index__n,tbody tr,.brand__n,.mis__g,
  .fig [data-grow],.fig [data-rise]{transition:none !important}
  .card:hover,.card:focus-within{transform:none}
  .card:hover .card__img,.row__fig:hover img,.lead__fig:hover img{transform:none}
  .fig:not(.seen) [data-grow]{transform:scaleX(1)}
  .fig:not(.seen) [data-rise]{transform:scaleY(1)}
}
@media (forced-colors:active){
  .card{box-shadow:none}
  .card:hover,.card:focus-within{border-color:Highlight;transform:none}
  .index__i:hover,.index__i:focus-within{background:Highlight;color:HighlightText}
}

/* ============================================================================
   THE GROUND
   ----------------------------------------------------------------------------
   The flat paper read as plain, so it gets depth -- but NOT from a mesh, a dot
   field or a blueprint grid. Those are banned here on purpose: a faint grid is
   a cheap signal of "measured" on a page that has not earned it, and it is the
   single most over-used background on the web.

   Instead the ground behaves like the thing this site already is: something
   printed. Three layers, none of them a lattice.

     1  GRAIN. Newsprint tooth, from fractal noise. Fixed, static, ~3% -- felt
        rather than seen. It is what stops a flat #F7F8FA looking like unpainted
        drywall.
     2  INK BLEED. Each band's color soaks a little way in from its own top
        edge, the way ink wicks into uncoated stock. It follows --hue, so the
        ground changes character section by section and page by page.
     3  THE WET SHEET. On the hero only, one very slow drift of that tint.
        Nothing else on the site moves on its own.
   ========================================================================= */

body{
  position:relative;
  background-color:var(--paper);
}
/* 1 -- grain */
body::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  opacity:.032;
  background-image:url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'>\
<filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/>\
<feColorMatrix type='saturate' values='0'/></filter>\
<rect width='180' height='180' filter='url(%23n)'/></svg>");
  background-size:180px 180px;
}
/* keep every real layer above the grain */
.mast,.nav,main,.foot{position:relative;z-index:1}

/* 2 -- ONE ink bleed for the whole page, not one per section.
   It used to be a gradient on every .band, which meant two adjacent bands of
   the same color each restarted the same fade -- so instead of a wash you got
   a hard seam where one ended and the next began. A single gradient on the
   document runs the whole way down and never repeats. Sections still change
   character, but by changing GROUND (card, wash, dark), which is a deliberate
   edge rather than an accidental one. */
body{
  background-image:linear-gradient(to bottom,
    color-mix(in srgb, var(--hue) 12%, transparent) 0,
    color-mix(in srgb, var(--hue) 4%,  transparent) 46vh,
    transparent 108vh);
  background-repeat:no-repeat;
  background-attachment:scroll;
}
/* a band with its own ground is an intentional change of surface and keeps it */
.band{position:relative;isolation:isolate}

/* 3 -- the wet sheet: the hero tint drifts, once, slowly. Nothing else moves. */
/* overflow:clip, not hidden -- it stops the drift widening the page without
   creating a scroll container that would clip the cards' offset plates. */
.band--lede{overflow:clip}
.band--lede::after{
  content:"";position:absolute;inset:0;
  z-index:-1;pointer-events:none;
  background:radial-gradient(60% 70% at 22% 8%,
             color-mix(in srgb, var(--hue) 16%, transparent) 0%,
             transparent 62%);
  animation:wet 34s ease-in-out infinite alternate;
}
@keyframes wet{
  from{transform:translate3d(0,0,0) scale(1)}
  to  {transform:translate3d(4%,2%,0) scale(1.18)}
}

/* browsers without color-mix get a plain wash rather than nothing */
@supports not (background: color-mix(in srgb, red 10%, transparent)){
  body{background-image:linear-gradient(to bottom,var(--wash),transparent 100vh)}
  .band--lede::after{display:none}
}

/* 4 -- registration marks: real press furniture, four corners, not a lattice */
.reg{position:fixed;z-index:0;pointer-events:none;width:17px;height:17px;
     opacity:.3;color:var(--hue)}
.reg--tl{top:96px;left:14px}
.reg--tr{top:96px;right:14px}
.reg--bl{bottom:16px;left:14px}
.reg--br{bottom:16px;right:14px}
@media (max-width:900px){.reg{display:none}}

@media (prefers-reduced-motion:reduce){
  .band--lede::after{animation:none}
}
@media (forced-colors:active){
  body::before,.band::before,.band--lede::after,.reg{display:none}
}

/* ---------- when: the question people arrive with ---------- */
/* Real radios, styled. A segmented control built from buttons has to
   reimplement arrow-key navigation and checked state for the screen reader;
   a radio group already is one. The input is visually hidden but still the
   focus target, so :focus-visible is carried by the label next to it. */
.when{border:0;margin:0;padding:0;min-width:0}
.when legend{font-family:var(--f-d);font-weight:700;font-size:var(--t-xs);
             letter-spacing:.08em;text-transform:uppercase;color:var(--ink-2);
             padding:0;margin-bottom:.35em}
.when__g{display:inline-flex;flex-wrap:wrap;gap:2px;padding:2px;
         border:1px solid var(--rule);border-radius:3px;background:var(--paper)}
.when input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
            overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
.when label{display:inline-flex;align-items:center;min-height:44px;padding:0 var(--s3);
            font-family:var(--f-d);font-weight:600;font-size:var(--t-s);
            color:var(--ink-2);border-radius:2px;cursor:pointer;
            transition:background var(--fast) var(--ease),color var(--fast) var(--ease)}
.when label:hover{background:var(--wash);color:var(--ink)}
.when input:checked + label{background:var(--hue-ink);color:var(--paper)}
.when input:focus-visible + label{outline:3px solid var(--hue-ink);outline-offset:2px}
@media (prefers-reduced-motion:reduce){.when label{transition:none}}
@media (forced-colors:active){
  .when input:checked + label{background:Highlight;color:HighlightText;forced-color-adjust:none}
}

/* ---------- the row of things you can do with an event ---------- */
.acts{display:flex;flex-wrap:wrap;gap:var(--s3);margin-top:1.4rem}

/* ---------- getting there ---------- */
.gt{margin-top:var(--s5);padding:var(--s5);border:1px solid var(--rule);
    border-radius:3px;background:var(--card);box-shadow:var(--shadow)}
.gt h2{margin:0 0 var(--s4)}
.gt__l{list-style:none;margin:0;padding:0;display:grid;gap:var(--s3)}
.gt__i{display:grid;grid-template-columns:auto 1fr;gap:.15em var(--s3);
       align-items:baseline;padding-bottom:var(--s3);border-bottom:1px solid var(--rule)}
.gt__i:last-child{border-bottom:0;padding-bottom:0}
.gt__s{font-family:var(--f-d);font-size:1.05rem;grid-column:1}
.gt__y{font-family:var(--f-d);font-size:var(--t-xs);font-weight:600;
       letter-spacing:.06em;text-transform:uppercase;color:var(--hue-ink);
       grid-column:2;justify-self:start}
.gt__d{grid-column:1 / -1}

/* The front page asks a smaller weather question than the events page, so it
   gets a quieter answer: one line, seated against the ground rather than
   plated like the event-page forecast. */
.wx--home{margin:0 0 1.6rem;border-left-width:3px}

/* ---------- venues grouped by neighborhood ---------- */
/* A different system from the cards above it on purpose: those are a ranked
   shortlist, this is a directory, and a directory reads better as columns of
   plain lists than as another row of boxes. */
.hoods{column-width:15rem;column-gap:var(--s6)}
.hoodg{break-inside:avoid;margin:0 0 var(--s5)}
.hoodg h3{margin:0}
.hoodg > .tiny{margin:.15rem 0 .5rem}
.hoodg__l{list-style:none;margin:0;padding:0;border-top:1px solid var(--rule)}
.hoodg__l li{padding:.34rem 0;border-bottom:1px solid var(--rule)}
.hoodg__l .tiny{float:right;padding-left:.6em}

/* the neighborhood line on an event page */
.hood{font-family:var(--f-d);margin:.4rem 0 0}

/* ---------- event artwork, hotlinked from the ticket seller ---------- */
.art{margin:0 0 var(--s5)}
.art img{width:100%;height:auto;aspect-ratio:16/9;object-fit:cover;display:block;
         border-radius:3px;background:var(--wash);box-shadow:var(--shadow)}
.art figcaption{margin-top:.5rem}

/* ---------- a listing that is not simply going ahead ---------- */
.flag{font-family:var(--f-d);font-size:var(--t-s);line-height:1.5;
      margin:1rem 0 0;padding:.7rem .9rem;border-left:4px solid var(--hue-ink);
      background:var(--card);border-radius:0 3px 3px 0}
.flag strong{color:var(--hue-ink)}
@media (forced-colors:active){.flag{border-left-color:CanvasText}}

/* ---------- the venue's own photograph ---------- */
.vph{margin:var(--s5) 0 0}
/* No forced ratio. These are photographs of buildings, and a centre crop to
   3:2 took the marquee off the bottom of the Fox. The width and height
   attributes are real, so the space is reserved and nothing jumps. */
.vph img{width:100%;height:auto;display:block;max-height:78vh;object-fit:contain;
         border-radius:3px;background:var(--wash)}
.vph figcaption{margin-top:.5rem}

/* ---------- other ways the same night is sold ---------- */
.also{margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid var(--rule)}
.also h2{margin:0}
.also > .tiny{margin:.2rem 0 .7rem}
.also__l{list-style:none;margin:0;padding:0;font-family:var(--f-d);font-size:var(--t-s)}
.also__l li{padding:.4rem 0;border-bottom:1px solid var(--rule)}
.also__l li:last-child{border-bottom:0}

/* ---------- air quality ---------- */
/* EPA's six bands, in EPA's colors, as a 4px edge. Their yellow is #FFFF00 and
   their green #00E400 -- unreadable behind text, fine as an edge, and the
   reader already knows the scale from every weather app and highway sign. */
.aq{font-family:var(--f-d);font-size:var(--t-s);line-height:1.55;
    margin:1rem 0 0;padding:.7rem .9rem;border-left:4px solid var(--ink-3);
    background:var(--card);border-radius:0 3px 3px 0}
.aq b{color:var(--ink)}
.aq .say{display:block;margin-top:.2rem;color:var(--ink-2)}
.aq .tiny{display:block;margin-top:.3rem}
.aq--good{border-left-color:#00A44B}
.aq--moderate{border-left-color:#C9A400}
.aq--usg{border-left-color:#E36B00}
.aq--unhealthy{border-left-color:#D2222D}
.aq--very{border-left-color:#8F3F97}
.aq--hazard{border-left-color:#7E0023}
@media (forced-colors:active){.aq{border-left-color:CanvasText}}
