/* One sheet of the player's design system (tickets/T19-room-for-two.md).
   style.css keeps the fonts, the tokens and the reset; every area has its
   own file from there, linked in index.html in this order — the cascade is
   the order of the <link>s, not of a bundler. A ticket works in its sheet.
   No @import: it serialises the requests, which is the cost being avoided. */

/* ---------- Page ---------- */
.page {
  position: relative;
  z-index: 1;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: var(--pad-top) var(--margin) var(--pad-bottom);
}

.icon { display: block; fill: currentColor; }
.led {
  display: block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--control);
}
.is-on > .led, .is-current > .led { background: var(--primary); }

/* ---------- Bar: the deck on the left, the meta on the right ---------- */
.bar {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  height: 24px;
}
.deck { display: flex; align-items: center; gap: 16px; }
.transport { display: flex; gap: 16px; }
/* Four keys 4 apart: at the shared --hit-x of 8, each zone was 32 wide on 20 of
   pitch and the neighbours overlapped by 12 — the key you aimed at was not
   always the one that answered. Half the gutter is what a zone may take
   (tickets/T27-the-hand-finds-the-key.md). */
.steps { display: flex; gap: 4px; --hit-x: 2px; }
/* Every icon of the bar is 16, on both sides of it: the music keys here and the
   theme toggle in the meta. The box is the glyph; the hit zone is 32 x 40 around it. */
.hit {
  position: relative;
  display: grid;
  place-items: center;
  width: var(--icon);
  height: var(--icon);
  color: var(--ink-muted);
  transition: color 160ms ease;
}
.hit::before { content: ""; position: absolute; inset: calc(var(--hit-y) * -1) calc(var(--hit-x) * -1); }
.hit[hidden] { display: none; }   /* an author rule beats the UA's [hidden], so it is spelled out */
/* The haptic switch (player/sfx.js) covers the key's DRAWING — ios-haptics
   writes `inset: 0` on it, inline — so a tap in the zone above reached the key
   but not the switch: the account opened, the phone stayed still (T73). It is
   laid on the zone instead; !important because the library's style is inline. */
.hit > [data-haptic-trigger] { inset: calc(var(--hit-y) * -1) calc(var(--hit-x) * -1) !important; width: auto !important; height: auto !important; }
/* …and the library rounds it into a capsule: a square key's corners, and any
   zone wider than tall, lost their tick. The switch is invisible; its shape is
   only where it answers, and that is the whole key. */
[data-haptic-trigger] { clip-path: none !important; }
/* …and it writes `position: relative`, inline, on a key it finds static. A key
   that is static only for now — the Jam's pill, hidden when the switch is laid
   and absolute on a phone once shown (jam.css) — kept the inline relative over
   its own rule, and fell across the mood (T152). sfx.js takes the inline back;
   the key gets its anchor here instead, at no weight: any position a sheet
   gives it wins. */
:where(:has(> [data-haptic-trigger])) { position: relative; }
.hit.is-on { color: var(--ink); }
/* Playing is not just "the lit one": the radio is on, and the house says on in primary. */
.transport [data-transport="play"].is-on { color: var(--primary); }
.hit--brand { color: var(--primary); }
/* Every answer to the pointer lives behind this query, here as in stage.css and
   volume.css (tickets/T27-the-hand-finds-the-key.md): a finger has no hover, and
   Safari leaves :hover stuck on the last thing tapped — a key that stays lit
   after the touch says the radio is thinking about something it is not. */
@media (hover: hover) {
  .hit:hover { color: var(--ink); }
  .hit--brand:hover { color: var(--primary); }   /* the brand does not light: it is already primary */
  /* MONO and STEREO had a pointer cursor and no answer to it. The one already
     on says so by being ink; the other one lights like any other key. */
  .mode__item:not(.is-on):hover { color: var(--ink); }
}
.mode { display: flex; gap: 8px; margin-left: 8px; }  /* 16 + 8: the gutter of the Figma bar */
.mode__item { cursor: pointer; }
.mode__item:disabled { cursor: default; opacity: 0.5; }
.mode__item {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  line-height: 16px;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.mode__item.is-on { color: var(--ink); }

.meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* 16 inside the row, not 24 (frame 1495:2905, tickets/T40-la-rangee-de-droite.md).
     The hour, the place and the temperature say ONE thing — where we are and
     when — and they read as one line; the theme switch and the account key are
     commands, each its own. The law of proximity, and the bar had 24 between
     everything, so it had three groups of nothing. .theme takes back the 8 it
     needs below: one declaration against a new DOM node — and against the four
     `.meta > *` selectors of responsive.css that would all have to be rewritten. */
  gap: 16px;
  /* The row of the bar is the icon: 16, the same as the deck's, so both halves
     share one middle line. The bar keeps 24 for the toggle's underline, which
     hangs 8 below and lands on its bottom edge. */
  height: 16px;
  /* The four items hug their own content here: at any width down to 900 they
     stay well clear of the 400 floor, which only ever mattered once the place
     and the temperature are gone (responsive.css) and it is the floor, not
     this rule, that holds the spread. */
  width: max-content;
  max-width: 100%;
  white-space: nowrap;
}
/* The clock ticks and the temperature refreshes without widening or
   narrowing their own box: tabular-nums holds every digit to the same width,
   so neither one shoves its neighbours in the bar. The rule to reach for
   wherever a value like this changes in place — a clock, a counter, a timer. */
