/* Modernist — ported tokens + kiosk base. Source of truth: the synced
   design system styles.css (projectId af5a3944…). Flat, Archivo, zero radius. */
@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@400;600;800&display=swap');

:root {
  --color-bg: #f3f2f2;
  --color-surface: #eae9e9;
  --color-text: #201e1d;
  --color-accent: #ec3013;
  --radius-md: 0px;
  /* Sky-arc palette: the sun is a warm Modernist yellow (on darker cards), a deeper
     amber/ochre (--sun-light) on light-grey day cards so it stays legible, and the moon
     a pale blue-grey — so the two are unmistakable across every card theme. */
  --sun: #f2b100;
  --sun-light: #c47600;
  --moon: #aebfce;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

/* Preview bezel — the device screen is the fixed frame centred on dark.
   In kiosk fullscreen the frame simply fills the panel.
   touch-action: none locks scrolling/zoom via CSS (no JS touchmove-preventDefault, which on iOS
   suppresses the tap's synthesized click and dropped tab taps). Our swipe reads pointer coords itself. */
html { height: 100%; overflow: hidden; overscroll-behavior: none; touch-action: none; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  background: #101214;
  position: fixed; inset: 0;        /* pin to the viewport — the fixed frame can't be scrolled/dislodged */
  margin: 0; width: 100%; height: 100%;
  overflow: hidden;                /* frame.js scales the fixed frame to fit; no scrollbars */
  overscroll-behavior: none;       /* no rubber-band */
  touch-action: none;              /* scroll-lock via CSS (see html) */
  font-family: 'Archivo', system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.dd-frame {
  width: 1280px;
  height: 720px;
  flex: none;            /* never let the centring flex shrink the fixed device frame */
  position: relative;
  overflow: hidden;
  background: var(--gnd, #cfd8dc);
  color: var(--ink, #1c2427);
  font-family: 'Archivo', system-ui, sans-serif;
  display: flex;
}

/* Themed focus ring — never the default blue. */
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
button::-moz-focus-inner { border: 0; }
button { font-family: inherit; }
/* Every button is tappable across its whole area, with no mobile tap delay or grey
   flash, and a Modernist press response (a quick press-in) so a tap is unmistakable. */
button { touch-action: manipulation; -webkit-tap-highlight-color: transparent; transition: transform 60ms ease, box-shadow 60ms ease; }
/* Press feedback: a clear intermediate COLOUR change (accent-red tint via an inset fill that sits over
   the button's own background but under its label) plus a small press-in. Works on every button
   regardless of its own colours. */
button:active { transform: scale(0.97); box-shadow: inset 0 0 0 100vmax rgba(236, 48, 19, .32); }
@media (prefers-reduced-motion: reduce) { button { transition: box-shadow 60ms ease; } button:active { transform: none; box-shadow: inset 0 0 0 100vmax rgba(236, 48, 19, .32); } }

/* Ambient motion (honour prefers-reduced-motion via the `motion` flag in JS). */
@keyframes drift { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes breathe { 0%, 100% { opacity: .55; } 50% { opacity: .95; } }

/* ── Single-page shell ─────────────────────────────────────────────── */
.dd-frame { flex-direction: column; }   /* shell stacks header + content */
/* Smooth theme/colour changes when cycling locations/shares (all platforms).
   Duration matches the content fade-IN in weather.js/finance.js (the ~700ms
   cross-fade is fade-out ~300 -> theme swap -> fade-in ~400), so the frame
   background and the new content settle in lockstep (no colour flicker). */
.dd-frame { transition: background-color 400ms ease, color 400ms ease; }
#dd-header, .dd-tab, #dd-devclock, #dd-fs { transition: background-color 400ms ease, color 400ms ease, border-color 400ms ease; }
@media (prefers-reduced-motion: reduce) { .dd-frame, #dd-header, .dd-tab, #dd-devclock, #dd-fs { transition: none; } }

#dd-header {
  flex: 0 0 calc(52px * var(--dd-chrome, 1) * var(--dd-phone, 1)); height: calc(52px * var(--dd-chrome, 1) * var(--dd-phone, 1));
  display: flex; align-items: stretch;
  border-bottom: 2px solid var(--rule, #1c242766);
}
#dd-tabs { display: flex; border-right: 2px solid var(--rule, #1c242766); }
.dd-tab {
  /* width + padding scale with the same chrome/phone factors as the font, so the
     label never outgrows its cell and bleeds into the next tab (tablet/phone).
     reTerminal: chrome=1, phone=1 -> 154px/18px, unchanged. */
  width: calc(154px * var(--dd-chrome, 1) * var(--dd-phone, 1)); height: 100%; display: flex; align-items: center; padding: 0 calc(18px * var(--dd-chrome, 1) * var(--dd-phone, 1));
  border: none; cursor: pointer; font-family: inherit; font-weight: 800;
  /* Label font uses --dd-tabf, NOT --dd-phone: the cell stays big (tap target) but on
     the phone the word is sized to sit inside it with margin (1.25, not 1.6), so the
     hero toggle is never clipped. fitTabs() in app.js shrinks further if a device's
     substitute font is still too wide. reTerminal/tablet: tabf=1 -> 18px*chrome, unchanged. */
  font-size: calc(18px * var(--dd-chrome, 1) * var(--dd-tabf, var(--dd-phone, 1)));
  letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; overflow: hidden;
}
.dd-tab + .dd-tab { border-left: 2px solid var(--rule, #1c242766); }
.dd-tab.on { background: var(--ink, #1c2427); color: var(--gnd, #cfd8dc); }
.dd-tab.off { background: transparent; color: var(--mut, #6b7a82); }
/* Phone (FLOOR) only: tabs shrink to fit their label (frees horizontal space for the ribbon), label
   centred vertically + horizontally. The whole button stays the tap target — generous padding, fully
   clickable. reTerminal/tablet (FILL) keep the fixed 154px cells above, so they're pixel-identical. */
.dd-floor .dd-tab { width: auto; padding: 0 calc(14px * var(--dd-phone, 1)); justify-content: center; line-height: 1; }
/* Carousel ribbon (marquee) sits between the toggle and the clock. */
#dd-carousel { flex: 1 1 auto; min-width: 0; overflow: hidden; position: relative; display: flex; align-items: stretch; }
.dd-marquee { display: flex; align-items: stretch; flex: 0 0 auto; white-space: nowrap; animation: dd-marquee 24s linear infinite; will-change: transform; }
.dd-marquee:hover { animation-play-state: paused; }
@keyframes dd-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.dd-cell {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 0 18px;
  border-left: 2px solid var(--rule, #1c242766); white-space: nowrap; height: 100%;
}
@media (prefers-reduced-motion: reduce) { .dd-marquee { animation: none; } }

/* Skeleton shimmer for ribbon cells while their live data is still loading (cold start). */
@keyframes dd-shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
.dd-shimmer {
  display: inline-block; border-radius: 0; opacity: .55;
  background: linear-gradient(90deg, var(--rule, rgba(255,255,255,.14)) 25%, var(--mut, #98a0aa) 50%, var(--rule, rgba(255,255,255,.14)) 75%);
  background-size: 220% 100%; animation: dd-shimmer 1.25s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .dd-shimmer { animation: none; } }

/* Freshness pill: the status dot pulses while a background refresh is in flight ("… ago, refreshing"). */
@keyframes dd-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }
.dd-pulse { animation: dd-pulse 1s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .dd-pulse { animation: none; } }

/* Fullscreen toggle + settings gear (browser tabs only — hidden in kiosk/standalone
   via JS, so the reTerminal header is unchanged). */
#dd-fs, #dd-gear {
  flex: 0 0 calc(60px * var(--dd-chrome, 1)); width: calc(60px * var(--dd-chrome, 1)); height: 100%; padding: 0; border: 0;
  border-left: 2px solid var(--rule, #1c242766);
  background: transparent; color: var(--ink, #f1f2f4); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
#dd-fs svg, #dd-gear svg { width: calc(26px * var(--dd-chrome, 1)); height: calc(26px * var(--dd-chrome, 1)); display: block; }
#dd-fs[hidden], #dd-gear[hidden] { display: none; }

/* Device clock, top-right. position:relative so the build badge can sit in its
   bottom-right corner (absolute) WITHOUT widening the box. */
#dd-devclock {
  flex: 0 0 auto; display: flex; align-items: center; padding: 0 20px 0 16px; position: relative;
  border-left: 2px solid var(--rule, #1c242766);
  font-size: calc(20px * var(--dd-chrome, 1)); font-weight: 800; letter-spacing: .04em; font-variant-numeric: tabular-nums;
}

#dd-content { position: relative; flex: 1 1 auto; min-height: 0; }
.dd-split { position: absolute; inset: 0; display: flex; }

/* Shared-axis transition: the frame background + header cross-fade (root),
   the body slides along X. Direction is set on <html data-vt>. */
#dd-content { view-transition-name: dd-body; }
::view-transition-group(dd-body) { animation-duration: 350ms; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 350ms; }
html[data-vt="forward"]::view-transition-old(dd-body) { animation: 350ms cubic-bezier(.2,.7,.2,1) both dd-slide-out-left; }
html[data-vt="forward"]::view-transition-new(dd-body) { animation: 350ms cubic-bezier(.2,.7,.2,1) both dd-slide-in-right; }
html[data-vt="back"]::view-transition-old(dd-body) { animation: 350ms cubic-bezier(.2,.7,.2,1) both dd-slide-out-right; }
html[data-vt="back"]::view-transition-new(dd-body) { animation: 350ms cubic-bezier(.2,.7,.2,1) both dd-slide-in-left; }
@keyframes dd-slide-out-left { to { transform: translateX(-7%); opacity: 0; } }
@keyframes dd-slide-in-right { from { transform: translateX(7%); opacity: 0; } }
@keyframes dd-slide-out-right { to { transform: translateX(7%); opacity: 0; } }
@keyframes dd-slide-in-left { from { transform: translateX(-7%); opacity: 0; } }

/* ── Lift loader (from Loader.dc.html, 1c · smooth): 4 bars, 4 stages,
   0.4s per stage, 1.6s loop; active bar rises 8px and turns accent. ── */
.dd-loader-wrap { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.dd-loader { display: flex; align-items: flex-end; gap: 8px; height: 16px; }
.dd-liftbar {
  width: 34px; height: 8px; flex: 0 0 34px; background: var(--ink, #1c2427); opacity: .22;
  animation: dd-lift 1.6s ease infinite;
}
@keyframes dd-lift {
  0%    { transform: translateY(0);    background: var(--ink, #1c2427); opacity: .22; }
  12.5% { transform: translateY(-8px); background: var(--acc, #ec3013); opacity: 1; }
  25%   { transform: translateY(0);    background: var(--ink, #1c2427); opacity: .22; }
  100%  { transform: translateY(0);    background: var(--ink, #1c2427); opacity: .22; }
}
@media (prefers-reduced-motion: reduce) {
  .dd-liftbar { animation: none; opacity: .5; }
  ::view-transition-group(dd-body), ::view-transition-old(dd-body), ::view-transition-new(dd-body) { animation: none; }
}
