/* style.css: structure of the mirror and its widgets. All looks come from tokens.css (and a theme). */

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

/* Fullscreen */
body {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-display);
  font-size: var(--size-base);
}

[hidden] {
  display: none !important;
}

/* ---------- Layout: three columns, one per glass pane ---------- */

/* Columns follow the measured glass panes (js/core/calibration.js sets --mirror-columns:
 * hidden edge, pane, post, pane, post, pane, hidden edge). Nothing is placed behind a post. */
#main-body {
  display: grid;
  grid-template-columns: var(--mirror-columns, 0 1fr 0 1fr 0 1fr 0);
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  padding-top: var(--mirror-top, 0);
  padding-bottom: var(--mirror-bottom, 0);
}

.mirror {
  min-width: 0;
  min-height: 0;
  padding: var(--column-padding);
  display: flex;
  flex-direction: column;
  align-items: center;
  opacity: 0;
  animation: fadeInMirror var(--fade-in) ease forwards;
}

@keyframes fadeInMirror {
  to {
    opacity: 1;
  }
}

#left-mirror {
  grid-column: 2;
  text-align: left;
  align-items: flex-start;
}

#center-mirror {
  grid-column: 4;
  text-align: center;
  align-items: center;
}

#right-mirror {
  grid-column: 6;
  text-align: right;
  align-items: flex-end;
}

/* Long appointment lists fade out at the bottom of the left pane. */
.fade-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 400px;
  height: 500px;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom, transparent 0%, transparent 75%, var(--color-bg) 100%);
}

/* Data that couldn't be refreshed for a while: keep showing it, dimmed. */
.stale {
  opacity: 0.4;
}

/* ---------- Clock ---------- */

#datetime {
  position: relative;
  top: -30px;
  font-size: var(--size-clock-text);
  font-variant: var(--font-variant-display);
  font-family: var(--font-display);
  text-align: left;
  color: var(--color-text);
  width: 100%;
  z-index: 2;
  margin-bottom: 20px;
}

.date {
  font-size: var(--size-date);
}

.time {
  font-size: var(--size-clock);
  vertical-align: middle;
}

#s {
  font-size: var(--size-clock-seconds);
  vertical-align: 2px;
}

/* ---------- Reminders ---------- */

#reminders {
  font-size: var(--size-reminders);
  font-variant: var(--font-variant-display);
  font-family: var(--font-display);
  width: 80%;
  margin-bottom: 20px;
}

.reminder {
  background: var(--reminder-fill);
  background-size: 400% 400%;
  animation: reminder-shine 8s ease infinite;
  color: var(--reminder-text);
  padding: 8px;
  margin-bottom: 8px;
  border-radius: var(--reminder-radius);
  font-size: var(--size-reminder);
  width: 100%;
  box-shadow: var(--reminder-shadow);
}

@keyframes reminder-shine {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

/* ---------- Appointments ---------- */

#appointments-container {
  position: relative;
  margin-top: var(--appointments-gap);
  width: var(--panel-width);
  color: var(--color-text);
  font-family: var(--font-data);
  border: none;
  padding: 10px;
  font-size: var(--size-appointments);
}

.date-header {
  font-weight: bold;
  margin-top: 15px;
  margin-bottom: 8px;
  border-bottom: 1px solid var(--color-rule);
  padding-bottom: 4px;
  font-size: var(--size-appointment-header);
}

.appointment-card {
  border-left: 5px solid var(--color-card-edge); /* tinted with the owner's colour */
  margin: 3px 0;
  padding: var(--card-padding);
  background: var(--color-card);
  border-radius: var(--card-radius);
  width: 100%;
}

.appointment-user {
  display: inline-block;
  font-weight: bold;
  margin-right: 10px;
  font-size: var(--size-appointment-owner);
}

.appointment-time,
.appointment-location,
.appointment-attendees,
.appointment-description {
  display: block;
  font-size: var(--size-appointments);
  margin: 2px 0;
}

.appointment-description {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

.appointment-highlight {
  transform: scale(1.05);
  background: linear-gradient(90deg, var(--color-highlight-wash) 0%, rgba(255, 255, 255, 0.05) 100%);
  border-radius: 8px;
  box-shadow: 0 0 10px var(--color-highlight);
  transition: all 0.3s ease;
}

.appointment-faded {
  opacity: 0.6;
  transition: opacity 0.5s ease;
}

/* ---------- World map ---------- */

#worldmap .worldmap-img {
  display: block;
  width: 100%;
}

.worldmap-link {
  display: block;
  cursor: pointer;
}

/* ---------- Photo of the day ---------- */

#photo {
  margin: var(--photo-margin) 0;
  display: flex;
  justify-content: center;
}

