/* =========================================================================
   Screenly RSS Reader — "The Wire"
   A syndication/teletype identity for signage. RSS is the wire service; a sign
   is the transmission board. Bricolage Grotesque headlines over a slate-teal
   ink, Space Mono for the wire rail / datelines / QR stamp, RSS amber as the one
   accent. Two modes share a top rail: a big photo story (image feeds) and a
   multi-item list (text feeds). The rail's position counter (NN/NN) and the
   transmission line that fills over each interval encode the rotation.
   Layout is fluid (one clamp root, vw+vh) so it holds 480p -> 4K, both
   orientations; the per-item fit is finished in main.ts.
   ========================================================================= */

@font-face {
  font-family: "Bricolage Grotesque";
  font-weight: 200 800;
  font-style: normal;
  font-optical-sizing: auto;
  font-display: swap;
  src: url("/static/fonts/bricolage-grotesque-latin-standard-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Hanken Grotesk";
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  src: url("/static/fonts/hanken-grotesk-latin-wght-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Mono";
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  src: url("/static/fonts/space-mono-latin-400-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Space Mono";
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  src: url("/static/fonts/space-mono-latin-700-normal.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --font-display: "Bricolage Grotesque", "Hanken Grotesk", system-ui, sans-serif;
  --font-body: "Hanken Grotesk", system-ui, -apple-system, sans-serif;
  --font-mono: "Space Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --ink: #0c1416;
  --ink-rail: #0a1113;
  --paper: #eef2f1;
  --paper-dim: #9aa6ad;
  --paper-faint: rgb(238 242 241 / 0.5);
  --wire: #f58a1f;
  --hairline: rgb(238 242 241 / 0.12);

  /* One fluid root size — symmetric across orientation (vw + vh). */
  --root: clamp(15px, 0.58vw + 0.58vh, 44px);

  /* Set per item by main.ts. */
  --title-scale: 1;
  --rotate-ms: 12000ms;
}

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

html,
body {
  block-size: 100%;
}

html {
  font-size: var(--root);
}

body {
  min-block-size: 100%;
  color: var(--paper);
  background-color: var(--ink);
  font-family: var(--font-body);
  line-height: 1.3;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow: hidden;
}

::selection {
  background: var(--wire);
  color: #11130f;
}

/* =========================================================================
   Stage — rail on top, content below (both modes share the rail)
   ========================================================================= */
.stage {
  position: relative;
  inline-size: 100vw;
  block-size: 100svh;
  overflow: hidden;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}

/* ---- Wire rail (masthead) ------------------------------------------------- */
.rail {
  grid-row: 1;
  position: relative;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: clamp(0.55rem, 1.4vmin, 1.4rem) clamp(0.9rem, 2.6vmin, 2.8rem);
  background: var(--ink-rail);
  border-block-end: 1px solid var(--hairline);
  font-family: var(--font-mono);
  font-size: clamp(0.62rem, 0.5vw + 0.4vh, 1.05rem);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.rail__mark {
  flex: none;
  inline-size: 1.4em;
  block-size: 1.4em;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  /* RSS glyph in wire amber. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Crect width='24' height='24' rx='5' fill='%23f58a1f'/%3E%3Ccircle cx='7' cy='17' r='2.2' fill='%23111'/%3E%3Cpath d='M5 11.2a7.8 7.8 0 0 1 7.8 7.8H10A5 5 0 0 0 5 14z' fill='%23111'/%3E%3Cpath d='M5 6.4A12.6 12.6 0 0 1 17.6 19H15A10 10 0 0 0 5 9z' fill='%23111'/%3E%3C/svg%3E");
}
.rail__source {
  color: var(--paper);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rail__pos {
  margin-inline-start: auto;
  color: var(--wire);
  font-weight: 700;
  white-space: nowrap;
}
.rail__brand {
  flex: none;
  display: flex;
  align-items: center;
  padding-inline-start: clamp(0.7rem, 2vmin, 1.6rem);
  margin-inline-start: clamp(0.7rem, 2vmin, 1.6rem);
  border-inline-start: 1px solid var(--hairline);
  opacity: 0.85;
}
.rail__brand img {
  block-size: clamp(0.7rem, 1vmin + 0.5rem, 1.4rem);
  inline-size: auto;
  display: block;
}
/* Transmission line: a track on the rail's bottom edge that fills amber over
   each rotation interval (set in motion below). */
.rail__line {
  position: absolute;
  inset-inline: 0;
  inset-block-end: -1px;
  block-size: 2px;
  background: transparent;
  overflow: hidden;
}
.rail__fill {
  display: block;
  block-size: 100%;
  inline-size: 0;
  background: var(--wire);
}

/* =========================================================================
   Story mode — one photo story at a time
   ========================================================================= */
.story {
  grid-row: 2;
  position: relative;
  overflow: hidden;
}

.story__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.story__img {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
}
.story__img--back {
  background-size: cover;
  filter: blur(2.2rem) brightness(0.5) saturate(1.1);
  /* Overscan so the blur's faded edges stay off-screen (no soft gradient in the
     letterbox). The entrance animation must not reset this scale. */
  transform: scale(1.18);
}
.story__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    0deg,
    rgb(8 12 14 / 0.95) 0%,
    rgb(8 12 14 / 0.85) 20%,
    rgb(8 12 14 / 0.35) 44%,
    rgb(8 12 14 / 0) 66%
  );
}

/* Text band — a capped, overflow-hidden box main.ts fits content into. The
   right gutter reserves room for the QR so the summary never runs under it. */
.story__panel {
  position: absolute;
  z-index: 2;
  inset-inline: 0;
  inset-block-end: 0;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: clamp(1.1rem, 3vmin, 3.4rem);
  padding-inline-end: clamp(6.5rem, 17vmin, 15rem);
  max-block-size: 50svh;
  overflow: hidden;
}

.story__kicker {
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  font-family: var(--font-mono);
  font-size: clamp(0.62rem, 0.5vw + 0.35vh, 1.05rem);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.story__source {
  color: var(--wire);
  font-weight: 700;
}
.story__time {
  color: var(--paper-faint);
}

.story__title {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-wrap: balance;
  font-size: calc(clamp(1.9rem, 4vw + 1.5vh, 5.4rem) * var(--title-scale));
}
.story__summary {
  color: var(--paper-dim);
  font-size: clamp(0.95rem, 0.85vw + 0.6vh, 1.55rem);
  line-height: 1.34;
  text-wrap: pretty;
  max-inline-size: 46ch;
}

/* ---- Text-only story (image-less item): centered, no media ---------------- */
.stage[data-mode="text"] .story {
  display: grid;
  place-items: center;
}
.stage[data-mode="text"] .story__media,
.stage[data-mode="text"] .story__scrim {
  display: none;
}
.stage[data-mode="text"] .story__panel {
  position: relative;
  inline-size: min(92%, 36rem);
  max-block-size: 80svh;
  padding-inline: 0;
  text-align: center;
  align-items: center;
}
.stage[data-mode="text"] .story__kicker {
  justify-content: center;
}
.stage[data-mode="text"] .story__title {
  font-size: calc(clamp(2.2rem, 5vw + 2vh, 7rem) * var(--title-scale));
}
.stage[data-mode="text"] .story__summary {
  font-size: clamp(1rem, 1vw + 0.7vh, 1.7rem);
}

@media (orientation: portrait) {
  .story__panel {
    max-block-size: 58svh;
  }
}

/* ---- QR stamp (story) ----------------------------------------------------- */
.qr {
  position: absolute;
  z-index: 3;
  inset-block-end: clamp(1.1rem, 3vmin, 3.4rem);
  inset-inline-end: clamp(1.1rem, 3vmin, 3.4rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.55rem;
  inline-size: clamp(4.6rem, 10vmin, 9rem);
}
.qr[hidden] {
  display: none;
}
.qr__frame {
  position: relative;
  inline-size: 100%;
  padding: clamp(0.3rem, 0.8vmin, 0.7rem);
  background: #fff;
  border-radius: 2px;
}
/* Amber corner brackets — a wire-service stamp around the code. */
.qr__frame::before,
.qr__frame::after {
  content: "";
  position: absolute;
  inline-size: 0.85rem;
  block-size: 0.85rem;
  border: 2px solid var(--wire);
}
.qr__frame::before {
  inset-block-start: -5px;
  inset-inline-start: -5px;
  border-inline-end: 0;
  border-block-end: 0;
}
.qr__frame::after {
  inset-block-end: -5px;
  inset-inline-end: -5px;
  border-inline-start: 0;
  border-block-start: 0;
}
.qr__code svg {
  display: block;
  inline-size: 100%;
  block-size: auto;
}
.qr__label {
  font-family: var(--font-mono);
  font-size: clamp(0.55rem, 0.7vmin + 0.28rem, 0.92rem);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--paper-dim);
  text-shadow: 0 1px 4px rgb(0 0 0 / 0.7);
  text-align: center;
  white-space: nowrap;
}

/* =========================================================================
   List mode — several short stories per page (text feeds), each with a QR
   ========================================================================= */
.list {
  grid-row: 2;
  display: none;
  flex-direction: column;
  padding: clamp(1.2rem, 3.4vmin, 4rem) clamp(1.2rem, 3.4vmin, 4.5rem);
  overflow: hidden;
}
.list__items {
  flex: 1;
  min-block-size: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}
.list__item {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vmin, 2.6rem);
  padding-block: clamp(0.6rem, 1.7vmin, 1.5rem);
  border-block-start: 1px solid var(--hairline);
}
.list__item:first-child {
  border-block-start: 0;
  padding-block-start: 0;
}
.list__body {
  flex: 1;
  min-inline-size: 0;
}
.list__title {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.015em;
  text-wrap: balance;
  font-size: clamp(1.15rem, 1.5vw + 1vh, 2.8rem);
}
.list__sum {
  margin-block-start: 0.25rem;
  color: var(--paper-dim);
  font-size: clamp(0.85rem, 0.7vw + 0.5vh, 1.3rem);
  line-height: 1.3;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.list__time {
  display: block;
  margin-block-start: 0.35rem;
  font-family: var(--font-mono);
  font-size: clamp(0.6rem, 0.45vw + 0.3vh, 0.95rem);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper-faint);
}
.list__qr {
  flex: none;
  inline-size: clamp(2.6rem, 5.5vmin, 5rem);
  padding: clamp(0.2rem, 0.5vmin, 0.45rem);
  background: #fff;
  border-radius: 2px;
}
.list__qr svg {
  display: block;
  inline-size: 100%;
  block-size: auto;
}

/* =========================================================================
   Mode visibility + state gating
   ========================================================================= */
.stage[data-mode="list"] .story {
  display: none;
}
.stage[data-mode="list"] .list {
  display: flex;
}

.status {
  grid-row: 2;
  display: none;
  place-content: center;
  text-align: center;
  padding: 2rem;
  font-family: var(--font-mono);
  font-size: clamp(0.9rem, 1vw + 0.7vh, 1.6rem);
  letter-spacing: 0.06em;
  color: var(--paper-faint);
}

.stage[data-state="loading"] .story,
.stage[data-state="empty"] .story,
.stage[data-state="error"] .story,
.stage[data-state="loading"] .list,
.stage[data-state="empty"] .list,
.stage[data-state="error"] .list {
  visibility: hidden;
}
.stage[data-state="loading"] .status,
.stage[data-state="empty"] .status,
.stage[data-state="error"] .status {
  display: grid;
}
.stage[data-state="ready"] .status {
  display: none;
}

/* =========================================================================
   Motion — transmission line + one entrance per item (reduced-motion safe)
   ========================================================================= */
@media (prefers-reduced-motion: no-preference) {
  .stage.is-in .rail__fill {
    animation: wire-fill var(--rotate-ms) linear both;
  }
  .stage.is-in .story__img {
    animation: media-in 900ms ease both;
  }
  /* Back layer fades only — never animate its transform, or it would drop the
     overscan scale and leave a soft gradient in the letterbox. */
  .stage.is-in .story__img--back {
    animation: fade-in 900ms ease both;
  }
  .stage.is-in .story__kicker {
    animation: rise-in 600ms ease both;
  }
  .stage.is-in .story__title {
    animation: rise-in 700ms ease 60ms both;
  }
  .stage.is-in .story__summary {
    animation: rise-in 700ms ease 140ms both;
  }
  .stage.is-in .qr {
    animation: rise-in 700ms ease 220ms both;
  }
  .stage.is-in .list__items {
    animation: rise-in 700ms ease 80ms both;
  }

  @keyframes wire-fill {
    from {
      inline-size: 0;
    }
    to {
      inline-size: 100%;
    }
  }
  @keyframes media-in {
    from {
      opacity: 0;
      transform: scale(1.04);
    }
    to {
      opacity: 1;
      transform: scale(1);
    }
  }
  @keyframes fade-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
  @keyframes rise-in {
    from {
      opacity: 0;
      transform: translateY(0.6rem);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
}
