/* Desktop furniture: widgets, mascot. */

/* ---------- Widget stack (desktop) ---------- */

/* Top left. The desktop items live top right, so the two never meet, and the
   caption sits far enough below the stack to stay clear of it. */
.widget-stack {
  position: absolute;
  top: calc(var(--menubar-h) + 18px);
  left: 28px;
  width: 336px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  z-index: 1;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}

.widget-row {
  display: flex;
  gap: 16px;
}

/* The stack is about six hundred pixels tall. On a short desktop it would run
   through the caption and out of the screen, so it sheds its lowest tile rather
   than overflowing — a shorter stack still looks deliberate, half a tile hanging
   off the bottom does not. */
@media (max-height: 720px) {
  .widget-stack .widget-posts { display: none; }
}

@media (max-height: 470px) {
  .widget-stack .widget-row { display: none; }
}

.widget {
  position: relative;
  border-radius: 16px;
  overflow: hidden;
  background: var(--menu-bg);
  -webkit-backdrop-filter: saturate(180%) blur(30px);
  backdrop-filter: saturate(180%) blur(30px);
  box-shadow:
    0 0 0 0.5px var(--hairline-strong),
    0 8px 24px rgba(0, 0, 0, 0.18);
}

.widget-label {
  position: absolute;
  top: 10px;
  left: 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ink-2);
  z-index: 2;
}


/* Weather */

.widget-weather {
  flex: 1;
  aspect-ratio: 1;
  padding: 32px 12px 10px;
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
}

.weather-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}

/* The home row is marked, not highlighted: a quiet word, not a colour change. */
.weather-home {
  margin-left: 6px;
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(127, 127, 132, 0.22);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-2);
  vertical-align: 1px;
}

.weather-city {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.weather-value {
  display: flex;
  align-items: center;
  gap: 5px;
  flex: none;
}

.weather-glyph { display: flex; color: var(--ink-2); }
.weather-glyph svg { display: block; }

.weather-temp {
  font-size: 14px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

/* Location */

.widget-location {
  flex: 1;
  aspect-ratio: 1;
}

.widget-map {
  position: absolute;
  inset: 0;
}

.widget-map svg {
  width: 100%;
  height: 100%;
  display: block;
}

.widget-label-map {
  color: rgba(60, 64, 72, 0.75);
}

.widget-pin {
  position: absolute;
  left: 50%;
  top: 46%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* The pin carries the portrait now, so it keeps the ring and drops the fill:
   a background shorthand here would paint straight over the sprite. */
.widget-pin-avatar {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: #2f7ad8;
  box-shadow:
    0 0 0 2.5px #ffffff,
    0 3px 8px rgba(0, 0, 0, 0.3);
}

.widget-pin-tail {
  width: 8px;
  height: 8px;
  margin-top: -5px;
  background: #ffffff;
  transform: rotate(45deg);
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
}

.widget-city {
  position: absolute;
  left: 12px;
  bottom: 9px;
  font-size: 13px;
  font-weight: 700;
  color: #3c4048;
}

/* ---------- Mascot ---------- */

.mascot {
  position: fixed;
  left: 0;
  top: 0;
  /* On the desktop floor: over the wallpaper and the widgets, under every
     window and the dock. Nothing walks across an open window. Standing on
     the dock, or being carried, lifts him above both. */
  z-index: 5;
  cursor: grab;
  touch-action: none;
  will-change: transform;
}

.mascot:active { cursor: grabbing; }

/* Three screen pixels per sprite pixel: a whole multiple, so the grid stays
   hard. The engine's SCALE is the same number. */
.mascot.is-elevated { z-index: 9500; }

/* The only layer that carries a flip. Nothing else in the mascot may. */
.mascot-sprite {
  display: block;
  transform-origin: center;
}

.mascot canvas {
  display: block;
  width: 42px;
  height: 81px;
  image-rendering: pixelated;
}

/* A pixel speech bubble: hard edges on the sprite's own grid, a square tail,
   and no fade. It appears the instant he is bothered and is gone again in a
   second and a half. */
.mascot-bubble {
  position: absolute;
  bottom: calc(100% + 12px);
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 220px;
  padding: 7px 10px;
  background: #f2efe6;
  color: #1d1d1f;
  border: 3px solid #24242a;
  border-radius: 0;
  image-rendering: pixelated;
  display: none;
  pointer-events: none;
  /* Upright and left-to-right whatever the sprite is doing. */
  text-align: left;
  direction: ltr;
}

/* The tail: two stacked blocks, so it steps rather than tapers. */
.mascot-bubble::after,
.mascot-bubble::before {
  content: "";
  position: absolute;
  left: 18px;
  background: #f2efe6;
  border: 3px solid #24242a;
}

.mascot-bubble::before {
  bottom: -9px;
  width: 9px;
  height: 6px;
  border-top: 0;
}

.mascot-bubble::after {
  bottom: -15px;
  left: 21px;
  width: 3px;
  height: 6px;
  border-top: 0;
}

.mascot-bubble.is-flipped::before { left: auto; right: 18px; }
.mascot-bubble.is-flipped::after { left: auto; right: 21px; }

.mascot-bubble.is-visible { display: block; }

.mascot-bubble-text {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1.35;
}

/* ---------- Posts ---------- */

/* X's surface, not ours: near-black, their blue, their secondary grey. The tile
   opts back into pointer events because the stack above it is decorative. */
.widget-posts {
  --x-secondary: #71767b;
  --x-link: #1d9bf0;
  width: 100%;
  /* Matches the weather tile's inner rhythm, so the stack reads as one set. */
  padding: 14px 14px 16px;
  background: #000;
  color: #fff;
  pointer-events: auto;
}

.x-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  font-size: 14px;
  line-height: 1.4;
}

/* Nothing inside may push the card wider than the tile it sits in. */
.x-card > * { min-width: 0; }

.x-head {
  display: flex;
  align-items: center;
  gap: 14px;
  color: inherit;
  text-decoration: none;
}

/* The fill is set as a colour, not the shorthand: the shorthand would clear the
   sprite the portrait paints with. */
/* 64 rather than 96: a whole multiple of the 48 grid is not available between
   them, and at 96 the head alone was taller than the three lines beside it. */
.x-avatar {
  flex: none;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background-color: #16181c;
}

/* The stand-in is the site's own mark, sized and shaped like the picture it is
   waiting for, so nothing about it reads as missing. */


.x-identity { min-width: 0; }

.x-name-row {
  display: flex;
  align-items: center;
  gap: 4px;
}

.x-name {
  font-weight: 700;
  color: #fff;
}

.x-verified {
  display: block;
  width: 17px;
  height: 17px;
  color: var(--x-link);
}

.x-verified svg,
.x-meta-glyph svg {
  width: 100%;
  height: 100%;
  display: block;
  fill: currentColor;
}

.x-handle {
  display: block;
  color: var(--x-secondary);
  font-size: 13.5px;
}

.x-bio {
  margin: 0;
  color: #e7e9ea;
  font-size: 13.5px;
}

.x-link {
  color: var(--x-link);
  text-decoration: none;
}

.x-link:hover { text-decoration: underline; }

.x-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  color: var(--x-secondary);
  font-size: 13px;
}

.x-meta-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
}