.photo-frame {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

#photo-img {
  display: block;
  max-width: var(--photo-max-width);
  max-height: var(--photo-max-height);
  object-fit: contain;
  -webkit-mask-image: var(--photo-mask);
  mask-image: var(--photo-mask);
  filter: var(--photo-filter);
  opacity: 0;
  transition: opacity var(--photo-fade) ease;
}

#photo-img.visible {
  opacity: 1;
}

#photo-caption {
  font-family: var(--font-display);
  font-variant: var(--font-variant-display);
  font-size: var(--size-photo-caption);
  color: var(--color-text-muted);
  margin-top: 4px;
}

/* ---------- Market ---------- */

#market-container {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: auto;
  margin-bottom: 20px;
}

.market-box {
  width: var(--panel-width);
}

#market-status .market-closed-banner {
  width: 100%;
  background-color: var(--color-banner);
  color: var(--color-text-muted);
  text-align: center;
  font-size: var(--size-banner);
  padding: 4px 0;
  border-radius: 4px;
}

#market-table {
  width: 100%;
  /* Columns are chosen in admin, so widths follow the content; numbers never wrap. */
  table-layout: auto;
  border-collapse: collapse;
  font-size: var(--size-market);
  font-family: var(--font-data);
  border-radius: 8px;
}

#market-table th {
  padding: 2px var(--market-cell-gap);
  vertical-align: middle;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.market-symbol {
  text-align: left;
  font-weight: bold;
  width: 100%; /* takes the slack, so the numbers sit together on the right */
}

.market-correction {
  text-align: right;
  font-weight: bold;
}

.market-price {
  text-align: right;
}

.market-small {
  text-align: right;
  font-size: var(--size-market-small);
  color: var(--color-text-muted);
}

/* 52-week range: a thin line from the year's low to its high, with a dot at today's price. */
.market-range {
  width: var(--market-range-width);
  min-width: var(--market-range-width);
}

.range-track {
  position: relative;
  display: block;
  height: 2px;
  margin: 0 5px;
  background: var(--market-range-track);
}

.range-dot {
  position: absolute;
  top: 50%;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--color-text);
  transform: translate(-50%, -50%);
}

.range-dot-high {
  background: var(--color-up);
}

.range-dot-low {
  background: var(--color-down);
}

.market-color-green {
  color: var(--color-up);
}

.market-color-red {
  color: var(--color-down);
}

/* ---------- Weather ---------- */

#weather {
  position: relative;
  font-size: var(--size-weather);
  font-variant: var(--font-variant-display);
  font-family: var(--font-display);
  text-align: right;
}

#weather-now-temp {
  font-size: var(--size-temp);
}

#weather-forecast {
  font-size: var(--size-forecast);
  margin-top: 20px;
}

.weather-ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

.weather-li {
  padding: 5px 0;
}

/* ---------- Overlays: greeting, who's here, connection status ---------- */

#greeting {
  position: absolute;
  top: 40%;
  width: 100%;
  text-align: center;
  font-size: var(--size-greeting);
  font-weight: bold;
  opacity: 0;
  z-index: 10;
}

#identity-indicator {
  position: absolute;
  bottom: 20px;
  right: 20px;
  font-size: var(--size-indicator);
  font-weight: 500;
  color: var(--color-text);
  opacity: 0.6;
  text-align: right;
}

.status-dot {
  position: fixed;
  bottom: 10px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.5s ease;
  z-index: 1000;
}

.status-dot.visible {
  opacity: 1;
}

/* Face tracker not connected (bottom right). */
#connection-status {
  right: 10px;
  background-color: var(--color-alert);
}

/* API/sign-in trouble: data on screen may be old (bottom left). */
#data-status {
  left: 10px;
  background-color: var(--color-warning);
}

/* ---------- Calibration (admin → Calibrate, or ?posts=true) ---------- */

#calibration {
  position: fixed;
  inset: 0;
  z-index: 3000;
  pointer-events: none;
}

.cal-post,
.cal-edge {
  position: absolute;
}

.cal-post {
  top: 0;
  bottom: 0;
  background: var(--calibration-post);
}

.cal-edge {
  background: var(--calibration-edge);
}

.cal-edge-left { top: 0; bottom: 0; left: 0; }
.cal-edge-right { top: 0; bottom: 0; right: 0; }
.cal-edge-top { left: 0; right: 0; top: 0; }
.cal-edge-bottom { left: 0; right: 0; bottom: 0; }

/* Preview: show what the wood and frame cover without hiding the content underneath. */
#calibration.preview .cal-post,
#calibration.preview .cal-edge {
  opacity: 0.35;
  background: repeating-linear-gradient(45deg, var(--calibration-post) 0 6px, transparent 6px 12px);
  outline: 1px solid var(--calibration-post);
}

