    @font-face {
      font-family: 'W95FA';
      src: url('fonts/w95fa.woff2') format('woff2'),
           url('fonts/w95fa.woff') format('woff'),
           url('fonts/W95F.otf') format('opentype');
      font-weight: normal; font-style: normal; font-display: swap;
    }

    * { margin: 0; padding: 0; box-sizing: border-box; }

    :root {
      --backdrop:    #3a4a2a;
      --field:       #445634;
      --chrome-dark: #2f3a1f;
      --cream-warm:  #6c8146;
      --ink:         #f5e6d0;
      --ink-soft:    #d4c4a0;
      --ink-faint:   #a8b088;
      --sage-tint:   #c8d8a0;
    }

    html, body { height: 100%; overflow: hidden; }

    body {
      background: var(--backdrop);
      color: var(--ink);
      font-family: 'W95FA', 'Segoe UI', Tahoma, sans-serif;
      font-size: 16px;
      position: relative;
      -webkit-tap-highlight-color: transparent;
      user-select: none;
      -webkit-user-select: none;
    }

    /* ====== HUD - floats straight on the grass, no strip ======
       Everything lives in one column on the left. One typeface, one colour,
       one weight; the only hierarchy is size and how faded a thing is.     */
    .hud {
      position: absolute;
      top: 16px;
      left: 20px;
      z-index: 30;
      pointer-events: none;
      text-shadow: 0 1px 3px rgba(10, 16, 6, 0.9), 0 0 12px rgba(10, 16, 6, 0.5);
    }
    .hud button, .hud a { pointer-events: auto; }

    /* Deliberately across the field from everything else. A way out that sits
       under your hand becomes the first thing you reach for; one you have to
       cross the screen for stays a last resort, which is the whole point of it. */
    .aside {
      position: absolute;
      top: 16px;
      right: 20px;
      z-index: 30;
      text-shadow: 0 1px 3px rgba(10, 16, 6, 0.9), 0 0 12px rgba(10, 16, 6, 0.5);
    }

    h1.lead { font-size: 68px; }
    h1 {
      font-size: 34px;
      font-weight: normal;
      letter-spacing: 0.5px;
      color: var(--sage-tint);
      line-height: 1;
    }

    /* counters and tools share a line of their own, beneath the title */
    .topline {
      display: flex;
      align-items: center;
      gap: 22px;
      flex-wrap: wrap;
      margin-top: 10px;
    }

    /* the counters: numbers only */
    .counts {
      display: flex;
      align-items: baseline;
      gap: 14px;
      color: var(--sage-tint);
      opacity: 0.62;
    }
    .counts .n { font-size: 26px; line-height: 1; }
    .counts .n.small { font-size: 20px; opacity: 0.7; }
    /* the clock is the only reading left, so a hushed row goes entirely rather
       than sitting there empty and pushing the tools along by one gap */
    .counts.hushed { display: none; }

    /* the tools, in the same green as the luck list but quieter */
    .tools {
      display: flex;
      align-items: center;
      gap: 16px;
    }

    .hud button, .hud a, .aside button {
      font-family: inherit;
      text-decoration: none;
      font-size: 15px;
      background: none;
      border: 0;
      padding: 0;
      color: var(--ink-soft);
      cursor: pointer;
      text-shadow: inherit;
      opacity: 0.42;
      transition: opacity 160ms, color 160ms, transform 160ms;
      line-height: 1;
    }
    .hud button:hover, .hud a:hover,
    .aside button:hover { opacity: 0.95; color: var(--sage-tint); }
    /* A link in the tools row is still a tool. Left to itself the browser
       paints it blue, then visited-purple, and either one is close to
       unreadable against the grass - so every link state is nailed to the same
       faded green the buttons beside it use. :link and :visited come first so
       the hover below still gets the last word. */
    .hud a:link, .hud a:visited { color: var(--ink-soft); text-decoration: none; }
    .hud a:hover, .hud a:focus, .hud a:active { color: var(--sage-tint); }

    /* The daily is the one thing in this row worth leading with, so it does not
       wear the faded green the tools beside it do: full strength, a touch more
       letter, and a slow breath of light. Nothing moves and nothing reflows -
       only the glow behind the word rises and falls, which reads as alive
       rather than as an advert. */
    .hud a#daily-link:link,
    .hud a#daily-link:visited {
      color: var(--sage-tint);
      opacity: 1;
      letter-spacing: 0.7px;
      animation: daily-breath 3.6s ease-in-out infinite;
    }
    .hud a#daily-link:hover,
    .hud a#daily-link:focus,
    .hud a#daily-link:active { color: #eaf6c8; }

    @keyframes daily-breath {
      0%, 100% { text-shadow: 0 1px 3px rgba(10, 16, 6, 0.9), 0 0 5px rgba(200, 216, 160, 0.2); }
      50%      { text-shadow: 0 1px 3px rgba(10, 16, 6, 0.9), 0 0 15px rgba(200, 216, 160, 0.75); }
    }
    /* a glow that pulses forever is exactly what motion sensitivity means, so
       anyone who has asked for less of it gets the bright word and none of the
       breathing */
    @media (prefers-reduced-motion: reduce) {
      .hud a#daily-link:link,
      .hud a#daily-link:visited { animation: none; }
    }
    .hud button.off { opacity: 0.24; }

    #again {
      display: flex;
      align-items: center;
      width: 18px;
      height: 18px;
    }
    #again svg { width: 100%; height: 100%; display: block; }
    #again svg path { fill: none; stroke: currentColor; stroke-width: 2.1; stroke-linecap: round; stroke-linejoin: round; }
    #again svg polygon { fill: currentColor; }
    #again:hover { transform: rotate(-40deg); }

    .ask {
      margin-top: 17px;
      color: var(--ink-soft);
      font-size: 15px;
      opacity: 0.62;
    }

    .luck {
      margin-top: 7px;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
      gap: 3px;
    }

    .luck button {
      font-size: 16px;
      opacity: 0.5;
      transform-origin: left center;
    }
    .luck button:hover { opacity: 0.95; transform: translateX(3px); }
    .luck button.on { opacity: 1; color: var(--sage-tint); }
    .luck button.on::before { content: '› '; }
    .luck button:not(.on)::before { content: '  '; }

    /* ====== THE MAGNIFIER ====== */
    html, body, #field, .clover, #zone { cursor: none; }
    .hud button, .hud a, .aside button, #worm-icon, .panel button { cursor: pointer; }

    #lens {
      position: fixed;
      left: 0; top: 0;
      width: 32px; height: 32px;              /* the 16px drawing at 2x, so it stays crisp */
      z-index: 600;
      pointer-events: none;
      background: url('images/clover/lens.png') 0 0 / 32px 32px no-repeat;
      image-rendering: pixelated;
      opacity: 0;
      transition: opacity 180ms ease;
      filter: drop-shadow(0 1px 2px rgba(10, 16, 6, 0.65));
      will-change: transform;
    }
    #lens.on { opacity: 1; }

    /* ====== ZONE CARD ======

       Letters drift up out of a blur, one after the next, then leave the same
       way. Nothing blocks the field and nothing waits on it.                */
    /* down in the corner, like a caption on the place you have arrived */
    #zone {
      position: absolute;
      left: 20px;
      bottom: 24px;
      z-index: 25;
      text-align: left;
      pointer-events: none;
    }

    #zone span {
      display: inline-block;
      font-size: 52px;
      letter-spacing: 5px;
      color: #a9c47e;
      text-shadow:
        0 2px 10px rgba(10, 16, 6, 0.75),
        0 0 46px rgba(24, 38, 14, 0.7);
      opacity: 0;
      transform: translateY(14px) scale(1.04);
      filter: blur(7px);
      transition:
        opacity 1100ms cubic-bezier(.22,.68,.24,1),
        transform 1400ms cubic-bezier(.22,.68,.24,1),
        filter 1100ms cubic-bezier(.22,.68,.24,1);
      transition-delay: calc(var(--i) * 55ms);
    }

    #zone.show span {
      opacity: 0.88;
      transform: none;
      filter: blur(0);
    }

    #zone.out span {
      opacity: 0;
      transform: translateY(-10px) scale(1.02);
      filter: blur(5px);
      transition-duration: 1300ms, 1500ms, 1300ms;
      transition-delay: calc(var(--i) * 28ms);
    }

    /* ====== FIELD ====== */
    #field {
      position: fixed;
      inset: 0;
      overflow: hidden;
      background-color: var(--field);
      background-image:
        radial-gradient(circle at 50% 45%, transparent 45%, rgba(20,28,12,0.34) 100%),
        url('images/clover/grass-tile.jpg');
      background-size: 100% 100%, 1024px 1024px;
      background-repeat: no-repeat, repeat;
      background-position: center, center;
    }

    .clover {
      position: absolute;
      display: block;
      cursor: none;                      /* the magnifier stands in for it */
      transform: translate(-50%, -50%)
                 translate(var(--dx, 0px), var(--dy, 0px))
                 translate(var(--wx, 0px), var(--wy, 0px))
                 rotate(calc(var(--r) + var(--w, 0deg)))
                 scaleX(var(--flip, 1))
                 scale(var(--z, 1)) scale(var(--hs, 1)) scale(var(--pu, 1));
      transition: filter 220ms, opacity 220ms;
      -webkit-user-drag: none;
      opacity: 0;
    }

    /* A patch arrives whole. Left alone, every clover is its own <img> and shows
       itself the instant its own file finishes decoding, so the field assembles
       in front of you a handful at a time. They are planted invisible instead,
       and the whole patch is faded up once the art is decoded and ready.
       `settling` only lends the entrance a longer, softer beat than the 220ms
       the hint wants for its dimming. */
    #field.grown .clover { opacity: 1; }
    #field.settling .clover { transition: filter 220ms, opacity 520ms ease; }


    /* the class only carries depth and shadow now - the lift itself is eased
       frame by frame, so it comes back down as nicely as it went up */
    .clover.zoom {
      z-index: 900 !important;
      filter: drop-shadow(0 4px 8px rgba(0,0,0,0.5)) brightness(1.05);
    }

    /* hint dims the patch down to a rough area around the lucky one */
    #field.hinting .clover { opacity: 0.15; }
    #field.hinting .clover.hot { opacity: 1; }

    .clover.found {
      animation: bloom 1400ms cubic-bezier(.2,.75,.3,1) forwards,
                 breathe 4.5s ease-in-out 1400ms infinite;
      z-index: 950 !important;
    }
    @keyframes bloom {
      0%   { filter: drop-shadow(0 0 0 rgba(234,255,176,0)); }
      55%  { filter: drop-shadow(0 0 22px rgba(234,255,176,0.95)) brightness(1.22); }
      100% { filter: drop-shadow(0 0 12px rgba(234,255,176,0.6)) brightness(1.1); }
    }
    @keyframes breathe {
      0%, 100% { filter: drop-shadow(0 0 10px rgba(234,255,176,0.5)) brightness(1.06); }
      50%      { filter: drop-shadow(0 0 18px rgba(234,255,176,0.8)) brightness(1.14); }
    }

    /* ====== THE WORM ====== */
    #worm {
      position: fixed;
      inset: 0;
      z-index: 12;
      pointer-events: none;
      opacity: 0;
      transition: opacity 700ms ease;
    }
    #worm.here { opacity: 1; }

    #worm-chat {
      position: absolute;
      z-index: 520;
      pointer-events: none;
    }

    #worm-icon {
      pointer-events: auto;
      width: 32px;
      height: 26px;
      cursor: pointer;
      opacity: 0;
      transform: translateY(7px) scale(0.6);
      transition: opacity 420ms ease, transform 520ms cubic-bezier(.22,1.4,.4,1);
      filter: drop-shadow(0 2px 4px rgba(10, 16, 6, 0.55));
    }
    #worm-icon svg { width: 100%; height: 100%; display: block; }
    #worm-icon svg path {
      fill: rgba(47, 58, 31, 0.72);
      stroke: #a9c47e;
      stroke-width: 1.6;
    }
    #worm-icon svg circle { fill: #c8d8a0; }
    #worm-icon:hover svg path { fill: rgba(72, 90, 48, 0.85); }

    #worm-chat.here #worm-icon { opacity: 1; transform: none; animation: nudge 2.8s ease-in-out infinite; }
    @keyframes nudge {
      0%, 100% { transform: translateY(0); }
      50%      { transform: translateY(-2.5px); }
    }

    #worm-bubble {
      position: absolute;
      left: 26px;
      bottom: 14px;
      width: max-content;
      max-width: 250px;          /* the lines are longer now */
      padding: 6px 10px;
      font-size: 14px;
      line-height: 1.35;
      color: var(--ink);
      background: rgba(24, 32, 15, 0.42);
      backdrop-filter: blur(3px);
      -webkit-backdrop-filter: blur(3px);
      border: 1px solid rgba(169, 196, 126, 0.35);
      opacity: 0;
      transform: translateY(4px) scale(0.97);
      transform-origin: 0 100%;
      transition: opacity 320ms ease, transform 380ms cubic-bezier(.2,.8,.25,1);
    }
    #worm-chat.open #worm-bubble { opacity: 1; transform: none; }

    /* ====== WIN OVERLAY - and the daily's briefing, in the same box ====== */
    #win, #intro, #about {
      position: fixed;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 1000;
      padding: 1rem;
      cursor: default;
      background: rgba(20, 29, 12, 0.52);
      opacity: 0;
      visibility: hidden;
      transition: opacity 700ms cubic-bezier(.33, 0, .2, 1), visibility 0s linear 700ms;
    }
    #win.show, #intro.show, #about.show {
      opacity: 1;
      visibility: visible;
      transition: opacity 700ms cubic-bezier(.33, 0, .2, 1);
    }
    #win *, #intro *, #about * { cursor: default; }

    /* ====== ONE PANEL ======
       Every box in the game is this box: the win tally, the daily briefing, the
       about page and the leaderboard. The hand-drawn art it used to wear was a
       fixed 3.34:1 letterbox that could not hold a list of times without being
       stretched out of shape, and having two unrelated containers made the game
       read as two games. Its warmth is kept in the palette instead - everything
       inside is the same greens and creams as the rest of the site, rather than
       the bright whites that were needed to sit on the drawing. */
    .panel,
    .intro-panel,
    .board-panel {
      box-sizing: border-box;
      background: rgba(47, 58, 31, 0.88);
      backdrop-filter: blur(3px);
      -webkit-backdrop-filter: blur(3px);
      border: 2px solid var(--cream-warm);
      box-shadow: 0 10px 40px rgba(10, 16, 6, 0.5);
      color: var(--ink);
    }

    .panel {
      width: min(94vw, 460px);
      max-height: 88vh;
      overflow-y: auto;
      min-width: 0;
      opacity: 0;
      transform: translateY(12px) scale(0.985);
      /* one long ease that runs out of momentum rather than stopping, and the
         same curve on both properties so nothing arrives ahead of the rest */
      transition: opacity 700ms cubic-bezier(.22, 1, .36, 1) 90ms,
                  transform 900ms cubic-bezier(.22, 1, .36, 1) 90ms;
      will-change: opacity, transform;
    }
    #win.show .panel, #intro.show .panel { opacity: 1; transform: none; }

    .sheet {
      min-width: 0;
      padding: 26px 24px 22px;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      text-align: center;
    }

    /* Sizes are plain pixels now. They used to be read off the box's own width
       so the words would shrink with the drawing; nothing is being drawn on any
       more, and type that holds still is easier to read. */
    .panel h2 {
      font-size: 23px;
      line-height: 1.15;
      color: var(--sage-tint);
      font-weight: normal;
      letter-spacing: 0.4px;
      margin: 0 0 0.35em;
    }
    .sub {
      font-size: 14px;
      line-height: 1.35;
      color: var(--ink-faint);
      margin: 0 0 0.5em;
    }
    .tally {
      font-size: 14.5px;
      line-height: 1.35;
      color: var(--ink-soft);
      margin: 0 0 0.6em;
    }
    .tally b { font-weight: normal; color: var(--sage-tint); }

    /* side by side: two or three short readings sit better across than down */
    .stats {
      display: flex;
      justify-content: center;
      align-items: baseline;
      flex-wrap: wrap;
      gap: 0.5em 26px;
      margin-bottom: 0.7em;
    }
    .stat { display: flex; flex-direction: column; line-height: 1.15; }
    .stat b {
      font-size: 20px;
      color: var(--ink);
      font-weight: normal;
    }
    .stat span {
      font-size: 11.5px;
      color: var(--ink-faint);
      letter-spacing: 0.4px;
      margin-top: 0.45em;
    }
    /* a new best is still worth a second colour - the same sage the headings
       use, so it reads as emphasis rather than as a different palette */
    .stat.record b { font-size: 17px; color: var(--sage-tint); }
    .stat.record span { color: var(--sage-tint); opacity: 0.75; }

    .panel-actions {
      display: flex;
      justify-content: center;
      flex-wrap: wrap;
      gap: 9px;
      margin-top: 4px;
    }
    /* the same square, bordered button the tiers and the boards use */
    .panel button {
      font-family: inherit;
      font-size: 14px;
      color: var(--ink-soft);
      background: none;
      border: 1px solid var(--cream-warm);
      padding: 9px 15px;
      cursor: pointer;
      transition: background 160ms, border-color 160ms, color 160ms;
    }
    .panel button:hover,
    .panel button:focus {
      background: var(--sage-tint);
      border-color: var(--sage-tint);
      color: var(--chrome-dark);
    }

    /* ====== THE LEADERBOARD ======
       The shared box above, with a scrolling list inside it and its own height
       cap - a board can run to a hundred names and still has to fit a phone. */
    #board {
      position: fixed;
      inset: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      z-index: 1100;
      padding: 1rem;
      cursor: default;
      background: rgba(20, 29, 12, 0.62);
      opacity: 0;
      visibility: hidden;
      transition: opacity 420ms cubic-bezier(.33, 0, .2, 1), visibility 0s linear 420ms;
    }
    #board.show {
      opacity: 1;
      visibility: visible;
      transition: opacity 420ms cubic-bezier(.33, 0, .2, 1);
    }
    #board * { cursor: default; }
    #board input { cursor: text; }
    #board button { cursor: pointer; }

    .board-panel {
      width: min(94vw, 460px);
      max-height: min(86vh, 620px);
      display: flex;
      flex-direction: column;
      padding: 22px 22px 18px;
      transform: translateY(10px);
      transition: transform 460ms cubic-bezier(.22, 1, .36, 1);
    }
    #board.show .board-panel { transform: none; }

    .board-panel h2 {
      font-size: 19px;
      font-weight: normal;
      letter-spacing: 0.4px;
      color: var(--sage-tint);
      line-height: 1;
    }
    .board-when { font-size: 13px; color: var(--ink-faint); margin-top: 5px; }

    /* once the time is posted there is nothing left to fill in - only the note
       saying which name it went up under */
    .board-join { margin-top: 16px; }
    .board-join.done .board-label,
    .board-join.done .board-entry,
    .board-join.done #board-send { display: none; }

    .board-label { display: block; font-size: 13px; color: var(--ink-soft); margin-bottom: 6px; }
    .board-entry { display: flex; gap: 8px; }
    #board-name {
      flex: 1 1 auto;
      min-width: 0;
      font-family: inherit;
      font-size: 15px;
      color: var(--ink);
      background: var(--field);
      border: 1px solid var(--cream-warm);
      padding: 7px 9px;
    }
    #board-name:focus { outline: none; border-color: var(--sage-tint); }

    #board-reroll, #board-send, #board-close, .panel-close {
      font-family: inherit;
      font-size: 13px;
      color: var(--ink-soft);
      background: none;
      border: 1px solid var(--cream-warm);
      padding: 7px 12px;
      transition: background 160ms, color 160ms, border-color 160ms;
    }
    #board-send { margin-top: 10px; width: 100%; padding: 8px; color: var(--sage-tint); }
    #board-close { margin-top: 14px; align-self: center; }
    #board-reroll:hover, #board-send:hover, #board-close:hover, .panel-close:hover {
      background: var(--sage-tint);
      border-color: var(--sage-tint);
      color: var(--chrome-dark);
    }
    #board-send[disabled] { opacity: 0.45; }
    #board-send[disabled]:hover {
      background: none;
      color: var(--sage-tint);
      border-color: var(--cream-warm);
    }
    .board-note { font-size: 12px; color: var(--ink-faint); margin-top: 8px; min-height: 1.2em; }

    .board-list {
      list-style: none;
      margin-top: 16px;
      flex: 1 1 auto;
      min-height: 0;                 /* or the list refuses to scroll inside the flex column */
      overflow-y: auto;
      border-top: 1px solid rgba(168, 176, 136, 0.3);
    }
    .board-row, .board-empty {
      display: flex;
      align-items: baseline;
      gap: 10px;
      padding: 7px 2px;
      font-size: 15px;
      border-bottom: 1px solid rgba(168, 176, 136, 0.14);
    }
    .board-empty { justify-content: center; color: var(--ink-faint); font-size: 13px; }
    .board-rank { flex: 0 0 2.2em; font-size: 13px; color: var(--ink-faint); }
    .board-name {
      flex: 1 1 auto;
      min-width: 0;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      color: var(--ink-soft);
    }
    .board-time { flex: 0 0 auto; color: var(--ink); }
    .board-row.you .board-rank,
    .board-row.you .board-name,
    .board-row.you .board-time { color: var(--sage-tint); }

    /* ====== THE BRIEFING ======
       Its own box rather than the drawn tally panel. That art is a 3.34:1
       letterbox sized for a line of stats, and a heading, two paragraphs and
       three buttons can only fit inside it by stretching the drawing out of
       shape and squeezing the words down past reading size. This is the same
       box the leaderboard uses, at proper sizes, and it can grow. */
    .intro-panel {
      position: relative;
      width: min(94vw, 460px);
      max-height: 88vh;
      overflow-y: auto;
      padding: 28px 26px 24px;
      transform: translateY(10px);
      transition: transform 460ms cubic-bezier(.22, 1, .36, 1);
    }
    #intro.show .intro-panel,
    #about.show .intro-panel { transform: none; }
    #intro button, #intro a, #about button { cursor: pointer; }

    /* A way out of the briefing. The daily is a small commitment - one go at a
       tier, no replays - so changing your mind before the clock starts should
       not mean hunting for the browser's back button. */
    .panel-x {
      position: absolute;
      top: 8px;
      right: 10px;
      font-family: inherit;
      font-size: 24px;
      line-height: 1;
      padding: 4px 9px;
      background: none;
      border: 0;
      transition: color 160ms;
    }
    .panel-x:link, .panel-x:visited { color: var(--ink-faint); text-decoration: none; }
    .panel-x:hover, .panel-x:focus, .panel-x:active { color: var(--sage-tint); }

    /* so a long heading never runs under the cross */
    #intro .intro-panel h2 { padding-right: 34px; }

    .panel-close { display: block; margin: 22px auto 0; }

    .intro-panel h2 {
      font-size: 27px;
      font-weight: normal;
      letter-spacing: 0.5px;
      line-height: 1.1;
      color: var(--sage-tint);
    }
    .intro-copy {
      font-size: 16px;
      line-height: 1.45;
      color: var(--ink);
      margin-top: 12px;
    }
    .intro-note {
      font-size: 13.5px;
      line-height: 1.45;
      color: var(--ink-faint);
      margin-top: 9px;
    }
    .intro-ask {
      font-size: 14px;
      color: var(--ink-soft);
      margin-top: 20px;
      opacity: 0.8;
    }

    /* Stacked, full width, one per line. Three across a 460px box leaves each
       one too narrow for its own label once the zone name sits under it - which
       is what pushed them out of the old panel in the first place. */
    .tier-pick {
      display: flex;
      flex-direction: column;
      gap: 9px;
      margin-top: 9px;
    }
    .tier {
      display: flex;
      align-items: baseline;
      justify-content: space-between;
      gap: 12px;
      width: 100%;
      font-family: inherit;
      text-align: left;
      color: var(--ink);
      background: none;
      border: 1px solid var(--cream-warm);
      padding: 13px 15px;
      transition: background 160ms, color 160ms, border-color 160ms;
    }
    .tier b { font-weight: normal; font-size: 18px; line-height: 1.1; }
    .tier span {
      font-size: 13px;
      color: var(--ink-faint);
      letter-spacing: 0.3px;
      transition: color 160ms;
    }
    .tier:hover {
      background: var(--sage-tint);
      border-color: var(--sage-tint);
      color: var(--chrome-dark);
    }
    .tier:hover span { color: var(--chrome-dark); }

    /* one already played today: a receipt rather than an offer, but still worth
       opening for its board */
    .tier.done { border-style: dashed; opacity: 0.66; }
    .tier.done:hover { opacity: 1; }

    /* one board per tier, switched by tabs above the list */
    .board-tabs {
      display: flex;
      gap: 6px;
      margin-top: 12px;
    }
    .board-tab {
      flex: 1 1 0;
      font-family: inherit;
      font-size: 13px;
      color: var(--ink-soft);
      background: none;
      border: 1px solid var(--cream-warm);
      padding: 6px 4px;
      opacity: 0.6;
      transition: opacity 160ms, background 160ms, color 160ms, border-color 160ms;
    }
    .board-tab:hover { opacity: 1; }
    .board-tab.on {
      opacity: 1;
      color: var(--chrome-dark);
      background: var(--sage-tint);
      border-color: var(--sage-tint);
    }

    /* ====== THE ABOUT PANEL ======
       Borrowed from the link hub so the two read as one place: its sparkle
       line, its leek rule, its lowercase letter-spaced chip. The heading and
       the trimmings are centred; the paragraphs are not, because centred prose
       is harder to read and this is the only real prose in the game. */
    .about-panel { text-align: center; }
    .about-panel .intro-copy { text-align: left; }

    .about-panel .deco-line {
      font-size: 11px;
      color: var(--ink-faint);
      letter-spacing: 1px;
      margin-top: 8px;
      margin-bottom: 16px;
    }

    /* the same leek that separates the homepage menu, at the same 14px and the
       same hard pixel edges, with a hairline running out to either side */
    .about-rule {
      display: flex;
      align-items: center;
      gap: 12px;
      margin-top: 22px;
    }
    .about-rule::before,
    .about-rule::after {
      content: '';
      flex: 1 1 auto;
      height: 1px;
      background: rgba(168, 176, 136, 0.28);
    }
    .about-rule img {
      height: 14px;
      width: auto;
      flex-shrink: 0;
      image-rendering: pixelated;
      display: block;
    }

    .about-chip {
      display: block;
      color: var(--sage-tint);
      font-size: 13px;
      letter-spacing: 2px;
      text-transform: lowercase;
      margin-top: 14px;
      margin-bottom: 11px;
    }

    /* three even columns, so no button is wider than its neighbour just because
       its name is longer. The address takes the row beneath: it is far longer
       than the rest and should never be broken across a line. */
    .about-links {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 8px;
    }
    .about-email { grid-column: 1 / -1; }

    .about-links a {
      font-family: inherit;
      font-size: 14px;
      color: var(--ink-soft);
      background: none;
      border: 1px solid var(--cream-warm);
      padding: 8px 13px;
      transition: background 160ms, color 160ms, border-color 160ms;
    }
    .about-links a:link,
    .about-links a:visited { color: var(--ink-soft); text-decoration: none; }
    .about-links a:hover,
    .about-links a:focus,
    .about-links a:active {
      background: var(--sage-tint);
      border-color: var(--sage-tint);
      color: var(--chrome-dark);
    }
    #about .intro-copy + .intro-copy { margin-top: 10px; }

    /* quieter than the tiers above it: an invitation to pass on, not a fourth
       thing to choose between */
    .intro-share {
      display: block;
      margin: 18px auto 0;
      font-family: inherit;
      font-size: 13px;
      color: var(--ink-faint);
      background: none;
      border: 1px solid rgba(168, 176, 136, 0.35);
      padding: 7px 15px;
      transition: background 160ms, color 160ms, border-color 160ms;
    }
    .intro-share:hover,
    .intro-share:focus {
      background: var(--sage-tint);
      border-color: var(--sage-tint);
      color: var(--chrome-dark);
    }