/* Body/Meta (DESIGN.md): 12/16 — the clock, the place and the temperature. */
#clock, .meta__place, .meta__temp {
  font-size: 12px;
  line-height: 16px;
}
#clock, .meta__temp { font-variant-numeric: tabular-nums; }
/* Light/dark read as one control (the law of proximity: close together is a
   group, farther apart is not) — .theme-toggle keeps them at the Figma
   `Theme Toggle` component's own spacing (12), and the account key sits a full
   gutter past the pair: 24, the frame's gutter between the row's three groups,
   never the toggle's 12. */
.theme {
  display: flex;
  align-items: center;
  gap: 24px;
  margin-left: 8px;   /* 16 of .meta's gap + 8 = the frame's 24 past the temperature */
}
.theme-toggle {
  display: flex;
  align-items: center;
  gap: var(--gap-theme);
}
.theme-btn { position: relative; display: block; width: var(--icon); height: var(--icon); }
/* Same hit zone as every other key of the bar (.hit, below): --hit-x/--hit-y,
   not a hardcoded 44 — that hardcode was the mismatch with the account key. */
.theme-btn::before { content: ""; position: absolute; inset: calc(var(--hit-y) * -1) calc(var(--hit-x) * -1); }
.theme-btn svg { display: block; width: var(--icon); height: var(--icon); }
/* The sun is drawn 14 inside its 16 where the moon fills it: brought to its
   neighbours' size rather than redrawn (T64). */
.theme-btn[data-set="light"] svg { transform: scale(1.143); }
.theme-btn .i-fill, .theme-btn .i-outline { display: none; }
:root[data-theme="light"] .theme-btn[data-set="light"] .i-fill,
:root[data-theme="dark"]  .theme-btn[data-set="dark"]  .i-fill,
:root[data-theme="light"] .theme-btn[data-set="dark"]  .i-outline,
:root[data-theme="dark"]  .theme-btn[data-set="light"] .i-outline { display: block; }
:root[data-theme="light"] .theme-btn[data-set="light"],
:root[data-theme="dark"]  .theme-btn[data-set="dark"]  { color: var(--primary); }
@media (hover: hover) {
  :root[data-theme="light"] .theme-btn[data-set="dark"]:hover,
  :root[data-theme="dark"]  .theme-btn[data-set="light"]:hover { color: var(--primary-muted); }
}
.theme-btn::after {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: calc(100% + var(--underline-gap));
  height: 1px;
  background: currentColor;
  opacity: 0;
}
:root[data-theme="light"] .theme-btn[data-set="light"]::after,
:root[data-theme="dark"]  .theme-btn[data-set="dark"]::after { opacity: 1; }

/* ---------- Under a finger (tickets/T27-the-hand-finds-the-key.md) ----------
   44 x 44 is the floor for a touch target, and it is bought with the zone, never
   with the drawing: nothing below changes a glyph, a gutter or a height that is
   seen. Only where a finger is the pointer — a 44 zone under a 16 glyph on a
   desktop would catch the mouse well outside the key. */
@media (pointer: coarse) {
  :root { --hit-y: 14px; }   /* 16 + 28 = 44, as .theme-btn::before already does */
  /* The two words of the output had no zone at all: 44 wide, 16 tall. Height
     only: at the narrow end of the bar the pair already sits a few pixels from
     the theme keys, and a zone wider than the drawing would cross into them. */
  .mode__item { position: relative; }
  .mode__item::before { content: ""; position: absolute; inset: -14px 0; }
  /* The theme keys share --hit-x/--hit-y with every other key now, so their
     zone grows to 44 x 44 from the same rule above — but at 20 apart, half a
     gutter each is 10, not the usual 8: at 14 straight they were reaching 4 px
     into the neighbour. The same cap on the account key, which stands in the
     same row. */
  .theme { --hit-x: 10px; }
  /* The first theme key has no gutter on its left at all: at the narrow end of
     the bar the deck's own words are right against it. A zone that cannot go
     left does not go left — an overlap sends the tap to the wrong control,
     which is worse than a target that is short on one side. */
  .theme-btn:first-of-type::before { left: 0; }
  /* The brand and the transport are 12 apart at the narrow end: six each. */
  .deck { --hit-x: 6px; }
}