.x-meta-glyph {
  flex: none;
  width: 15px;
  height: 15px;
  color: var(--x-secondary);
}

.x-post-link {
  display: block;
  color: inherit;
  text-decoration: none;
}

.x-post {
  padding-top: 10px;
  border-top: 1px solid #2f3336;
}

.x-post-text {
  margin: 0;
  color: #e7e9ea;
  font-size: 13.5px;
  white-space: pre-wrap;
}

.x-post-time {
  display: block;
  margin-top: 4px;
  color: var(--x-secondary);
  font-size: 12.5px;
}

.x-read {
  color: var(--x-link);
  font-size: 13.5px;
  text-decoration: none;
}

.x-read:hover { text-decoration: underline; }

/* The bio is never cut. A tile that has more to say is a taller tile — trimming
   the one piece of writing on it to keep a rectangle would be the wrong trade. */
.x-card.is-compact .x-bio {
  font-size: 13px;
  line-height: 1.45;
}


/* One prop, only while it is in use, drawn where he is standing. The desktop is
   empty the rest of the time. */
/* The golf ball. Three pixels of white, which is all a ball needs to be. */
.mascot-ball {
  position: fixed;
  left: 0;
  top: 0;
  width: 6px;
  height: 6px;
  background: #f4f6fb;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
  z-index: 6;
  display: none;
  pointer-events: none;
}

.mascot-prop {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 4;
  display: none;
  pointer-events: none;
  image-rendering: pixelated;
}

/* Sweat: one pixel of the sprite's own scale, thrown off the head during the
   circuit. Light enough to read against the wallpaper at any hour. */
.mascot-sweat {
  position: fixed;
  left: 0;
  top: 0;
  width: 3px;
  height: 3px;
  background: #cfe6ff;
  box-shadow: 0 0 0 1px rgba(20, 30, 50, 0.35);
  z-index: 6;
  display: none;
  pointer-events: none;
}
