@layer components {
  /* ==== Type roles =======================================================
     Everything display-weight is Baloo 2 at 800. It is a fat rounded face, so
     it wants slightly negative tracking at large sizes and a tight line box. */
  .wordmark {
    display: inline-flex;
    align-items: center;
    gap: 0.2ch;
    min-height: 2.75rem; /* it is a link, so it owes the same 44px target */
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 800;
    letter-spacing: var(--tracking-tight);
    text-decoration: none;
    transform: rotate(var(--tilt-nudge));
    transition: transform var(--dur-base) var(--ease-boing);
  }

  .wordmark:hover {
    transform: rotate(0deg) scale(1.03);
  }

  .wordmark__race {
    color: var(--ink-pink);
    -webkit-text-stroke: 1.5px var(--ink);
    paint-order: stroke fill;
  }

  .display {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: var(--text-3xl);
    line-height: 0.94;
    letter-spacing: var(--tracking-tight);
  }

  .headline {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--text-2xl);
    line-height: 1.06;
    letter-spacing: var(--tracking-tight);
  }

  /* Small all-caps label. Nunito at 900 rather than a third typeface. */
  .eyebrow {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: var(--tracking-caps);
    color: var(--ink-soft);
  }

  .lede {
    font-size: var(--text-lg);
    font-weight: 600;
    color: var(--ink-soft);
    max-width: 34ch;
    margin-inline: auto;
  }

  .note {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--ink-soft);
  }

  /* The hero's bridging word, inked in the overprint colour because it is the
     thing the two players' letters produce together. Height is reserved so the
     layout does not jump as the word types and clears. */
  .hero__word {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    /* Paper fill with an overprint outline: the word the two inks made
       together, so it wears the overprint colour rather than either player's. */
    color: var(--paper);
    -webkit-text-stroke: 3.5px var(--overprint);
    paint-order: stroke fill;
    min-height: 1.5em;
  }

  /* ==== Buttons =========================================================
     Die-cut stickers. Pressing one squashes it into its own hard offset, which
     is the single most satisfying interaction in the whole interface, so it is
     worth the extra transform. */
  .btn {
    --btn-face: var(--paper);
    --btn-ink: var(--ink);
    --btn-tilt: 0deg;

    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 3.25rem;
    padding: var(--space-3) var(--space-6);
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 700;
    letter-spacing: 0.005em;
    color: var(--btn-ink);
    text-decoration: none;
    background-color: var(--btn-face);
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-pill);
    box-shadow: var(--offset-sm);
    transform: rotate(var(--btn-tilt));
    transition:
      transform var(--dur-base) var(--ease-boing),
      box-shadow var(--dur-base) var(--ease-boing),
      background-color var(--dur-base) var(--ease-out);
  }

  .btn:hover:not(:disabled) {
    transform: rotate(var(--btn-tilt)) translate(-2px, -3px) scale(1.02);
    box-shadow: var(--offset-lg);
  }

  .btn:active:not(:disabled) {
    transform: rotate(var(--btn-tilt)) translate(3px, 4px) scale(0.97);
    box-shadow: 0 0 0 var(--ink);
    transition-duration: var(--dur-fast);
  }

  .btn:disabled {
    opacity: 0.4;
    box-shadow: var(--offset-sm);
    transform: rotate(var(--btn-tilt));
  }

  .btn--primary {
    --btn-face: var(--ink);
    --btn-ink: var(--paper);
  }

  .btn--pink {
    --btn-face: var(--ink-pink);
  }

  .btn--blue {
    --btn-face: var(--ink-blue);
    --btn-ink: var(--paper);
  }

  .btn--mint {
    --btn-face: var(--ink-mint);
  }

  .btn--sun {
    --btn-face: var(--ink-sun);
  }

  /* The big first-choice button gets a deliberate tilt. Only one per screen. */
  .btn--hero {
    --btn-tilt: var(--tilt-b);

    min-height: 3.875rem;
    font-size: var(--text-xl);
    padding-inline: var(--space-7);
    box-shadow: var(--offset-md);
  }

  .btn--quiet {
    box-shadow: none;
    border-color: transparent;
    background-color: transparent;
    color: var(--ink-soft);
    padding-inline: var(--space-4);
    font-weight: 700;
  }

  .btn--quiet:hover:not(:disabled) {
    transform: none;
    box-shadow: none;
    color: var(--ink);
    background-color: var(--overprint-soft);
  }

  .btn--quiet:active:not(:disabled) {
    transform: scale(0.97);
    box-shadow: none;
  }

  .btn--block {
    width: 100%;
  }

  /* ==== Cards ===========================================================
     Thick outline, hard offset, and a slight tilt so a stack of them reads as
     placed by hand rather than laid out by a grid. */
  .card {
    position: relative;
    width: 100%;
    padding: var(--space-5);
    background-color: var(--paper);
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-lg);
    box-shadow: var(--offset-md);
    transform: rotate(var(--card-tilt, 0deg));
  }

  .card--tilt {
    --card-tilt: var(--tilt-nudge);
  }

  .card--halftone::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background-image: var(--halftone);
    background-size: 6px 6px;
    opacity: 0.6;
    pointer-events: none;
  }

  .card__title {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: var(--text-xl);
    line-height: 1.1;
    letter-spacing: var(--tracking-tight);
  }

  /* ==== Letter tile =====================================================
     A paper tile with a fat ring in the owner's ink. The glyph stays knocked
     out of bare paper, which is the only way it clears contrast against the
     darker blue — a glyph sitting directly on #3D5AFF would not.

     The ring is an inset shadow rather than a second border because inset
     shadows do not affect blending or layout, and this element is tilted. */
  .tile {
    --tile-tilt: 0deg;

    position: relative;
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    inline-size: var(--tile-size);
    aspect-ratio: 5 / 6;
    background-color: var(--paper);
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-tile);
    box-shadow:
      inset 0 0 0 calc(var(--tile-size) * 0.07) var(--player-ink),
      var(--offset-md);
    transform: rotate(var(--tile-tilt));
    transition:
      transform var(--dur-slow) var(--ease-boing),
      box-shadow var(--dur-slow) var(--ease-boing);
  }

  /* The two tiles lean away from each other, like a standoff. */
  .tile--a {
    --player-ink: var(--ink-pink);
    --tile-tilt: var(--tilt-a);
  }

  .tile--b {
    --player-ink: var(--ink-blue);
    --tile-tilt: var(--tilt-b);
  }

  .tile__glyph {
    font-family: var(--font-display);
    font-size: var(--text-tile);
    font-weight: 800;
    line-height: 1;
    color: var(--ink);
    text-transform: uppercase;
  }

  /* ==== The bridge ======================================================
     THE SIGNATURE. Two ink bands reach out from behind the tiles and overlap
     in the gap between them; `mix-blend-mode: multiply` turns that overlap
     into --overprint. It marks the exact spot where the two players' letters
     join to make one word, which is the whole idea of the game.

     These bands deliberately live in .standoff rather than inside the tiles.
     A tile carries `transform: rotate()`, which makes it a stacking context,
     and two blended layers in separate stacking contexts can never blend with
     each other. Keeping the bands as siblings is what makes the effect work. */
  .bridge__ink {
    position: absolute;
    z-index: 0; /* below the tiles, which sit at z-index 1 */
    inset-block-start: 50%;
    height: calc(var(--tile-size) * 0.2);
    margin-block-start: calc(var(--tile-size) * -0.1); /* margin, not transform */
    inline-size: calc(
      var(--bridge-gap) / 2 + var(--bridge-tuck) + var(--bridge-overlap)
    );
    /* Outlined like everything else here. Only the stretch crossing the gap is
       visible — the ends are tucked behind the tiles — so what reads is a
       printed bar running from one tile to the other. */
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-sm);
    mix-blend-mode: multiply;
    pointer-events: none;
  }

  .bridge__ink--a {
    inset-inline-start: calc(50% - var(--bridge-gap) / 2 - var(--bridge-tuck));
    background-color: var(--ink-pink);
  }

  .bridge__ink--b {
    inset-inline-start: calc(50% - var(--bridge-overlap));
    background-color: var(--ink-blue);
  }

  .tile__role {
    position: absolute;
    inset-block-start: 0.5rem;
    inset-inline: 0;
    font-family: var(--font-body);
    font-size: 0.625rem;
    font-weight: 900;
    text-align: center;
    text-transform: uppercase;
    letter-spacing: var(--tracking-caps);
    color: var(--ink-soft);
  }

  /* Face-down: the letter is committed but not revealed. Halftone stands in
     for the back of a printed tile. */
  .tile--hidden .tile__glyph {
    color: transparent;
  }

  .tile--hidden {
    background-image: var(--halftone);
    background-size: 7px 7px;
  }

  .tile--empty {
    border-style: dashed;
    box-shadow: inset 0 0 0 calc(var(--tile-size) * 0.07) var(--paper-deep);
  }

  /* ==== Letter picker ===================================================
     A one-character field shaped exactly like a tile, so committing a letter
     feels like placing the tile you were already looking at. */
  .letter-field {
    inline-size: var(--tile-size);
    aspect-ratio: 5 / 6;
    padding: 0;
    font-family: var(--font-display);
    font-size: var(--text-tile);
    font-weight: 800;
    line-height: 1;
    text-align: center;
    text-transform: uppercase;
    color: var(--ink);
    background-color: var(--paper);
    border: var(--stroke) dashed var(--ink);
    border-radius: var(--radius-tile);
    box-shadow: var(--offset-sm);
    caret-color: var(--ink-pink);
    transform: rotate(var(--tilt-a));
    transition:
      transform var(--dur-base) var(--ease-boing),
      box-shadow var(--dur-base) var(--ease-boing);
  }

  .letter-field:focus {
    border-style: solid;
    outline: none;
    transform: rotate(0deg) scale(1.04);
    box-shadow: var(--offset-md);
  }

  .letter-field::placeholder {
    color: var(--ink-faint);
  }

  /* ==== Text fields ====================================================== */
  .field {
    display: grid;
    gap: var(--space-2);
  }

  .field__label {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: var(--tracking-caps);
    color: var(--ink-soft);
  }

  .input {
    inline-size: 100%;
    min-height: 3.25rem;
    padding: var(--space-3) var(--space-4);
    font-weight: 700;
    background-color: var(--paper);
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-md);
    box-shadow: var(--offset-sm);
    transition:
      box-shadow var(--dur-base) var(--ease-boing),
      transform var(--dur-base) var(--ease-boing);
  }

  .input:focus {
    outline: none;
    transform: translate(-1px, -2px);
    box-shadow: var(--offset-md);
  }

  .input--code {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 800;
    text-align: center;
    letter-spacing: 0.4em;
    /* letter-spacing adds trailing space after the last digit, which shifts the
       centred text left by half a step. Indent by half to put it back. */
    text-indent: 0.2em;
  }

  .field__error {
    font-size: var(--text-sm);
    font-weight: 800;
    color: var(--overprint);
    min-height: 1.4rem;
  }

  /* ==== Word input =====================================================
     Outlined in the overprint colour: this is where the two players' inks
     meet, so it is where the word gets typed. */
  .word-input {
    inline-size: 100%;
    min-height: 4.25rem;
    padding: var(--space-3) var(--space-5);
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 800;
    text-align: center;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--ink);
    background-color: var(--paper);
    border: var(--stroke) solid var(--overprint);
    border-radius: var(--radius-md);
    box-shadow: 4px 5px 0 var(--overprint);
    transition:
      border-color var(--dur-base) var(--ease-out),
      box-shadow var(--dur-base) var(--ease-boing),
      transform var(--dur-base) var(--ease-boing);
  }

  .word-input:focus {
    outline: none;
    transform: translate(-1px, -2px);
    box-shadow: 7px 8px 0 var(--overprint);
  }

  .word-input:disabled {
    color: var(--ink-faint);
    border-color: var(--ink-faint);
    box-shadow: 4px 5px 0 var(--ink-faint);
    background-color: var(--paper-deep);
  }

  .word-input::placeholder {
    color: var(--ink-faint);
    letter-spacing: 0.02em;
    text-transform: none;
  }

  /* ==== Room code =======================================================
     Fixed-width digit boxes, alternately tilted. The fixed width is why no
     monospace typeface is needed: the digits cannot shift the layout. */
  .code {
    display: flex;
    gap: var(--space-3);
    justify-content: center;
  }

  .code__digit {
    display: grid;
    place-items: center;
    inline-size: clamp(3.25rem, 2rem + 6vw, 4.25rem);
    aspect-ratio: 4 / 5;
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 800;
    background-color: var(--paper);
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-sm);
    box-shadow: var(--offset-sm);
  }

  .code__digit:nth-child(odd) {
    transform: rotate(var(--tilt-a));
    background-color: var(--ink-sun);
  }

  .code__digit:nth-child(even) {
    transform: rotate(var(--tilt-b));
  }

  /* ==== Player card ====================================================== */
  .player {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-3) var(--space-4);
    background-color: var(--paper);
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-md);
    box-shadow: var(--offset-sm);
  }

  .player__chip {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    inline-size: 2.75rem;
    aspect-ratio: 1;
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 800;
    color: var(--ink);
    background-color: var(--player-ink);
    border: var(--stroke-thin) solid var(--ink);
    border-radius: var(--radius-pill);
    text-transform: uppercase;
    transform: rotate(var(--tilt-a));
  }

  .player--b {
    --player-ink: var(--ink-blue);
  }

  .player--b .player__chip {
    transform: rotate(var(--tilt-b));
  }

  .player__body {
    display: grid;
    gap: 1px;
    min-inline-size: 0;
    flex: 1 1 auto;
  }

  .player__name {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .player__meta {
    display: flex;
    align-items: center;
    gap: var(--space-2);
    font-size: var(--text-xs);
    font-weight: 700;
    color: var(--ink-soft);
  }

  .player__score {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 800;
    line-height: 1;
  }

  .player--vacant {
    border-style: dashed;
    box-shadow: none;
    color: var(--ink-faint);
  }

  .player--vacant .player__chip {
    background-color: transparent;
    border-style: dashed;
  }

  /* ==== Status and badges ================================================ */
  .dot {
    inline-size: 0.625rem;
    aspect-ratio: 1;
    border: 1.5px solid var(--ink);
    border-radius: var(--radius-pill);
    background-color: var(--paper-deep);
    flex: 0 0 auto;
  }

  .dot--live {
    background-color: var(--ink-mint);
  }

  .dot--waiting {
    background-color: var(--ink-sun);
  }

  .dot--gone {
    background-color: var(--ink-pink);
  }

  .badge {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: 0.1rem var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--tracking-wide);
    background-color: var(--paper-deep);
    border: var(--stroke-thin) solid var(--ink);
    border-radius: var(--radius-pill);
    transform: rotate(var(--tilt-b));
  }

  .badge--ready {
    background-color: var(--ink-mint);
  }

  .badge--host {
    background-color: var(--ink-sun);
  }

  .badge--you {
    background-color: var(--ink-tangerine);
  }

  /* ==== Timer ============================================================ */
  .timer {
    inline-size: 100%;
    max-inline-size: var(--measure);
    height: 1rem;
    background-color: var(--paper-deep);
    border: var(--stroke-thin) solid var(--ink);
    border-radius: var(--radius-pill);
    box-shadow: var(--offset-sm);
    overflow: hidden;
  }

  .timer__fill {
    height: 100%;
    inline-size: 100%;
    background-color: var(--ink-mint);
    background-image: repeating-linear-gradient(
      -45deg,
      rgb(43 27 61 / 18%) 0 6px,
      transparent 6px 12px
    );
    transform-origin: left center;
    transition: background-color var(--dur-slow) linear;
  }

  .timer[data-urgency="warn"] .timer__fill {
    background-color: var(--ink-sun);
  }

  .timer[data-urgency="critical"] .timer__fill {
    background-color: var(--ink-pink);
  }

  /* ==== Countdown ======================================================== */
  .countdown {
    display: grid;
    gap: var(--space-3);
    justify-items: center;
    text-align: center;
  }

  .countdown__number {
    font-family: var(--font-display);
    font-size: var(--text-count);
    font-weight: 800;
    line-height: 0.85;
    color: var(--ink-sun);
    -webkit-text-stroke: 5px var(--ink);
    paint-order: stroke fill;
  }

  /* ==== Toast ============================================================ */
  .toast {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    inline-size: fit-content;
    max-inline-size: min(30rem, 100%);
    padding: var(--space-3) var(--space-5);
    font-weight: 800;
    background-color: var(--paper);
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-pill);
    box-shadow: var(--offset-md);
    pointer-events: auto;
  }

  .toast::before {
    content: "";
    inline-size: 0.75rem;
    aspect-ratio: 1;
    flex: 0 0 auto;
    border: 1.5px solid var(--ink);
    border-radius: var(--radius-pill);
    background-color: var(--paper-deep);
  }

  .toast--good::before {
    background-color: var(--ink-mint);
  }

  .toast--bad::before {
    background-color: var(--ink-pink);
  }

  .toast--info::before {
    background-color: var(--ink-blue);
  }

  /* ==== Modal ============================================================ */
  .modal {
    inline-size: min(28rem, 100%);
    padding: var(--space-6);
    text-align: center;
    background-color: var(--paper);
    border: var(--stroke) solid var(--ink);
    border-radius: var(--radius-lg);
    box-shadow: var(--offset-lg);
  }

  /* ==== Divider =========================================================
     A dashed cut line, because everything else here is a sticker. */
  .hairline {
    inline-size: 100%;
    height: 0;
    background: none;
    border: 0;
    border-block-start: var(--stroke-thin) dashed var(--ink-faint);
  }
}