#calibration.preview .cal-edge {
  background: repeating-linear-gradient(45deg, var(--calibration-edge) 0 6px, transparent 6px 12px);
  outline-color: var(--calibration-edge);
}

/* Calibrating: everything else dims so the bars are the only bright thing. */
#calibration.calibrating {
  background: rgba(0, 0, 0, 0.6);
}

.cal-ruler {
  position: absolute;
  color: #fff;
  font: 11px/1 monospace;
}

.cal-ruler-x {
  left: 0;
  right: 0;
  top: 50%;
  height: 14px;
  background: repeating-linear-gradient(to right, #fff 0 1px, transparent 1px 10px);
}

.cal-ruler-y {
  top: 0;
  bottom: 0;
  left: 50%;
  width: 14px;
  background: repeating-linear-gradient(to bottom, #fff 0 1px, transparent 1px 10px);
}

.cal-ruler-label {
  position: absolute;
  background: #000;
  padding: 1px 2px;
}

.cal-ruler-x .cal-ruler-label { top: 16px; transform: translateX(-50%); }
.cal-ruler-y .cal-ruler-label { left: 16px; transform: translateY(-50%); }

#cal-readout {
  position: absolute;
  left: 50%;
  top: 12%;
  z-index: 1; /* above the rulers */
  transform: translateX(-50%);
  max-width: 30%;
  text-align: center;
  font: 14px/1.4 monospace;
  color: #fff;
  background: #000;
  padding: 6px 10px;
}

#cal-readout:empty {
  display: none;
}

/* ---------- Voice assistant (centre pane) ---------- */

#center-mirror {
  position: relative;
}

/* While it's talking, everything else in the pane steps back. */
#center-mirror > :not(#assistant) {
  transition: opacity 1s ease;
}

#center-mirror.assistant-active > :not(#assistant) {
  opacity: 0;
}

.assistant {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: 0 24px;
  opacity: 0;
  transition: opacity 1.2s ease;
}

.assistant.visible {
  opacity: 1;
}

.assistant-avatar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.assistant-heard {
  font-family: var(--font-display);
  font-size: var(--size-assistant-heard);
  color: var(--color-text-muted);
  font-style: italic;
  max-width: 100%;
}

.assistant-reply {
  font-family: var(--font-display);
  font-size: var(--size-assistant-reply);
  color: var(--color-text);
  max-width: 100%;
  line-height: 1.3;
}

.assistant-heard:empty,
.assistant-reply:empty {
  display: none;
}

/* Daytime: a soft colour ring that breathes, spins up while thinking and pulses while talking. */
.assistant-face {
  display: none;
}

.assistant-ring {
  width: var(--assistant-ring-size);
  height: var(--assistant-ring-size);
  border-radius: 50%;
  background: conic-gradient(var(--assistant-ring-colors));
  -webkit-mask: radial-gradient(circle, transparent 56%, #000 58%, #000 70%, transparent 72%);
  mask: radial-gradient(circle, transparent 56%, #000 58%, #000 70%, transparent 72%);
  filter: blur(1px) saturate(1.2);
  animation: ring-spin 8s linear infinite, ring-breathe 3s ease-in-out infinite;
}

.assistant[data-state="listening"] .assistant-ring {
  animation: ring-spin 4s linear infinite, ring-breathe 1.2s ease-in-out infinite;
}

.assistant[data-state="thinking"] .assistant-ring {
  animation: ring-spin 1.2s linear infinite, ring-breathe 3s ease-in-out infinite;
}

.assistant[data-state="speaking"] .assistant-ring {
  animation: ring-spin 6s linear infinite, ring-talk 0.32s ease-in-out infinite alternate;
}

@keyframes ring-spin {
  to { transform: rotate(360deg); }
}

@keyframes ring-breathe {
  0%, 100% { scale: 0.92; opacity: 0.75; }
  50% { scale: 1.04; opacity: 1; }
}

@keyframes ring-talk {
  from { scale: 0.97; }
  to { scale: 1.07; }
}

/* ---------- Timers (right pane, under the weather) ---------- */

#timers {
  margin-top: 24px;
  font-family: var(--font-display);
  font-size: var(--size-timer);
  text-align: right;
}

.timer {
  display: flex;
  justify-content: flex-end;
  gap: 14px;
  padding: 3px 0;
}

.timer-label {
  color: var(--color-text-muted);
  font-variant: var(--font-variant-display);
}

.timer-time {
  font-variant-numeric: tabular-nums;
  min-width: 4.2em;
}

.timer-done .timer-time {
  color: var(--color-timer-done);
  animation: timer-blink 1s steps(2, start) infinite;
}

@keyframes timer-blink {
  to { visibility: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .assistant-ring,
  .timer-done .timer-time {
    animation: none !important;
  }
}
